Discussion:
[Maya-Python] Creating a QTreeView hierarchy from a given list of strings
likage
2018-09-08 00:18:59 UTC
Permalink
Hi all,

Given a list of strings, I am trying to populate the items in a tree view.
Here is my code:


class MyModel(QtGui.QStandardItemModel):
def __init__(self, parent=None):
super(MyModel, self).__init__(parent)
self.get_contents()

def get_contents(self):
self.clear()
contents = [
'|Base|character|Mike|body',
'|Base|character|John',
'|Base|camera'
]

for content in contents:
count = content.count('|')
for index in range(count):
index = index + 2
split_path = content.split('|')[0:index]
self.add_item(split_path)

def add_item(self,name):
item1 = QtGui.QStandardItem(name)
self.appendRow([item1])


However, the hierarchy that I have got in my Tree View are not collapsible
(those with the small arrow icons by the side) and each row is appended
with values and editable (if double click), in which I do not want.

An example of the output from my code:

|Base
|Base|character
|Base|character|Mike
|Base|character|Mike|body
|Base
|Base|character
|Base|character|John
|Base
|Base|camera


where there are a few repeatable rows...

And this is what I am expecting:

|-- Base
|--|-- character
|--|--|-- Mike
|--|--|--|-- body
|--|-- character
|--|--|-- John
|--|-- camera



Any insights?
--
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+***@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/c59b034f-9786-4215-a807-4753642bb2d7%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Justin Israel
2018-09-08 02:34:15 UTC
Permalink
Instead of appending all your items to the model as rows you actually need
to append them to the appropriate parent QStandardItem

http://doc.qt.io/archives/qt-4.8/qstandarditem.html

You can do that by keeping a reference to the current parent as you loop
down into the next depth. Or you can look them up on the model as needed
when dynamically adding more items later.
Post by likage
Hi all,
Given a list of strings, I am trying to populate the items in a tree view.
super(MyModel, self).__init__(parent)
self.get_contents()
self.clear()
contents = [
'|Base|character|Mike|body',
'|Base|character|John',
'|Base|camera'
]
count = content.count('|')
index = index + 2
split_path = content.split('|')[0:index]
self.add_item(split_path)
item1 = QtGui.QStandardItem(name)
self.appendRow([item1])
However, the hierarchy that I have got in my Tree View are not collapsible
(those with the small arrow icons by the side) and each row is appended
with values and editable (if double click), in which I do not want.
|Base
|Base|character
|Base|character|Mike
|Base|character|Mike|body
|Base
|Base|character
|Base|character|John
|Base
|Base|camera
where there are a few repeatable rows...
|-- Base
|--|-- character
|--|--|-- Mike
|--|--|--|-- body
|--|-- character
|--|--|-- John
|--|-- camera
Any insights?
--
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
To view this discussion on the web visit
https://groups.google.com/d/msgid/python_inside_maya/c59b034f-9786-4215-a807-4753642bb2d7%40googlegroups.com
<https://groups.google.com/d/msgid/python_inside_maya/c59b034f-9786-4215-a807-4753642bb2d7%40googlegroups.com?utm_medium=email&utm_source=footer>
.
For more options, visit https://groups.google.com/d/optout.
--
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+***@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAPGFgA2kgksSfrg8UEOYdJ-gVa5EN4J%3D6CTEsMw%2BgD6XP2UtEA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
likage
2018-09-10 16:50:51 UTC
Permalink
Got it, many thanks for it, Justin!

I have another question, the following is the working code:
class MyModel(QtGui.QStandardItemModel):
def __init__(self, parent=None):
super(MyModel, self).__init__(parent)
self.get_contents()
self.assets_column = 0

def get_contents(self):
self.clear()
contents = [
'|Base|character|Mike|body',
'|Base|character|John',
'|Base|camera'
]

base_grp_icon = QtGui.QIcon('/user_data/base_grp_icon.png') # For
|Base
char_grp_icon = .QIcon('/user_data/char_grp_icon.png') # For
|Base|character
char_icon = .QIcon('/user_data/char_icon.png') # For
|Base|character|John
cam_icon = QtGui.QIcon('/user_data/cam_icon.png') # For |Base|camera

for content in contents:
parent = self.invisibleRootItem()


# content here will be `|Base|character|Mike|body` instead of
it iterating each and every item in that path
# node_type = cmds.nodeType(content)
# if node_type == "baseMain":
# icon = base_grp_icon
# if node_type == "charGrp":
# icon = char_grp_icon
# if node_type == "charMain":
# icon = char_icon
# if node_type == "camMain":
# icon = cam_icon


for word in content.split("|")[1:]:
child_items = [parent.child(i) for i in
range(parent.rowCount())]
for item in child_items:
if item.text() == word:
it = item
break
else:
it = QtGui.QStandardItem(word)
parent.setChild(parent.rowCount(), it)
parent = it


If I had wanted to append icons for each row, what is the best way that I
can do?
Those paths that you have seen in the code, are custom node types and if I
do `cmds.nodeType` as seen in that commented code portion, I will only be
able to iterate it based on the items found within the `contents` instead
of every item within...
--
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+***@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/28092299-d377-41ad-ac96-2e1c7f5544bd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Justin Israel
2018-09-10 21:43:01 UTC
Permalink
Post by likage
Got it, many thanks for it, Justin!
super(MyModel, self).__init__(parent)
self.get_contents()
self.assets_column = 0
self.clear()
contents = [
'|Base|character|Mike|body',
'|Base|character|John',
'|Base|camera'
]
base_grp_icon = QtGui.QIcon('/user_data/base_grp_icon.png') # For
|Base
char_grp_icon = .QIcon('/user_data/char_grp_icon.png') # For
|Base|character
char_icon = .QIcon('/user_data/char_icon.png') # For
|Base|character|John
cam_icon = QtGui.QIcon('/user_data/cam_icon.png') # For |Base|camera
parent = self.invisibleRootItem()
# content here will be `|Base|character|Mike|body` instead of
it iterating each and every item in that path
# node_type = cmds.nodeType(content)
# icon = base_grp_icon
# icon = char_grp_icon
# icon = char_icon
# icon = cam_icon
child_items = [parent.child(i) for i in
range(parent.rowCount())]
it = item
break
it = QtGui.QStandardItem(word)
parent.setChild(parent.rowCount(), it)
parent = it
If I had wanted to append icons for each row, what is the best way that I
can do?
Those paths that you have seen in the code, are custom node types and if I
do `cmds.nodeType` as seen in that commented code portion, I will only be
able to iterate it based on the items found within the `contents` instead
of every item within...
If I understand correctly, you already know how to set the icon, but you
are asking how to find these items in the hierarchy at a later point? Just
to save a round trip in case you are asking about icons, you would want to
use setIcon() on the first column item in each row.

For the part about navigating your tree hierarchy, what you can do is save
the maya path as data, and then search on this data later:

http://doc.qt.io/archives/qt-4.8/qabstractitemmodel.html#match

# Class variable
MayaPath = QtCore.Qt.UserRole+1
# Save the maya path as a custom data role
it = QtGui.QStandardItem(word)
it.setData(content, self.MayaPath)
# Find items later by the maya path
idxs = self.match(
self.index(0,0),
self.MayaPath,
content,
flags=QtCore.Qt.MatchRecursive,
)if not idxs:
# not found

it = self.itemFromIndex(idxs[0])
it.setIcon(...)

​
--
Post by likage
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
To view this discussion on the web visit
https://groups.google.com/d/msgid/python_inside_maya/28092299-d377-41ad-ac96-2e1c7f5544bd%40googlegroups.com
<https://groups.google.com/d/msgid/python_inside_maya/28092299-d377-41ad-ac96-2e1c7f5544bd%40googlegroups.com?utm_medium=email&utm_source=footer>
.
For more options, visit https://groups.google.com/d/optout.
--
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+***@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAPGFgA2qN5YTE5_Cm%2B4%2Bzv17UnzwuAyQDNnpui-sgg95NZa1dA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
likage
2018-09-11 17:07:03 UTC
Permalink
Hi Justin, thank you for getting back.

I added your code into my get_contents() function.
It seems that only an item is being stored? Tried doing a `print
it.text()`, it is only returning me `camera` as the result instead of the
full path..
As such, only that item is being appended with icon..

Wondering if I had done it wrong in any case?
--
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+***@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/a15b269f-180f-485a-88c3-8afd78fabbc3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Justin Israel
2018-09-11 19:25:53 UTC
Permalink
Post by likage
Hi Justin, thank you for getting back.
I added your code into my get_contents() function.
It seems that only an item is being stored? Tried doing a `print
it.text()`, it is only returning me `camera` as the result instead of the
full path..
As such, only that item is being appended with icon..
Wondering if I had done it wrong in any case?
text() is always going to be equivalent to data(Qt.DisplayRole), which is
the split name component you set when you constructed the item. The full
Maya path is being stored as extra data in a custom role. So you need to do
data(self.MayaPath) to get that back again.
Post by likage
--
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
To view this discussion on the web visit
https://groups.google.com/d/msgid/python_inside_maya/a15b269f-180f-485a-88c3-8afd78fabbc3%40googlegroups.com
<https://groups.google.com/d/msgid/python_inside_maya/a15b269f-180f-485a-88c3-8afd78fabbc3%40googlegroups.com?utm_medium=email&utm_source=footer>
.
For more options, visit https://groups.google.com/d/optout.
--
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+***@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAPGFgA0ZdjNmbBMQmP5EZwLvk4kRHPFTaha_BF7kBimHDtLncw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
Loading...