Question

I'm having problems with a class that implements __getitem__ and __setitem__.

Instances of this class are the data backend of a QAbstractListModel. I return these instances in the data(index) implementation of the Model when role==Qt.UserRole to be able to access the object from outside the model.

One scenario where I want to do this, is when the user clicks on any item in the QListView that uses my model for displaying the data. The problem now is, that my program starts running in an endless loop (within __getattr__) as soon as I try to retrieve the data from the index that the user clicked on.

Below is a complete, copy/pasteable code fragment that reproduces the behaviour described. The program will loop in the line index.data(Qt.UserRole) of testfunc.

Am I missing a point somewhere or have I encountered a bug in PySide?

#!/usr/bin/python

from PySide.QtCore import QAbstractListModel, Qt, QObject
from PySide.QtGui import QApplication, QListView

import sys

###############################################################################

class TestObject(QObject):
    def __init__(self, parent=None):
        """Creates new instance of TestObject.
        @param parent Qt parent."""
        super(TestObject, self).__init__(parent)
        self._data = {}

    def __getitem__(self, key):
        """Gets an item from self._data"""
        if key in self._data.keys():
            return self._data[key]

    def __setitem__(self, key, value):
        """Sets the value for key."""
        self._data[key] = value

###############################################################################

class TestModel(QAbstractListModel):
    def __init__(self, parent=None):
        """Creates a new instance of TestModel.
        @param parent Qt parent."""
        super(TestModel, self).__init__(parent)
        self._objects = []
        for i in range(5):
            obj = TestObject(self)
            obj[i] = str(i)
            self._objects.append(obj)

    def rowCount(self, parent):
        """Returns the amount of datasets."""
        return len(self._objects)

    def columnCount(self):
        """Returns the amount of columns, which is 1."""
        return 1

    def data(self, index, role=Qt.DisplayRole):
        """Returns the data for the given model index"""
        if index.isValid():
            obj = self._objects[index.row()]
            if role == Qt.DisplayRole:
                return str(obj)
            elif role == Qt.UserRole:
                return obj
        return None

###############################################################################

def testfunc(index):
    """Does something with index."""
    print "getting..."
    index.data(Qt.UserRole)
    print "never getting here :/"

###############################################################################

if __name__ == "__main__":
    app = QApplication(sys.argv)
    view = QListView()
    view.setModel(TestModel())
    view.clicked.connect(testfunc)
    view.show()
    app.exec_()
Was it helpful?

Solution 2

__getitem__ needs to raise IndexError() on invalid key

OTHER TIPS

It seems that PySide is trying to iterate over you objects (can't say why). Just as said in comment, you need to raise IndexError in __getitem__ to stop this iteration inside of PySide.

Info about __getitem__ and iteration over an object: https://stackoverflow.com/a/926645/812662

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top