[PYTHON] Make a model iterator with PySide

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.

code

#! 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']

Reverse iterator

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

Make a model iterator with PySide
Make a fortune with Python
Make a fire with kdeplot
Let's make a GUI with python.
Make a sound with Jupyter notebook
Let's make a breakout with wxPython
Make a recommender system with python
Make a filter with a django template
Let's make a graph with python! !!
Let's make a supercomputer with xCAT
Make a nice graph with plotly
Let's make a shiritori game with Python
Make a video player with PySimpleGUI + OpenCV
Make a rare gacha simulator with Flask
Make a partially zoomed figure with matplotlib
Make a drawing quiz with kivy + PyTorch
Let's make a voice slowly with Python
Make a cascade classifier with google colaboratory
Let's make a simple language with PLY 1
Make a logic circuit with a perceptron (multilayer perceptron)
Make a Yes No Popup with Kivy
Make a wash-drying timer with a Raspberry Pi
Make a GIF animation with folder monitoring
Let's make a web framework with Python! (1)
Let's make a tic-tac-toe AI with Pylearn 2
Make a desktop app with Python with Electron
Let's make a Twitter Bot with Python!
Implement a model with state and behavior
Let's make a web framework with Python! (2)
Try TensorFlow RNN with a basic model
I came up with a way to make a 3D model from a photo.
A model that identifies the guitar with fast.ai
A memorandum to make WebDAV only with nginx
Investment quest: Make a system trade with pyhton (2)
Make a Twitter trend bot with heroku + Python
[Python] Make a game with Pyxel-Use an editor-
Make a monitoring device with an infrared sensor
Make a simple pixel art generator with Flask
Investment quest: Make a system trade with pyhton (1)
How to make a dictionary with a hierarchical structure.
I want to make a game with Python
Predict hot summers with a linear regression model
Try to make a "cryptanalysis" cipher with Python
Create a color bar with Python + Qt (PySide)
Let's replace UWSC with Python (5) Let's make a Robot
Create a color-specified widget with Python + Qt (PySide)
Try to make a dihedral group with Python
[Chat De Tornado] Make a chat using WebSocket with Tornado
Implement a discrete-time logistic regression model with stan
Make holiday data into a data frame with pandas
(Memorandum) Make a 3D scatter plot with matplodlib
Make a squash game
Make one repeating string with a Python regular expression.
Make Lambda Layers with Lambda
I tried to make something like a chatbot with the Seq2Seq model of TensorFlow
Simulate a good Christmas date with a Python optimized model
Make a morphological analysis bot loosely with LINE + Flask
Try to make a command standby tool with python
A4 size with python-pptx
[Practice] Make a Watson app with Python! # 2 [Translation function]
[Practice] Make a Watson app with Python! # 1 [Language discrimination]