PDA

View Full Version : QMenu::addAction ownership



tuli
23rd February 2019, 13:21
Hi,

In a widget of mine, I create a contextmenu like this



QMenu menu(this);
QAction* act = menu.addAction("menuaction");
act->setStatusTip("fff");
...


But! I realized the statusTip doesnt work. That's because the QAction needs to be a direct child of the QMainWindow containing the statusBar, as far as I can tell. And indeed, if I add act->setParent(my_main_window), then the statusTip works!


But now I am wondering if I leak the QActions. The documentation says "QMenu takes ownership of the returned QAction." But is this ownership expressed in a qobject-child-parent relationship, or does the menu explicitly delete the action?

Does the QMenu still own the QAction when I call setParent(my_main_window)?

As far as I can tell this is indeed the case.


Second question: Is it possible to add a statusTip to a submenu?



QMenu menu(this);
QMenu* submenu = menu.addMenu("submenue");
QAction* act = submenu->addAction("menuaction");

submenu->setStatusTip("fff"); //doesnt work!
...



It doesnt work, even if I force its parent to my mainwindow (which is not possible bc it messes with the submenues location).

Any way to accomplish this?

anda_skoa
23rd February 2019, 14:45
But is this ownership expressed in a qobject-child-parent relationship, or does the menu explicitly delete the action?


As far as I can tell only by QObject relationship
https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qmenu.cpp.html#_ZN5QMenu9addActionERK7QString

Cheers,
_

tuli
23rd February 2019, 14:56
Hm, that sucks. Am I correct that the setStatusTip indeed only works if the QAction is a direct child of the MainWindow?

That puts me in a difficult position to use statusTips for menus that are dynamically created and need to be generated anew for each menu show.

d_stranz
23rd February 2019, 16:54
You can create QAction instances as children of any QObject (using new QAction( parent )). In that case, they are "owned" by that parent. You can then add the QAction to any QMenu, QToolBar, or other QWidget with ownership remaining with the original parent. In this case, you're calling QWidget::addAction() with the QAction pointer. When you create the QAction, you make the connection between its triggered() signal and whatever slot you want executed, independently of which QWidget you have added it to. Therefore, you can add the same QAction instance to multiple QWidgets (using addAction()) and have the same slot executed.

anda_skoa
23rd February 2019, 16:57
Am I correct that the setStatusTip indeed only works if the QAction is a direct child of the MainWindow?


Looking at the code says that the action always sends a status tip event to its widget or parent, but essentially only the main window reacts to it.

You could try setting the main window as the parent of each action, or you could install an event filter in the QApplication object and forward all status tip events to the main window.

Cheers,
_

tuli
23rd February 2019, 23:52
Thanks. Yes, it seems they have to be direct parents indeed.

In my case the menu is different every time it's invoked, so it doesnt make sense to store actions permanently.
Seems I have to go for a workaround hack, like storing all actions and deleting or reusing them on next menu invokation or something like that.

anda_skoa
24th February 2019, 13:03
I think the easiest way is the event filter approach.

Something like


MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
QApplication::instance()->installEventFilter(this);
}

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
// Status tip sent to any widget other than the main window gets rerouted to "this"
if (event->type() == QEvent::StatusTip && watched != this) {
QMainWindow::event(event);
return true;
}

return QMainWindow::eventFilter(watched, event);
}


Cheers,
_

tuli
24th February 2019, 16:23
Thanks for the sample code, that's probably the best solution. :)

The problem with submenues and tooltips seems to be a longstanding bug btw:

https://bugreports.qt.io/browse/QTBUG-14287?focusedCommentId=307223