PyQT5 - Custom QListView with reordering posibilities

23 Views Asked by At

I extensively used topic on SO but never posted anything so excuse me if I made mistakes.

So, my goal is too create a PyQT5 GUI with a QListView displaying layers for a plotly Dash server. To be completed I need a contextual menu (Done) and the possibility to reorder my layer and link this order to my Dash server to change traces order.

Actually I made: ReorderedListView, ListModel and ListModelItems as Subclasses from respectively QListView, QStandardItemModel and QStandardItem.

I manage using the dragdrop functions from QListView to reorder my item through a simple drag and drop.

PROBLEM :My issue is that when dragged and dropped my ListModelItem (arranged in my Model) are processed by the several function and returns as simple QStandardItem and no longer as ListModelItem, thus losing the property I added in my ListModelItem subclass.

WHAT I UNDERSTOOD: Now I stay with two option :

  1. Find wich function transform my Object in QStandardItem and Overwrite it (Seems to be QListView.StartDrag but for now I didn't managed to get something working in this option)

  2. Rethink my code structure and use the original QStandardItem and store my data in the current attribute of this class (I didn't find any promissing clues for now)

Documentation on what I aim to do seems to be inexistant (I used several docs in JS that I translated but still none aiming at subclassing QStandardItem) so I'm trying my luck here.

Here is elements form my code to understand :

My QListView class and instantiation:

class ReorderedListView(QListView):
    def __init__(self,Model,parent=None):
        super().__init__(parent)
        self.setMinimumWidth(100)
        self.setMaximumWidth(300)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.setDragEnabled(True)
        self.setDragDropMode(QAbstractItemView.InternalMove)
        self.setDragDropOverwriteMode(False)
        self.setModel(Model)
        self.drop = pyqtSignal(bool)

self.layerscol = ReorderedListView(self.Model, parent=self)
self.layerscol.customContextMenuRequested.connect(self.layerscolcontext_menu)

My Model class:

class ListModel(QStandardItemModel):
    # Model to be displayed in layerscol object
    # This model is the class setting up the data
    # to the format to be displayed in a QListView
    def __init__(self, items = None, parent=None):
        super().__init__(parent)
        items : ListModelItem
        self.items = items or []

    def print_item_names(self):
        for row in range(self.rowCount()):
            try:
                item = self.item(row)
                text = item.text()
                # pos = item.getPos()
                print("type=",type(item)," name=", text)
            except Exception:
                traceback.print_exc()

And My Model Item's class:

class ListModelItem(QStandardItem):
    id: int
    position: int
    newid = count()
    data: pd.DataFrame

    def __init__(self, df: pd.DataFrame, nid=None, name=None):
        super().__init__()
        if nid is not None:
            self.id = nid
            self.position = self.id
            self.newid = count(nid)
        else:
            self.id = next(self.newid)
        self.setText(name if name is not None else "Layer " + str(self.id))
        self.data = df
    def getPos(self):
        return self.position
    def setPos(self, npos):
        self.position = npos

I hope someone will find my question interest-ing and that I was clear enough. You're my only hope Guys. Thanks.

EDIT:

I added the clone function in my QListView subclass

def clone(self):
clone_item = ListModelItem(df=self.data,nid=self.id, name=self.text())
# Copy any additional attributes or properties you have in your ListModelItem
return clone_item

And a template to my ListModel:

# Create an instance of ListModelItem as a template
template_item = ListModelItem(pd.DataFrame(), name="Template Item")
self.setItemPrototype(template_item)

But for some reason the clone function take the template and thus delete my data and id attribute. I'm sure this is a simple fix but I can't find anything.

0

There are 0 best solutions below