Model/View Progamming and Drag/Drop

244 views
Skip to first unread message

Joe Weidenbach

unread,
Mar 11, 2015, 5:00:32 PM3/11/15
to python_in...@googlegroups.com
Hey folks,

More of a conceptual question here, as I've got this working at this point, but it feels like I had to do some ugly workarounds, which I can design around in the future, but would rather not have to.

As I'm understanding it, Qt's Drag and Drop functionality in Models and Views is based on primarily taking elements from one model and moving them to another.  When I am working in a Tree View, for example, and I want to reorder or reparent items, I basically have to clone my item that I'm dropping and put it in the model where I want it, after which Qt deletes the original.  This makes sense based on the usual use of drag and drop to go from one view to another.

The question is, is there a way to set things up so I can just move an item?  It's easy enough to build a data model that supports serializing and then making a new item that is a duplicate of the old, but it seems like extra work (both on the coding and on the processing sides) as compared to just changing the parent or sort index.

Just curious.

Thanks,

Joe

Justin Israel

unread,
Mar 11, 2015, 5:23:25 PM3/11/15
to python_in...@googlegroups.com
You should just be able to "take" an item from the model and then add it to the new location. Does that approach not work for you? I don't recall needing to clone the item and delete the old one. 


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAM33%3Da4_R8YYmG_BOG0nnh%2BHGVQrWhvbrFTCM%2BOjoWmxHx4W_A%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Joe Weidenbach

unread,
Mar 11, 2015, 5:24:09 PM3/11/15
to python_in...@googlegroups.com
I should note that more specifically, for getting this to work currently, I create a clone of my original element in the dropMimeData function of my model, and put that clone in place.  Qt Deletes my original automatically after the fact.  I know this is happening because if I do a debug inspection of my data at the end of dropMimeData, the original element is still there.  Also, if I just reparent the item, Qt deletes it after it has been reparented.  I suspect that removeRows is is being called internally on the original dragged element, but I can't see any way to override that behavior, and am hoping that's just one of those things that's not documented but is still possible.

As I said, it's easy enough to design around, but it doesn't feel like I should have to, with how long Qt's been around.

Joe Weidenbach

unread,
Mar 11, 2015, 5:25:50 PM3/11/15
to python_in...@googlegroups.com
I can check into the take aspect.  I haven't used it specifically, so it's worth a try.

Marcus Ottosson

unread,
Mar 11, 2015, 5:40:17 PM3/11/15
to python_in...@googlegroups.com

Rather than serialising and de-serialising your item each time, you could instead keep track of origin and destination indexes of the operation; and then re-order the items accordingly.

For example, if you’ve got these items in your model.

item0
item1
item2
item3

And in your drag and drop operation, you take the item at index 0 (only keeping track of the index in dropMimeData) and drop it at index 2 then you might expect your model to look like this.

item1
item2
item0
item3

And once you’ve know that, you can either sort it manually to match or use something like moveRow of QAbstractItemModel and have the model handle how it should all end up.

It saves you the trouble of serialisation, at the cost of not being able to drop it anywhere else, like a text editor, as the index doesn’t really mean much on its own.

Joe Weidenbach

unread,
Mar 11, 2015, 6:41:47 PM3/11/15
to python_in...@googlegroups.com
I'm glad we're all on the same page.  Looking into Justin's mention of "taking" the item, I do see that functionality in the Convenience Widgets (QTreeWidget, etc), but not in QAbstractItemModel.  Same with Marcus' suggestion of moveRow(). I might be looking at the wrong documentation...(http://srinikom.github.io/pyside-docs/PySide/QtCore/QAbstractItemModel.html or http://qt-project.org/doc/qt-4.8/qabstractitemmodel.html).

I haven't gone into beginMoveRows yet, mainly as in dropMimeData I don't have an index or parent for the original element (I think the model manages that internally), although I can get the data from it (I look up the element in my underlying data model using the serialization I put into the MimeData).  I'm doing the reordering exactly as Marcus described as well, although I'm currently inserting my cloned item.

I think I could serialize the index data in mimeData to reconstruct the parent index in dropMimeData, that might be my next move so I can try working with beginMoveRows and see if it's any cleaner.

Joe Weidenbach

unread,
Mar 11, 2015, 8:08:26 PM3/11/15
to python_in...@googlegroups.com
Just an update; from my research, it looks like I need to subclass QTreeView to do this.  The default implementation of startDrag from QAbstractItemView apparently is what will delete the original item after everything's said and done, which checks out with reading the source code of qabstractitemview.cpp.  So far, I've made do with a raw QTreeView.  It looks like I'll have to subclass that so I can override startDrag and not have it remove the row.

Justin Israel

unread,
Mar 11, 2015, 8:12:49 PM3/11/15
to python_in...@googlegroups.com
Ya actually there are a number of ways to work with drag and drop, depending on what classes you are using. Like you have said, there is dropMimeData on the model if you want to handle it there, and startDrag on the view if you want to handle it there, and then more manual approaches with starting your own drag in the mouse events.


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAM33%3Da6U7RYaWUVBFaxCLuhzMzWAB%3DYU_UPOdg0A0CetR%2BH9KA%40mail.gmail.com.

Joe Weidenbach

unread,
Mar 11, 2015, 8:22:17 PM3/11/15
to python_in...@googlegroups.com
I've actually done the manual approaches before with raw widgets, this is partially because I think that the model/view approach is actually the best way to handle this particular scenario, and partially because I want to know more of the ins and outs of Qt's systems.  Mostly the former, but I do like increasing my knowledge base :)

With that said, I did just get everything working without the cloning step, and without subclassing QTreeView.  I basically added a flag to my model to block item removals, set the flag in dropMimeData, and then check that flag in removeRows, where I clear it if it was set and then skip the actual row removal.  It still feels a bit hacky, but it works.  I think the next stage is to subclass QTreeView.  That feels more clean all around, even if it is a little more work :)

To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAPGFgA0rK435D%2BC47gx1AgSJuRxhbm7ZfQSzKZnNzaeJgxpuqw%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages