PDA

View Full Version : Qt Crash during QDockWidget reparent through Drag and Drop



TEAmerc
7th October 2015, 20:33
In my program I've reimplemented the dropEvent and the mousePressEvents in order to let me re-parent QDockWidgets by dragging and dropping them between different instances of an inherited QMainWindow class. I previously had an issue where after reparenting a QDockWidget I had to mouseover the name of the QDockWidget in the top corner of the window in order for me to be able to select where to dock the widget in its new window rather than this happening immediately upon the drop completion. I've since fixed that by adding these two lines to the dropEvent():



QEvent reParentEvent(QEvent::MouseMove); // Mouse move (QMouseEvent) - 5
QApplication::sendEvent(child, &reParentEvent);


However somehow this introduced a new bug where sometimes during the drop (it seems to occur especially often when you reparent the dockwidget from the window that you spawn second into the window that was spawned first) a segfault occurs. Note I've never seen this crash without the above 2 lines of code, but I have no idea why these lines would cause a crash. Alternatively if there was another way to fix my issue of docking widgets immediately upon drop without causing intermittent crashes or the need to mouseover the QDockWidget's title that would also work.

I've created and attached a small qtproject (Here: 11415) to demonstrate the issue. Note if you comment/remove lines 82 and 83 from src/TableViewWindow.cpp the crash no longer occurs, but then you'll get the delayed docking action issue instead. I've found the most repeatable way to reproduce the crash is to create two windows containing QDockWidgets (press ctrl+N while on the mainwindow or use the dropdown menu), and then drag and drop the QDockWidget from the second window that was created into the first window that was created. If it doesn't crash at this point just restart the application and try again as it's faster than reparenting at random until it crashes after this point (It will eventually but sometimes it's after 2 more drag and drops, and sometimes after 15).

Also for some reason my drag and drop to reparent only works with both right and left click held down, and not just left click like I wanted so if someone could also tell me how to fix that in the meantime it'd be appreciated.

Thanks

TEAmerc
14th October 2015, 15:13
Shameless Bump

aefskysa
12th November 2015, 20:11
Can you post a quick example of your implementation of the events? I've been trying to figure out how to drop QDockWidgets into separate MainWindow instances for a while now, and haven't yet succeeded. If you could send me down the right track, I'd appreciate it.

Thanks.

TEAmerc
12th November 2015, 20:36
Hey, if you're having a similar issue to mine, I ended up finding what was causing my crash was that I had originally set that the dockwidgets were restricted to never be floating in their Ctor (using dock->setFeatures() and not including the DockWidgetFloatable property), but sometimes after the reparent they would become floating and that caused the segfault.

To fix the issue I added the DockWidgetFloatable feature, but on mousemove over a dock it would check if it was floating, and if it was floating I would check if there was an existing MyQMainWindow underneath the current mouse position, and if there was I would add it to a dockarea in that MyQMainWindow so it wouldn't be floating. If there wasn't I would create a MyQMainWindow at the current position and place it in the new one's dockarea.

The reason I did the check in MouseMoveEvent was because there isn't any way to detect the end of a dockwidget drag because the OS handles that task, but this way immediately after stopping the drag, once the mouse moves even a pixel it will put the dock widget in a MyQMainWindow. So if a dock is floating it won't be floating for long, and usually a person will continue to move the mouse due to the momentum of their hand after releasing from a drag, so most people won't notice it unless they do completely stop moving their mouse on release and even then it's not too jarring because the widget doesn't move, just a window border appears around it from the user's perspective.

If you don't have this issue, but you're looking for code to get you started on dragging QDockWidgets between QMainWindows you can download my code excerpt (the ForQtForums.tar.gz archive) from my original post above to get you started. Just remember to add the below feature to the constructor so you don't get a crash:



dock->setFeatures(QDockWidget::DockWidgetClosable
| QDockWidget::DockWidgetMovable
| QDockWidget::DockWidgetFloatable);


I changed quite a bit since then for reparenting QDockWidgets to make it neater (the beginning of this post refers to all the changes like not using the drag and drop feature to move the widget anymore, but just check the isfloating property on mousemoveevent and reparent then if necessary) but that file has working code that moves QDockWidgets between QMainWindows so however inelegant it should be good enough to get you started.