Issue
I'm trying to retrieve the model index for the QTreeView item using the given slug - which is a single string representing the treeview item's hierarchy separated by hyphens. In this case, I want to get the model index for the given slug 'Vegetable-Carrot-Blackbean'
:
My current function always returns "Vegetable" and I feel like the way it's written I'd expect it to continually loop through a given index's children until it fails, returning the last found tree item:
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):
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
def getIndexBySlug(self, slug):
parts = slug.split('-')
index = QtCore.QModelIndex()
if not parts:
return index
root = self.categoryModel.index(0, 0)
for x in parts:
indexes = self.categoryModel.match(root, QtCore.Qt.DisplayRole, x, 1, QtCore.Qt.MatchExactly)
if indexes:
index = indexes[0]
root = index
print index, index.data()
return index
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.getIndexBySlug('Vegetable-Carrot-Blackbean')
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
pass
test_CategoryView()
Solution
The reason your current implementation doesn't work is that the start
argument of match()
needs to be valid index. The invisisble root item can never be valid because its row and column will always be -1
. So, instead, you must use the the model's index() function to try to get the first child index of the current parent. You also need to make sure that an invalid index is returned when any part of the slug cannot be matched, otherwise you could wrongly end up returning an ancestor index.
Here's a method that implements all that:
def getIndexBySlug(self, slug):
parts = slug.split('-')
indexes = [self.categoryModel.invisibleRootItem().index()]
for name in parts:
indexes = self.categoryModel.match(
self.categoryModel.index(0, 0, indexes[0]),
QtCore.Qt.DisplayRole, name, 1,
QtCore.Qt.MatchExactly)
if not indexes:
return QtCore.QModelIndex()
return indexes[0]
As an alternative, you might want to consider returning an item instead, as that will then give you access to the whole QStandardItem
API (and the index can be still be easily obtained via item.index()
):
def itemFromSlug(self, slug):
item = None
parent = self.categoryModel.invisibleRootItem()
for name in slug.split('-'):
for row in range(parent.rowCount()):
item = parent.child(row)
if item.text() == name:
parent = item
break
else:
item = None
break
return item
But note that this returns None
if the slug cannot be found (although it could easily be tweaked to return the invisible root item instead).
Answered By - ekhumoro
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.