Skip to content Skip to sidebar Skip to footer

Add Feature For Previous Question PySide2 QListView And QTableView

The previous question was PySide2 QListView QTableView sync problem Imagine to have another dict4 in the data structure: 'dict4':{'k8':'v8', 'EXISTING_DICT':'dict2'}, Meaning, tha

Solution 1:

In this case the idea is to use a role to indicate that the field points to another item, then use setSpan to join items and finally check if the item selected in the QTableView points to another element by selecting if it is so

from PySide2 import QtCore, QtGui, QtWidgets

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

def create_model_from_dict(d, parent=None):
    model = QtGui.QStandardItemModel(0, 2, parent)
    for k, v in dict_of_dicts.items():
        it = QtGui.QStandardItem(k)
        model.appendRow(it)
        for k_, v_ in v.items():
            if k_ != "EXISTING_DICT":
                it.appendRow([QtGui.QStandardItem(k_), QtGui.QStandardItem(v_)])
            else:
                child_it = QtGui.QStandardItem(v_)
                child_it.setTextAlignment(QtCore.Qt.AlignCenter)
                child_it.setData(True, QtCore.Qt.UserRole + 1000)
                it.appendRow(child_it)
    return model

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 = QtWidgets.QTableView()
        self.tableview.setModel(model)
        self.tableview.selectionModel().selectionChanged.connect(self.handleSelectionChangedTV)

        self.listview = QtWidgets.QListView()
        self.listview.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
        self.listview.setModel(model)
        self.listview.selectionModel().selectionChanged.connect(self.handleSelectionChangedLV)
        self.listview.selectionModel().select(model.index(0, 0), QtCore.QItemSelectionModel.Select)

        hlay = QtWidgets.QHBoxLayout(self)
        hlay.addWidget(self.listview)
        hlay.addWidget(self.tableview)

    @QtCore.Slot(QtCore.QItemSelection)
    def handleSelectionChangedLV(self, item):
        ixs = item.indexes()
        if ixs:
            self.tableview.setRootIndex(ixs[0])
            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)

    @QtCore.Slot(QtCore.QItemSelection)
    def handleSelectionChangedTV(self, item):
        ixs = item.indexes()
        if ixs:
            ix = ixs[0]
            if ix.data(QtCore.Qt.UserRole + 1000):
                items = self.listview.model().findItems(ix.data())
                if items:
                    self.tableview.clearSelection()
                    self.listview.selectionModel().select(items[0].index(), QtCore.QItemSelectionModel.ClearAndSelect)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

UPDATE:

from PySide2 import QtCore, QtGui, QtWidgets

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

def create_model_from_dict(d, parent=None):
    model = QtGui.QStandardItemModel(0, 2, parent)
    for k, v in dict_of_dicts.items():
        it = QtGui.QStandardItem(k)
        model.appendRow(it)
        for k_, v_ in v.items():
            if k_ != "EXISTING_DICT":
                it.appendRow([QtGui.QStandardItem(k_), QtGui.QStandardItem(v_)])
            else:
                child_it = QtGui.QStandardItem(v_)
                child_it.setTextAlignment(QtCore.Qt.AlignCenter)
                child_it.setData(True, QtCore.Qt.UserRole + 1000)
                it.appendRow(child_it)
    return model

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 = QtWidgets.QTableView()
        self.tableview.setModel(model)
        self.tableview.doubleClicked.connect(self.handleSelectionChangedTV)

        self.listview = QtWidgets.QListView()
        self.listview.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
        self.listview.setModel(model)
        self.listview.selectionModel().selectionChanged.connect(self.handleSelectionChangedLV)
        self.listview.selectionModel().select(model.index(0, 0), QtCore.QItemSelectionModel.Select)

        hlay = QtWidgets.QHBoxLayout(self)
        hlay.addWidget(self.listview)
        hlay.addWidget(self.tableview)

    @QtCore.Slot(QtCore.QItemSelection)
    def handleSelectionChangedLV(self, item):
        ixs = item.indexes()
        if ixs:
            self.tableview.setRootIndex(ixs[0])
            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)

    @QtCore.Slot(QtCore.QModelIndex)
    def handleSelectionChangedTV(self, ix):
        if ix.data(QtCore.Qt.UserRole + 1000):
            items = self.listview.model().findItems(ix.data())
            if items:
                self.tableview.clearSelection()
                self.listview.selectionModel().select(items[0].index(), QtCore.QItemSelectionModel.ClearAndSelect)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

UPDATE2

from PySide2 import QtCore, QtGui, QtWidgets

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

def create_model_from_dict(d, parent=None):
    model = QtGui.QStandardItemModel(0, 2, parent)
    for k, v in dict_of_dicts.items():
        it = QtGui.QStandardItem(k)
        model.appendRow(it)
        for k_, v_ in v.items():
            if k_ != "EXISTING_DICT":
                it.appendRow([QtGui.QStandardItem(k_), QtGui.QStandardItem(v_)])
            else:
                child_it = QtGui.QStandardItem(v_)
                child_it.setTextAlignment(QtCore.Qt.AlignCenter)
                child_it.setData(True, QtCore.Qt.UserRole + 1000)
                it.appendRow(child_it)
    return model

class TableView(QtWidgets.QTableView):
    leftDoubleClicked = QtCore.Signal(QtCore.QModelIndex)

    def mouseDoubleClickEvent(self, event):
        super(TableView, self).mouseDoubleClickEvent(event)
        if event.buttons() & QtCore.Qt.LeftButton:
            ix = self.indexAt(event.pos())
            if ix.isValid(): self.leftDoubleClicked.emit(ix)

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.tableview.setModel(model)
        self.tableview.leftDoubleClicked.connect(self.handleSelectionChangedTV)

        self.listview = QtWidgets.QListView()
        self.listview.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
        self.listview.setModel(model)
        self.listview.selectionModel().selectionChanged.connect(self.handleSelectionChangedLV)
        self.listview.selectionModel().select(model.index(0, 0), QtCore.QItemSelectionModel.Select)

        hlay = QtWidgets.QHBoxLayout(self)
        hlay.addWidget(self.listview)
        hlay.addWidget(self.tableview)

    @QtCore.Slot(QtCore.QItemSelection)
    def handleSelectionChangedLV(self, item):
        ixs = item.indexes()
        if ixs:
            self.tableview.setRootIndex(ixs[0])
            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)

    @QtCore.Slot(QtCore.QModelIndex)
    def handleSelectionChangedTV(self, ix):
        if ix.data(QtCore.Qt.UserRole + 1000):
            items = self.listview.model().findItems(ix.data())
            if items:
                self.tableview.clearSelection()
                self.listview.selectionModel().select(items[0].index(), QtCore.QItemSelectionModel.ClearAndSelect)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

Post a Comment for "Add Feature For Previous Question PySide2 QListView And QTableView"