1

I am writing a PySide application with a QListView. This QListView allows drag and drop events to change the order of the items it displays.

The QListView uses a QStandardItemModel, and the QStandardItemModel contains QStanardItem objects. I have given these QStandardItem objects custom instance attributes, as follows:

def createShotItem(self, path, display_name, name):
    item = CustomItem(display_name)
    item.setCheckable(True)
    item.setCheckState(QtCore.Qt.Checked)

    item.path = path
    item.name = name
    item.fields = {}  # Used to store setting fields

    return item

Below is the CustomItem class.

class CustomItem(QtGui.QStandardItem):
    def __init__(self, text):
        self.shot_path = ""
        self.name = ""
        self.fields = {}
        super(CustomItem, self).__init__(text)

Previously, I was simply adding the attributes directly to a QStandardItem, without using a sub-class. There was no difference.

The sub-classed QListView and QStandardItemModel classes are as follows:

class DragDropListView(QtGui.QListView):
    def __init__(self):
        super(DragDropListView, self).__init__()
        self.setAcceptDrops(True)
        self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
        self.setDefaultDropAction(QtCore.Qt.MoveAction)
        self.setDragDropOverwriteMode(False)
        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)

    def dragEnterEvent(self, event):
        if __name__ == '__main__':
            if event.mimeData().hasUrls:
                event.acceptProposedAction()
        else:
            super(DragDropListView, self).dragEnterEvent(event)
class DragDropItemModel(QtGui.QStandardItemModel):
    def __init__(self):
        super(DragDropItemModel, self).__init__()

    def flags(self, index):
        if index.isValid():
            return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsEnabled \
                   | QtCore.Qt.ItemIsUserCheckable

        return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled \
               | QtCore.Qt.ItemIsDropEnabled | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable

When I later attempt to access one of these attributes on an item who has been moved in the list, I get an error as follows:

AttributeError: 'PySide.QtGui.QStandardItem' object has no attribute 'fields'

As you can see, my CustomItem, which extends QStandardItem, has been replaced by a QStandardItem that does not contain any of my custom attributes.

I believe that this is because, when a re-order occurs, due to a drag-and-drop event, PySide creates a new QStandardItem at the desired index, containing the same text attribute, and other PySide attributes, but discarding my custom attributes.

Note that accessing these custom attributes works fine on all unmoved items. Also, appending or inserting a CustomItem using model.appendRow(item) or model.insertRow(index, item) works fine, so the issue is not with those methods.

How can I maintain these custom attributes throughout move events? Do I need to alter the behavior of the move event, and if so, how?

Johndt
  • 4,187
  • 1
  • 23
  • 29

0 Answers0