When creating a tree model in PySide, you may want to access all items sequentially.
If you are using QTreeWidget, you can access it sequentially with QTreeWidgetItemIterator. (Since it is a library for C ++, it is a little inconvenient to use with python) I created it because I want to use an iterator for QStandardItemModel and my own model.
The code is python2, but since it doesn't use xrange, it works as it is in python3.
#! usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function, absolute_import
from PySide.QtCore import *
from PySide.QtGui import *
def model_iter(model, parent_index=QModelIndex(), col_iter=True):
"""Model iterator
:rtype: generator(QModelIndex)
:type col_iter: bool
:type parent_index: QModelIndex
:type model: QAbstractItemModel
"""
index = model.index(0, 0, parent_index)
while True:
if col_iter:
for col in range(0, model.columnCount(parent_index)):
yield index.sibling(index.row(), col)
else:
yield index
if model.rowCount(index) > 0:
for _ in model_iter(model, index, col_iter):
yield _
index = index.sibling(index.row() + 1, index.column())
if not index.isValid():
break
It's easy to use, just pass the model and it will return an iterator.
tree_model = QStandardItemModel()
item = QStandardItem("A")
item.appendRow(QStandardItem("A-1"))
item.appendRow(QStandardItem("A-2"))
tree_model.appendRow(item)
item = QStandardItem("B")
item.appendRow(QStandardItem("B-1"))
item.appendRow(QStandardItem("B-2"))
tree_model.appendRow(item)
item = QStandardItem("C")
tree_model.appendRow(item)
print([_.data() for _ in model_iter(tree_model)])
>>> [u'A', u'A-1', u'A-2', u'B', u'B-1', u'B-2', u'C']
It supports not only tree type but also table type model.
table_model = QStandardItemModel(3, 3)
for r in range(3):
for c in range(3):
table_model.setItem(r, c, QStandardItem("%d-%d" % (r, c)))
print([_.data() for _ in model_iter(table_model)])
>>> [u'0-0', u'0-1', u'0-2', u'1-0', u'1-1', u'1-2', u'2-0', u'2-1', u'2-2']
I also created a reverse iterator.
def model_iter_r(model, parent_index=QModelIndex(), col_iter=True):
"""Model iterator (reverse order)
:rtype: generator(QModelIndex)
:type col_iter: bool
:type parent_index: QModelIndex
:type model: QAbstractItemModel
"""
index = model.index(model.rowCount(parent_index) - 1, 0, parent_index)
while True:
if model.rowCount(index) > 0:
for _ in model_iter_r(model, index, col_iter):
yield _
if col_iter:
for col in range(model.columnCount(parent_index) - 1, -1, -1):
yield index.sibling(index.row(), col)
else:
yield index
index = index.sibling(index.row() - 1, index.column())
if not index.isValid():
break
The usage is exactly the same as the one in order.
print([_.data() for _ in model_iter_r(tree_model)])
>>> [u'C', u'B-2', u'B-1', u'B', u'A-2', u'A-1', u'A']
print([_.data() for _ in model_iter_r(table_model)])
>>> [u'2-2', u'2-1', u'2-0', u'1-2', u'1-1', u'1-0', u'0-2', u'0-1', u'0-0']
The tree structure is also followed in reverse order.
Sequential access to models is a frequently used feature, but it is cumbersome to implement each one because it uses recursion. It would be nice to copy this function.
Next time, we will use this function to create a search object.
Recommended Posts