restoring expanded state of qtreewidget hierarchy

1,630 views
Skip to first unread message

Benjam901

unread,
Apr 15, 2015, 10:40:24 AM4/15/15
to python_in...@googlegroups.com
Hello all,

I have run into a problem with my application. I need to be able to restore the hierarchy as it is after I clear it and repopulate the list.

My current solution is to run through the items in the treewidget and gather the list of indexes like so. I then iterate through the tree once it has been cleared and repopulated and try to match up the indexes with the old list:

It does not work, I believe that the indexes are changed on the refresh for each item which is problematic, is there any way to keep the index of each consistent?

I have come across persistent indexes but that is for QAbstractModel and I am using QtreeWidget, I am unsure if the underlying model o fmy treewidget is a QAbstractModel and if I can use persistent indexes.

def refreshWidget(self, filePath, xmlTree, displayWidget, fileType):
saveState = self.saveWidgetState(displayWidget)
config.uiViewCleared = True
displayWidget.clear()
config.uiViewCleared = False
self.xmlI_O.setUpTree(filePath, xmlTree, displayWidget, fileType)
self.loadWidgetState(displayWidget, saveState)
 
 
def saveWidgetState(self, displayWidget):
print displayWidget.selectionModel()
expandedIndexes = {}
 
it = QtGui.QTreeWidgetItemIterator(displayWidget)
while it.value():
itemIndex = displayWidget.indexFromItem(it.value(), 0)
expandedItem = displayWidget.isItemExpanded(it.value())
expandedIndexes.update({itemIndex: expandedItem})
it += 1
return expandedIndexes
 
def loadWidgetState(self, displayWidget, expandedIndexes):
it = QtGui.QTreeWidgetItemIterator(displayWidget)
while it.value():
toExpand = [i for i in expandedIndexes if i == displayWidget.indexFromItem(it.value(),0)]
print "toExpand", toExpand
shouldExpand = expandedIndexes.get(toExpand[0])
if shouldExpand == True:
if not displayWidget.isItemExpanded(it.value()):
print "to expand", it.value().text(0)
displayWidget.expandItem(it.value())
it += 1




Cheers!

Ben

Marcus Ottosson

unread,
Apr 15, 2015, 11:37:41 AM4/15/15
to python_in...@googlegroups.com
Without fully understanding what you're up to, you may be better off with a QTreeView and QAbstractItemModel. The model would keep track of hierarchy, and your view simply represent it. Thus if you refresh the view, the data remains the same and if you change the data, the view updates accordingly.​

Ben Hearn

unread,
Apr 15, 2015, 12:18:04 PM4/15/15
to python_in...@googlegroups.com
I am representing XML data in a tree view and enabling the editing of this XML data, when the user changes some data in the editable fields the view is then updated to represent this new data. 

I have not used QTreeView or any model information yet. Are there any huge differences with adding items and editing them? Also is there that much of a benefit in switching from QtTreeWidget especially since I am quite a leap into the project at current.


On 15 April 2015 at 17:37, Marcus Ottosson <konstr...@gmail.com> wrote:
Without fully understanding what you're up to, you may be better off with a QTreeView and QAbstractItemModel. The model would keep track of hierarchy, and your view simply represent it. Thus if you refresh the view, the data remains the same and if you change the data, the view updates accordingly.​

--
You received this message because you are subscribed to a topic in the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/python_inside_maya/SR3v1N1zYuc/unsubscribe.
To unsubscribe from this group and all its topics, 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/CAFRtmOD_M7Myk_4LXkgGn-QWtum53FjsAYQQVMg_ii5y1_eJvQ%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.



--

Tel - +46 76245 92 90 (Sweden)

Marcus Ottosson

unread,
Apr 15, 2015, 1:00:14 PM4/15/15
to python_in...@googlegroups.com
The strength of widget views in general is that they are very easy to get started with compared to item views, but fall short in more complex use-cases.

It does sound like you would be better off with an item view, however whether or not it's viable to switch is mostly a matter of how much further you intend on extending and maintaining your current implementation. It's quite likely that you are at a point where the amount of work involved in adding new functionality requires an exponentially increasing amount of work to get done due to having to fight the convenience provided by the widget view, and jidging by your example I'd say that this seems to be the case. On the other hand, if you're close to finishing and don't think it will need much maintenance once done then it's questionable whether the effort is worth it.

Item views are undeniably more complex than their widget counterparts but their complexity is really only a reflection of how complex the data you're working with really is, and hierarchical data especially is amongst the most complex data there is.

To put an analogy on your problem, you've been working with Microsoft Movie Maker and are looking to do things that Nuke has no problem doing. Do you learn Nuke, or find ways around the problem in Movie Maker?
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/CAM2ybkUwuA5Z00taxccfLUnZaUeKBgjRbdqKpu-%2BGaNE7TDWLA%40mail.gmail.com.

Justin Israel

unread,
Apr 15, 2015, 4:25:05 PM4/15/15
to python_in...@googlegroups.com

Switching to a view/model is not going to change the outcome of the current approach. Clearing the data is still clearing the data. QTreeWidget is a subclass of QTreeView with a built in model. You could use QPersistentModelIndex, and get the model from the widget with model(), but if you clear it, then the index will invalidate anyways.

There are two approaches you could take. One would be to change how you handle updates to data and not respond by clearing the whole model, but rather to update data for what has actually changed, and add and remove items. It would be the same with a view/model, except you would be handling the changes from the model instead of the widget. Then persistent model indexes would also work.

Or you could continue dumping and rebuilding every time, but store some kind of unique reference as data on each item so that you can save it before clearing, and check for it when you restore. Maybe some kind of xml path. If there is no unique type of identifier that you can associate with each item in reference to the xml, then you probably don't have a choice but to be more granular with how you manage the changes to your data.

Justin


Marcus Ottosson

unread,
Apr 15, 2015, 4:45:00 PM4/15/15
to python_in...@googlegroups.com
It depends.

The current outcome could potentially never have been a problem to begin with if the view simply represented the same data between being refreshes. This was at least my motivation for suggesting it in the first place.

Spontaneously, I'm thinking that the XML hierarchy would be parsed into an object hierarchy which would be directly represented by the view. The view and model would inherently support being edited and any ad-hoc solutions would become superflous.

The problem the OP is having basically sounds like what the item views were designed to solve and I'd think it would consume more time and effort to try and re-implement it on top of convenience objects.

I couldn't say for sure. It's merely an observation based on the information I got.

Best,
Marcus

Ben Hearn

unread,
Apr 15, 2015, 5:04:17 PM4/15/15
to python_in...@googlegroups.com
Thanks again for some solid info Marcus and Justin. I have been thinking about how to solve this and did not think to update the current item. I think this would be a good approach to go on as it would keep my current hierarchy as it is. The other approach to completely refreshing the tree widget would be to store the hierarchy in a dictionary of lists, For example root-child-sibling-last item if said last items parent is expanded 

I think I will try to implement an update on the current item and save a full refresh for a different case. 

As per implementing a tree view with models what does this mean exactly, is the model itself the type of data passed into the tree view. If a tree widget takes a tree widget item as an item type, would you be passing in an abstract model item for example as an item i.e. QTreeView.append(QAbstractModelItem)

Cheers,

Ben

For more options, visit https://groups.google.com/d/optout.

Justin Israel

unread,
Apr 16, 2015, 12:55:44 AM4/16/15
to python_in...@googlegroups.com
@Marcus, I think I had just read his description from a different angle as you did. In the first post, he didn't mention how the model was being edited. Then his follow up to your reply described "editable fields". To me, I just took that as the tree view being modified and he was refreshing everything based on that. But I think you interpreted it as another view changing the data to which the tree view then needed to be refreshed. 

I definitely agree that if you are showing multiple views onto the data, then the model/view approach would make that easier. Like Marcus said, editing one view would drive changes in another view that share the same model. 

QTreeView doesn't deal with "items" in the way the higher level widget does. In the higher level approach, the abstraction is that each item completely represents its own little data container. In QTreeView, it is meant to sit on top of a model and just handle user interactions and send/receive interactions to the data model. The next step down from QTreeWidget is to use QTreeView and a QStandardItemModel, which still maintains that item-based approach, where you do those operations on the model (not the view). Then the next step down from there is an QAbstractItemModel, where you don't deal with individual items representing their data, but rather define in the model exactly  how to access the underlying data. That is, given some row/column/parent, what data should be returned for what role? The item-based abstraction is gone. 

Justin


Reply all
Reply to author
Forward
0 new messages