tux007 tux007 - 9 days ago 6
C++ Question

identify a trigger of QAction

below I quoted my code. The problem is easy to describe. selectedItem->text is not the right way to differ what action was selected in the menu. How to do it right?

void RView::ShowContextMenu(const QPoint& pos) // this is a slot
{
// for most widgets
QPoint globalPos = statusWidget->mapToGlobal(pos);
// for QAbstractScrollArea and derived classes you would use:
// QPoint globalPos = myWidget->viewport()->mapToGlobal(pos);

QMenu myMenu;
myMenu.addAction("first");
myMenu.addAction("second");

QAction* selectedItem = myMenu.exec(globalPos);
if (selectedItem)
{
if(selectedItem->text == "first")
// do something
if(selectedItem->text == "second")
// do other stuff
}
else
{
// nothing was chosen
}
}

Answer

You should rather compare the QActions directly and either use the comparison of selectedItem as you do in your ifs or better yet connect each action to the desired slot (or lambda if they are one time things localised to this context).

QMenu myMenu;
QAction *action1 = myMenu.addAction("first");
QAction *action2 = myMenu.addAction("second");
connect(action1, &QAction::triggered, [](){/*lambda code here*/});
connect(action2, &QAction::triggered, [](){/*lambda code here*/});
myMenu.exec(statusWidget->mapToGlobal(pos));

EDIT: For Qt4 you would use slots and old connect syntax:

QMenu myMenu;
QAction *action1 = myMenu.addAction("first");
QAction *action2 = myMenu.addAction("second");
connect(action1, SIGNAL(triggered()), this, SLOT(doStuff()));
connect(action1, SIGNAL(triggered()), this, SLOT(doOtherStuff()));
myMenu.exec(statusWidget->mapToGlobal(pos));

For this to work you will need "doStuff" and "doOtherStuff" to be declared as slots in your header taking no arguments (becuase the signal QAction::triggered() have none). The code you want done will go to definitions of these slots:

class RView
{
public slots:
    void doStuff() { /*do stuff*/ }
    void doOtherStuff() { /*do other stuff*/ }
};
Comments