1

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)

eddy2k
  • 119
  • 1
  • 12

1 Answers1

1

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)

# ...
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Amazing!! I didn't understand anything (didn't get still the role stuff since the beginning and now the proxymodel), but it is amazing!! Thanks!! – eddy2k Jan 22 '19 at 21:00
  • @eddy2k use `def getFirstSibling(self) ixs = self.tableview.selectedIndexes() if ixs: model_index = ixs[0] sibling_ix = model_index.sibling(model_index.row(), 1) return sibling_ix.data()` – eyllanesc Jan 22 '19 at 22:59
  • @eddy2k remember that the QTableView model is no longer the QStandardItemModel but the QSortFilterProxyModel so the latter no longer has the itemFromIndex method, so instead of going the long way to get the QStandardItem you can access the text through the QModelIndex using the method data. read http://doc.qt.io/qt-5/qabstractproxymodel.html – eyllanesc Jan 22 '19 at 23:02
  • Really useful! Thanks!! – eddy2k Jan 22 '19 at 23:16
  • Can you help me with this one sir? https://stackoverflow.com/questions/54262785/text-styling-in-qtableview-with-pyside2 – eddy2k Jan 22 '19 at 23:38