PDA

View Full Version : Right click context menu by sub-classing how to catch the trigger



Tuxedo
20th July 2012, 11:07
Hi all I want to have a context menu on a qlistwidget.
I am using the designer and followed the first example from:

http://www.developer.nokia.com/Community/Wiki/Handling_right_button_clicks_using_Qt

Everything is working fine, the menu pops up. But how can I catch in my MainWindow if the first entry from context menu is clicked or action is triggerd. Or to run a procedure from MainWindow when context menu is clicked.

Any help is appreciated.

wysota
20th July 2012, 11:44
The menu consists of a bunch of actions. When you choose an entry in the menu, the action associated with it will be triggered(). Alternatively QMenu::exec() returns a pointer to the action that was chosen, you can use that as well.

Tuxedo
20th July 2012, 15:28
The menu consists of a bunch of actions. When you choose an entry in the menu, the action associated with it will be triggered().
I tried like this in my MainWidget.cpp but it is not working. I also made actionNew Public and class and header is linked to MainWidget.cpp/.h

QObject::connect(ui->listwidget->actionNew, SIGNAL(triggered()), this, SLOT(showMaximized()));

A normal menu works like a charm but this method mentioned with sub-classing eats my brain I tried so many things I am going crazy.

wysota
20th July 2012, 15:56
Subclassing has nothing to do with this.

Tuxedo
20th July 2012, 21:27
Ok I see. I got it working now by adding actions and a signal. In Mainwindow I connected to the signal. I hope this is the right procedure.

wysota
20th July 2012, 22:13
If I want a context menu on a view, then I usually do something like this (assuming I'm not subclassing the view itself):


listView->installEventFilter(this);

bool Window::eventFilter(QObject *obj, QEvent *e) {
if(obj == listView && e->type == QEvent::ContextMenu) {
showViewContextMenu(static_cast<QContextMenuEvent*>(e)->pos());
}
return ...;
}

... or ...


listView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(listView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showViewContextMenu(QPoint)));

... and then ...


void Window::showViewContextMenu(const QPoint &pt) {
QModelIndex idx = listView->indexAt(pt);
modelIndexForContextMenu = idx; // optional, to let slots know what index is the base for the context menu
QMenu menu;
fillMenuWithActionsDependingOnIndex(&menu, idx);
menu.exec(listView->viewport()->mapToGlobal(pt));
}

assuming I have a bunch of QAction objects with triggered() signals already connected to respective slots I can do:

void Window::fillMenuWithActionsDependingOnIndex(QMenu *menu, const QModelIndex &idx) {
ui->action1->setEnabled(idx.parent().isValid());
ui->action2->setEnabled(idx.column() == 0);
// etc.
menu->addAction(ui->action1);
menu->addAction(ui->action2);
// etc.
}

Everything else works on its own.

Of course that's only one of possible approaches.

By the way, code in the article you linked to is flawed and can cause an application to crash. By some luck it probably doesn't crash but it doesn't make the code valid.

Tuxedo
20th July 2012, 22:50
This with the QModelIndex looks nice I will try it. With your methode you don't need to emit a signal thats good. Thank you for your detailed answer.