QToolbar widget ownership issues
-
I have a toolbar with some custom widgets which I add with addWidget. According to the documentation, this makes the toolbar take ownership of that widget. But my widget is not deleted when I call QToolbar::clear! Instead, it only gets deleted together with the toolbar when I close the application (call stack in my widget's destructor clearly shows that it is indeed caused by QToolbar's destructor). This means that every time I clear my toolbar to reinitialize it from scratch, hoping that the clear would delete it, I am effectively causing a memory leak (until the whole applicatiion closes)... Again, experiments with a breakpoint in widget's destructor confirm that this is the case: if I add 2 widgets, then clear, add 2 new widgets, clear and so on - all these "lost" widgets will be deleted in the end. Sure, I can always delete them myself, but... doesn't that kinda defeat the purpose of "ownership"? ;)
If, instead, I try to re-add the same widget after clear() (know that I know it's still alive), it simply doesn't work. No errors, and QToolbar::addWidget even returns a valid action pointer - it just never shows up on the toolbar anymore. Explicit removeAction before clear doesn't help either, and there's no removeWidget...
Just in case - I am currently using Qt 5.7.0 on Windows 8.1.
So the questions are:
-
What's the point of "taking ownership" if you don't delete owned widgets when they are no longer used, instead expecting the user to keep managing their lifetime manually?
-
Is there any way to prevent QToolbar's ownership of my widgets in the first place? I don't really want to re-create them every time, I just want to occasionally rebuild the actions list!
-
What is the expected "Qt way" to implement dynamic context-dependent rebuilding of the toolbar content, without adding all the possible actions simultaneously and then keeping track of their visibility? Basically, I have a tabbed main form which has a few "common" toolbar commands (undo / redo). Now I want to add a lot more commands for each of the possible tab types (which are independent and very different in content, so they are unlikely to have any more commands in common). I also don't want to create a separate toolbar inside each tab - that would just be a waste of screen space.
-
-
Hi,
From a quick look:
- adding a widget to a QToolBar creates a new QWidgetAction
- that action will delete the widget under two conditions: you set a new widget on it, you delete the action.
Why not make your tabs provide the tool bar and let them hand their visibility base on their state ?
-
Ah, so the toolbar "takes ownership" by making itself the new parent of my widget (I double-checked - it does), but it can also be deleted by QWidgetAction which is NOT its parent?! (and I double-checked to confirm that too) Crazy. What kind of an ownership concept is that...
Well, I've found a kind of a workaround by using setWidget when populating the toolbar for the first time, then remembering returned action and using setAction in later calls. When I tried simply creating a QWidgetAction myself, my widget didn't have correct position on the toolbar. Apparently setWidget handles that too, but setAction doesn't... This approach seems to work, but doesn't look quite good to me yet (and probably won't work if the widget order isn't fixed).
Why not make your tabs provide the tool bar and let them hand their visibility base on their state ?
Not sure I understand correctly. Do you mean that a tab can create a second QToolbar (like I mentioned in the OP), then dock it to the same toolbar block inside the main window? Now that I think about it again, it might work (a bit of a possible misconception on my side) - will have to try that when I next have some free time for my project... Doesn't seem like I'll be able to get a single dynamic toolbar working... :(
-
How did you check that parenting stuff ?
Can you explain what kind of widgets you are adding to your tool bar ?
-
@SGaist said in QToolbar widget ownership issues:
How did you check that parenting stuff ?
First, by checking what widget's parent() method returns before and after adding it to toolbar. Second, by placing a breakpoint in widget class destructor and testing when it is called.
Can you explain what kind of widgets you are adding to your tool bar ?
Most of them will be simple standard actions, but I already have 2 custom helper widgets for undo/redo - dropdowns which allow the user to view the whole command stack in detail and quickly jump to desired place instead of doing it step-by-step and seeing what happens. The root widget (directly added to the toolbar) is a QToolButton with popupMode()==MenuButtonPopup, and its child QMenu has another child which is my custom CommandStackVisualizer widget. It is in the "global" part of the toolbar, so I never really needed to delete / re-create it when I tried to dynamically rebuild the toolbar.
Anyway, I've just tested it with separate toolbars grouped together and it works much better. Now I just have to remember calling show() manually when I re-add tab's toolbar after switching to another tab and back, because QMainWindow::removeToolbar hides it... Looks like I was really under a misconception regarding how multiple toolbars work (despite seeing them many times in various applications). :) Still, QToolbar's official documentation could have been much clearer on all of this...
Thanks for your time.