Reputation: 6147
I'm trying to build a treeview using what's called a slug: which is a string that's split by hyphens (e.g. Fruit-Apple
). Then you just loop through the parts and build the tree if the item doesn't already exist. The first item in the list is always the top most parent. Any suggestions or help would be greatly appreciated. I've having issues trying to append the item to the correct parent.
appendCategorySlug('Fruit-Apple')
appendCategorySlug('Fruit-Orange')
appendCategorySlug('Vegetable-Lettuce')
appendCategorySlug('Fruit-Kiwi')
appendCategorySlug('Vegetable-Carrot')
appendCategorySlug('Vegetable-Carrot-Blackbean')
appendCategorySlug('Vegan-Meat-Blackbean')
I'm not quite sure what I've got going wrong here. The results are kind close, but something is off...
import os, sys
from Qt import QtWidgets, QtGui, QtCore
class CategoryView(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.resize(250,400)
self.categoryModel = QtGui.QStandardItemModel()
self.categoryModel.setHorizontalHeaderLabels(['Items'])
self.categoryProxyModel = QtCore.QSortFilterProxyModel()
self.categoryProxyModel.setSourceModel(self.categoryModel)
self.categoryProxyModel.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.categoryProxyModel.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.categoryProxyModel.setDynamicSortFilter(True)
self.uiTreeView = QtWidgets.QTreeView()
self.uiTreeView.setModel(self.categoryProxyModel)
self.uiTreeView.sortByColumn(0, QtCore.Qt.AscendingOrder)
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.uiTreeView)
self.setLayout(self.layout)
def appendCategorySlug(self, slug):
# sourceIndex = self.categoryProxyModel.mapToSource(proxyIndex)
# item = self.categoryModel.itemFromIndex(sourceIndex)
parts = slug.split('-')
parent = self.categoryModel.invisibleRootItem()
for name in parts:
# find part and it doesn't exist append it
items = self.categoryModel.findItems(name, QtCore.Qt.MatchExactly | QtCore.Qt.MatchRecursive, 0)
if len(items) == 1:
print items[0].data()
parent = items[0]
item = QtGui.QStandardItem(name)
parent.appendRow(item)
parent = item
def test_CategoryView():
app = QtWidgets.QApplication(sys.argv)
ex = CategoryView()
ex.appendCategorySlug('Fruit-Apple')
ex.appendCategorySlug('Fruit-Orange')
ex.appendCategorySlug('Vegetable-Lettuce')
ex.appendCategorySlug('Fruit-Kiwi')
ex.appendCategorySlug('Vegetable-Carrot')
ex.appendCategorySlug('Vegetable-Carrot-Blackbean')
ex.appendCategorySlug('Vegan-Meat-Blackbean')
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
pass
test_CategoryView()
Upvotes: 1
Views: 142
Reputation: 120608
There are a few issues here. Searching recursively is error-prone because descendant items could have the same name as one of their ancestors. And it is also inefficient, because at each step we only want to know whether an item with the same name exists at the current level - the ones below it are irrelevant. Also, we should avoid searching if the current parent has no children, and make sure that new parents are only created when they're missing (which is the main problem with your current implementation).
The above issues can be fixed most easily if the model's match function is used instead of findItems
, since it allows greater control over how the searching is done:
def appendCategorySlug(self, slug):
parts = slug.split('-')
parent = self.categoryModel.invisibleRootItem()
for name in parts:
if parent.rowCount():
indexes = self.categoryModel.match(
parent.child(0).index(),
QtCore.Qt.DisplayRole, name, 1,
QtCore.Qt.MatchExactly)
if indexes:
parent = self.categoryModel.itemFromIndex(indexes[0])
continue
item = QtGui.QStandardItem(name)
parent.appendRow(item)
parent = item
This algorithm can be implemented even more simply with a simple for-loop, and is perhaps easier to understand:
def appendCategorySlug(self, slug):
parts = slug.split('-')
parent = self.categoryModel.invisibleRootItem()
for name in parts:
for row in range(parent.rowCount()):
child = parent.child(row)
if child.text() == name:
parent = child
break
else:
item = QtGui.QStandardItem(name)
parent.appendRow(item)
parent = item
Upvotes: 1