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"