Search code examples
pythonqtableviewpyside2qstandarditemmodel

New feature for previous question PySide2 QListView and QTableView


The previous question was this.

EDITED TO PROVIDE INFO:

The model represents a dict of dicts, which they can inherit other dicts apart from key-value pairs:

dict_of_dicts={
'dict1':{'k1':'v1', 'k2':'v2', 'k3':'v3', 'EXISTING_DICT':'dict2'},
'dict2':{'k4':'v4'},
'dict3':{'k5':'v5', 'k6':'v6'},
}

being the qlistview:

*dict1
------
dict2
-----
dict3

and the qtableview with dict1 selected in the qlistview:

k1 | v1
-------
k2 | v2
-------
k3 | v3
-------
dict2

Is there a way to sort the model with first the inherited dicts on top, and then the dict elements?

dict2
-------
k1 | v1
-------
k2 | v2
-------
k3 | v3

And if we introduce new elements in the fly (I have way to introduce new elements in the interface), it get sorted no matter the order?

I was playing with QStandardItemModel sort and setSortRole(Qt.CheckStateRole)


Solution

  • Using my previous answer as a basis, It is necessary to use a QSortFilterProxyModel but we must use the role QtCore.Qt.UserRole + 1000, in addition we must modify the parts that I will point out with a comment:

    # ...
    
    class Widget(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Widget, self).__init__(parent)
            model = create_model_from_dict(dict_of_dicts, self)
    
            self.tableview = TableView()
            self.proxy_model = QtCore.QSortFilterProxyModel() # <---
            self.proxy_model.setSourceModel(model) # <---
            self.proxy_model.setSortRole(QtCore.Qt.UserRole + 1000) # <---
            self.proxy_model.sort(0, QtCore.Qt.AscendingOrder) # <---
            self.tableview.setModel(self.proxy_model) # <---
            self.tableview.leftDoubleClicked.connect(self.handleSelectionChangedTV)
    
            # ...
    
        @QtCore.Slot(QtCore.QItemSelection)
        def handleSelectionChangedLV(self, item):
            ixs = item.indexes()
            if ixs:
                pix = self.proxy_model.mapFromSource(ixs[0]) # <---
                self.tableview.setRootIndex(pix) # <---
                model = self.tableview.model()
                self.tableview.clearSpans()
                for r in range(model.rowCount(self.tableview.rootIndex())):
                    index = model.index(r, 0, self.tableview.rootIndex())
                    if index.data(QtCore.Qt.UserRole + 1000):
                        self.tableview.setSpan(r, 0, 1, 2)
    
    # ...