Solved Basic file handling with QDirModel and QTreeView
-
AFAICS, you are re-creating every QAction every time you generate your contextual menu. So before you trigger that once, you likely don't have any shortcut for your application.
What is usually done is to create your QAction once in a central place (usually the constructor) and then re-use them as necessary to build menus/contextual menus etc.
-
Thanks for the hint. I did that. I moved the QAction block into the constructor of MainWindow but my shortcuts still do not work. I've been reading the QAction help but I do not see what I am doing differently from the example...
-
Did you took a look at the Application Example ? They show how to create QAction and use them from several places.
-
My shortcuts cannot work because the triggered action is not connect to a slot! I was handling everything in one function and this function could not be entered by the shortcut. So now I am redoing my entire code and define the action, connect it so a slot and handle the action in the slot. But it still does not work! While compiling I get an error:
QMetaObject::connectSlotsByName: No matching signal for on_pDel_triggered()
pDel = new QAction(tr("delete"), this); pDel->setShortcut(QKeySequence(Qt::Key_Delete)); connect(pDel, QAction::triggered, this, MainWindow::on_pDel_triggered);
Why is this just not working?
EDIT:
Apparently on_ is not allowed for a custom slot... I changed the slot name to pDel_triggered() and now the app complies but the shortcut is still not working =( Also if I use the context menu now the slot is called twice. -
The
on_WidgetName_SignalName
pattern is used by theconnectSlotsByName
method to automatically create the connection between the signalSignalName
from the widget namedWidgetName
to that slot. The most common use case is designer based widgets.Can you show the complete code where you setup your action ?
-
@SGaist Thanks a lot for taking so much interest in my problem.
Here is what I currently have. I solved the issue with the signal being emitted twice over the context menu but I am still not getting anywhere with my shortcuts. Currently I am focussing on pDel.MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { isCtrlPressed = false; pCopyPath = ""; isCutAction = false; fileContextMenu = new QMenu(ui->treeView); // Define actions for explorer pOpen = new QAction(QIcon(":/icon/icons/openEnable.png"),tr("open"), this); pRename = new QAction(tr("rename"), this); pRename->setShortcut(QKeySequence(Qt::Key_F2)); pDel = new QAction(tr("delete"), fileContextMenu); pDel->setShortcut(QKeySequence(Qt::Key_Delete)); connect(pDel, SIGNAL(triggered()), this, SLOT(pDel_triggered())); pCopy =new QAction(QIcon(":/icon/icons/copyEnable.png"),tr("©"), this); pCopy->setShortcut(QKeySequence(Qt::ControlModifier + Qt::Key_C)); pCut = new QAction(QIcon(":/icon/icons/cutEnable.png"), tr("cut"), this); pCut->setShortcut(QKeySequence(Qt::ControlModifier + Qt::Key_X)); pPast = new QAction(QIcon(":/icon/icons/pastEnable.png"), tr("past"), this); pAddFolder = new QAction(tr("Create Folder"), this); pAddFile = new QAction(QIcon(":/icon/icons/newEnable.png"),tr("Add new file"), this); fileContextMenu->addAction(pOpen); fileContextMenu->addAction(pRename); fileContextMenu->addSeparator(); fileContextMenu->addAction(pCopy); fileContextMenu->addAction(pCut); fileContextMenu->addAction(pPast); fileContextMenu->addSeparator(); fileContextMenu->addAction(pAddFile); fileContextMenu->addAction(pAddFolder); fileContextMenu->addSeparator(); fileContextMenu->addAction(pDel); [...] dirModel = new QFileSystemModel(this); dirModel->setReadOnly(false); connect(dirModel, SIGNAL(fileRenamed(QString,QString,QString)), this, SLOT(fileRenamed(QString,QString,QString))); ui->treeView->setModel(dirModel); ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->treeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDirContextMenu(QPoint))); } void MainWindow::showDirContextMenu(const QPoint &pos){ QModelIndex index=ui->treeView->indexAt(pos); bool isRoot = false; if(!index.isValid()){ index = dirModel->index(projects[ui->projectSelector->currentText()]); isRoot = true; } bool isDir = dirModel->isDir(index); if(isRoot){ pRename->setEnabled(false); pDel->setEnabled(false); pCopy->setEnabled(false); pCut->setEnabled(false); }else{ pRename->setEnabled(true); pDel->setEnabled(true); pCopy->setEnabled(true); pCut->setEnabled(true); } if(pCopyPath != "" && isDir){ pPast->setEnabled(true); pPast->setStatusTip(tr("Insert")+ ": " + pCopyPath.section("/",-1,-1)); }else{ pPast->setEnabled(false); } QAction* selectedItem = fileContextMenu->exec(ui->treeView->viewport()->mapToGlobal(pos)); if(selectedItem == pOpen){ on_treeView_doubleClicked(index); }else if [...] } void MainWindow::pDel_triggered() { QModelIndex index = ui->treeView->currentIndex(); qDebug() << dirModel->filePath(index); }
Action without a shortcut I plan to handle in the showDirContextMenu function. The other I plan to handle by signal and slots but currently the function pDel_triggered is only entered if I use the context menu. The shortcut is doing nothing.
Last thing I tried was to change the parents for the contectMenu and the actions.
-
hi,
a quick look into the docu, and I found this paragraph:
Once a QAction has been created it should be added to the relevant menu and toolbar, then connected to the slot which will perform the action.
You did not post the
connects
in your code-example, so did you keep to that order, did you mix it up? :-) -
Hi @J-Hilk,
I did connect the action, see above:
pDel = new QAction(tr("delete"), fileContextMenu); pDel->setShortcut(QKeySequence(Qt::Key_Delete)); connect(pDel, SIGNAL(triggered()), this, SLOT(pDel_triggered()));
So I believe I did this correct. The connect works because I see an output when I use the context menu.
-
-
Found the error! =) I got a hint on Stackoverflow. It is not enough to add the action to the menu, you also have to add the action to the widget. In my case the treeView.