Search code examples
pythonqtableviewqlistviewqabstracttablemodelpyside2

One Model, two different views - PySide


I have QAbstractTableModel with 4 columns.

I'm trying to display the first 3 columns on a view (QTableView), and when a row is selected on such view a second view (a QListView) should display the 4th column of the model.

I found something about a QProxyModel, but I'm having a hard time wrapping my mind on it. Also there are a 'solutions' I found something similar HERE but somehow I want the inverse result.

The data I'm trying to dispaly is something like this: [['green', 'car', 'available',['a','b','c','d']]]

So, on the Table View it would show: green - car - available. And when clicking on such row, the List view would display the array on the last position: a - b - c - d.

I hope it makes sense.

Tips on directions, documentations, examples?

Thank you for your time.


Solution

  • For this particular case, using a proxy model is not appropriate, what should be done each time you click is to obtain the QModelIndex, with the QModelIndex we obtain the model and the row pressed so that at the end we obtain the saved list, this list we can pass it as a source to the model QStringListModel and we will establish this in the QListView. To hide the column we use hideColumn() of the QTableView.

    from PySide2.QtCore import *
    from PySide2.QtGui import *
    from PySide2.QtWidgets import *
    
    
    class TableModel(QAbstractTableModel):
        def __init__(self, *args, **kwargs):
            QAbstractTableModel.__init__(self, *args, **kwargs)
    
            self.values = [['green', 'car', 'available', ['a', 'b', 'c', 'd']],
                           ['red', 'airplane', 'available', ['b', 'c', 'd', 'e']],
                           ['yellow', 'boat', 'not available', ['c', 'd', 'e', 'f']]]
    
        def columnCount(self, parent=QModelIndex()):
            return 4
    
        def rowCount(self, parent=QModelIndex()):
            return len(self.values)
    
        def data(self, index, role=Qt.DisplayRole):
            if 0 <= index.row() < self.rowCount() and 0 <= index.column() < self.columnCount():
                if role == Qt.DisplayRole:
                    return self.values[index.row()][index.column()]
    
    
    class Widget(QWidget):
        def __init__(self, *args, **kwargs):
            QWidget.__init__(self, *args, **kwargs)
            splitter = QSplitter()
            self.tv = QTableView()
            self.lv = QListView()
            self.setLayout(QHBoxLayout())
            splitter.addWidget(self.tv)
            splitter.addWidget(self.lv)
            self.layout().addWidget(splitter)
            model = TableModel()
            self.tv.setModel(model)
            self.tv.hideColumn(3)
    
            self.tv.clicked.connect(self.on_clicked)
    
        def on_clicked(self, ix):
            model = ix.model()
            m_list = model.index(ix.row(), 3).data()
            self.lv.setModel(QStringListModel(m_list))
    
    
    if __name__ == '__main__':
        import sys
    
        app = QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())