PySide: QtreeWidgetItems drop enable only on some items

102 views
Skip to first unread message

Rudi Hammad

unread,
Apr 6, 2017, 8:26:35 AM4/6/17
to Python Programming for Autodesk Maya
Hello,

I have 2 tree widgets. I drag items from the tree on the right side. I want that the item named "container", once dropped in the left side tree, will become the only item that can
receive drops. This is my first attempt. It is all setup to execute:

https://pastebin.com/3QTU9rBX

I guess that the problem is item dropped is taking the properties of the treewidget, so all the items can recieve drops.

The only way that I can think of is creating my own QTreeWidget class and override methods such as dropEvent(), but isn´t that to complicated? Because I will also have to do mouse events,
then get the QPoint on the widget, check which row it is, take out item, insert item etc...
I just wonder if there is a simpler way before going crazy writing my own class. All I want is that the item "container" could receive drops in the left tree widget.

Thanks

Justin Israel

unread,
Apr 6, 2017, 3:50:31 PM4/6/17
to Python Programming for Autodesk Maya

It looks like your example is trying to loop through the whole model and update the flags on every item, every time a click happens?

There are a couple ways you could solve this. You are in control of the items you create in your view. So you could just set the flags properly on them at creation time. But if you are basing the criteria on the name, and you feel the name can change which would change the availability of dropping then that may not work since you would then need to update the flags on the item each time the data changes on items.

If you were using a view + model approach, the model has a flags() virtual method that can be reimplemented to dynamically answer the question of what flags an item has at any time.

But with the QTreeWidget, yes you could subclass it and implement dragEnterEvent(). This would get called when an item enters the view. You would need to inspect what is being dragged in to accept or ignore if you allow it. Then you could implement the dragMoveEvent() to keep answering yes or no as the item is moved over different parts of the view. It would reject the event if it isn't over the parts you want.

So yes, the most complicated approach would be to implement the events. The easiest approach would be to try and manage the flags when items are created. Or switch to a QTreeView and model and implement flags() on the model.

One thing I don't remember if I have tried is to call model() on your QTreeWidget to get the abstract model instance, and then patching it's flags() method and setting the model back on the view with setModel(). It may not work since it was not originally  a python model.

Justin


--
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/a31036f7-55ad-4b5c-9431-6d692dc8719e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Rudi Hammad

unread,
Apr 7, 2017, 12:07:12 PM4/7/17
to Python Programming for Autodesk Maya
Hey Justin.hmmm...ok.
So I am trying the implement the events my self creating the class and overriding the methods.
This is what I did:
https://pastebin.com/
So now I am able to override the dropEvent and add items to the tree, but I having a hard time inserting the items where I want.
I tryied to use event.pos() to get the coordinates of the mouse, but I don´t see how to insert the item were the mouse is released.

R

Rudi Hammad

unread,
Apr 7, 2017, 12:10:33 PM4/7/17
to Python Programming for Autodesk Maya
sorry, badLink. This is the one --> https://pastebin.com/S6DZd5MM

Justin Israel

unread,
Apr 7, 2017, 11:01:21 PM4/7/17
to Python Programming for Autodesk Maya

If you now have the drop position from the QDropEvent, then you should be able to inspect the item under the position via itemAt

http://doc.qt.io/qt-4.8/qtreewidget.html#itemAt

From there you can choose how you want to insert

Justin


On Sat, Apr 8, 2017, 4:10 AM Rudi Hammad <rudih...@gmail.com> wrote:
sorry, badLink. This is the one --> https://pastebin.com/S6DZd5MM

--
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.

Rudi Hammad

unread,
Apr 8, 2017, 7:50:27 AM4/8/17
to Python Programming for Autodesk Maya
Thanks Justinn, that was it.

I guess that the next step is to be able to insert it before or after. The treeWidget by default highlights a line under or above, to indicate where the insertion will be done.
At the moment myInserted item is taking the place of the one that is dropped one. But I guess that it won´t be simple to do, since I will have to create methods to mimic this behavior?

My other question is if I am doing right the dropEvent(), because all I am doing is creating a new item and copying the text of the item in the left. I will also copy the data stored as userRole.
But is this a real drag and drop? I am just creating a newItem and copying the text and data of the item selected in the left.

R


El sábado, 8 de abril de 2017, 4:01:21 (UTC+1), Justin Israel escribió:

If you now have the drop position from the QDropEvent, then you should be able to inspect the item under the position via itemAt

http://doc.qt.io/qt-4.8/qtreewidget.html#itemAt

From there you can choose how you want to insert

Justin


On Sat, Apr 8, 2017, 4:10 AM Rudi Hammad <rudih...@gmail.com> wrote:
sorry, badLink. This is the one --> https://pastebin.com/S6DZd5MM

--
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.

Justin Israel

unread,
Apr 8, 2017, 5:21:18 PM4/8/17
to Python Programming for Autodesk Maya


On Sat, Apr 8, 2017, 11:50 PM Rudi Hammad <rudih...@gmail.com> wrote:
Thanks Justinn, that was it.

I guess that the next step is to be able to insert it before or after. The treeWidget by default highlights a line under or above, to indicate where the insertion will be done.
At the moment myInserted item is taking the place of the one that is dropped one. But I guess that it won´t be simple to do, since I will have to create methods to mimic this behavior?

Stepping back a sec to your previous questions and goal, did you actually want to customise the drip behavior beyond just filtering what can and can't be dropped? I noticed you don't call the super methods in your reimplemented event handlers. If you determine you don't want to handle the item you can ignore it in the move event. Otherwise you could let the item drop using the default implementation. 

But if you really do need custom drop logic because you want to decide what exactly to copy to the new item, and where it goes, then yea you would have to handle the stuff like if it's dropped as a sibling of the item or as a child. Or if it really does replace the previous item. 

To determine if you should make it a sibling drop above or below you can get the visual rect of the drop target item and check where the drop event falls in relation to the center y





My other question is if I am doing right the dropEvent(), because all I am doing is creating a new item and copying the text of the item in the left. I will also copy the data stored as userRole.
But is this a real drag and drop? I am just creating a newItem and copying the text and data of the item selected in the left.

That's all drag and drops are. A widget receives a drip event with mime data and they interpret it somehow. Then the caller that initiated the drag receives the results of whether it was accepted and which action was used. So if it were a move, then the caller knows to delete their instance. But for a copy, the receiver is applying a copy of data. 


R


El sábado, 8 de abril de 2017, 4:01:21 (UTC+1), Justin Israel escribió:

If you now have the drop position from the QDropEvent, then you should be able to inspect the item under the position via itemAt

http://doc.qt.io/qt-4.8/qtreewidget.html#itemAt

From there you can choose how you want to insert

Justin


On Sat, Apr 8, 2017, 4:10 AM Rudi Hammad <rudih...@gmail.com> wrote:
sorry, badLink. This is the one --> https://pastebin.com/S6DZd5MM

--
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.

--
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/830582ed-cbce-4d87-87f6-ef2d4ba5038f%40googlegroups.com.

Rudi Hammad

unread,
Apr 9, 2017, 12:06:33 PM4/9/17
to Python Programming for Autodesk Maya


Stepping back a sec to your previous questions and goal, did you actually want to customise the drip behavior beyond just filtering what can and can't be dropped?


What I want is to give different properties to the drop item. So the item called "folder", when dropped in the left tree, will be an item that will accept drops and therefore, will ne expandable. But the other items, like"ball", after being drop, they will not accept drops. Once item is a container, and the others are single items.
So when the drop happens, If the item is called "folder" I will custom the flags in a way, and if the item is called something else I will custom the flags differently.
Also I can have another item called "separator" that once drop in the left tree will change the text to "--------------------------------------"

Does that make scene?

Justin Israel

unread,
Apr 9, 2017, 5:36:21 PM4/9/17
to python_in...@googlegroups.com
Yes. You want custom drop behaviour.
 

--
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.

Rudi Hammad

unread,
Apr 10, 2017, 8:04:03 AM4/10/17
to Python Programming for Autodesk Maya
Okey, I think it is working properly now

https://pastebin.com/Nsf0JNU5

I think it works, but is no very precise to get it exactly were you want, because the items are too small (and I want them small).
To get a visual reference I tried to do:

self.setDropIndicatorShown(True)

When I active this in QtDesigner, you see the line were it is going to be inserted. I am not sure why it is not working here


R

Justin Israel

unread,
Apr 10, 2017, 3:23:50 PM4/10/17
to Python Programming for Autodesk Maya

You could also have your drop insert between two items of the drop happened in the spacing between them. You currently have logic where if the drop was not on an item it will just append it. Add a little spacing to your tree widget between items and handle the case where it's between two items.


--
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.

Rudi Hammad

unread,
Apr 10, 2017, 5:51:50 PM4/10/17
to Python Programming for Autodesk Maya
ok, but what you mean with "add spacing between items". Is this a treeWidget flag or something that will separate the items with some amount of pixels?
I am not sure to understand

R


El lunes, 10 de abril de 2017, 20:23:50 (UTC+1), Justin Israel escribió:

You could also have your drop insert between two items of the drop happened in the spacing between them. You currently have logic where if the drop was not on an item it will just append it. Add a little spacing to your tree widget between items and handle the case where it's between two items.


On Tue, Apr 11, 2017, 12:04 AM Rudi Hammad <rudih...@gmail.com> wrote:
Okey, I think it is working properly now

https://pastebin.com/Nsf0JNU5

I think it works, but is no very precise to get it exactly were you want, because the items are too small (and I want them small).
To get a visual reference I tried to do:

self.setDropIndicatorShown(True)

When I active this in QtDesigner, you see the line were it is going to be inserted. I am not sure why it is not working here


R

--
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.

Justin Israel

unread,
Apr 10, 2017, 6:01:29 PM4/10/17
to python_in...@googlegroups.com
On Tue, Apr 11, 2017 at 9:51 AM Rudi Hammad <rudih...@gmail.com> wrote:
ok, but what you mean with "add spacing between items". Is this a treeWidget flag or something that will separate the items with some amount of pixels?
I am not sure to understand

Sorry. Looks like only QListView has the first class setSpacing() option. For tree view you would either have to control the height of the items through a stylesheet, or by a delegate or the item defining the sizeHint() to have a specific height
 

R


El lunes, 10 de abril de 2017, 20:23:50 (UTC+1), Justin Israel escribió:

You could also have your drop insert between two items of the drop happened in the spacing between them. You currently have logic where if the drop was not on an item it will just append it. Add a little spacing to your tree widget between items and handle the case where it's between two items.


On Tue, Apr 11, 2017, 12:04 AM Rudi Hammad <rudih...@gmail.com> wrote:
Okey, I think it is working properly now

https://pastebin.com/Nsf0JNU5

I think it works, but is no very precise to get it exactly were you want, because the items are too small (and I want them small).
To get a visual reference I tried to do:

self.setDropIndicatorShown(True)

When I active this in QtDesigner, you see the line were it is going to be inserted. I am not sure why it is not working here


R

--
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.

--
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/4dba28f7-e525-481a-a905-6ece9cfb5f5f%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages