Consider this little snippet:
import sys
from PyQt5 import QtWidgets
from PyQt5 import QtWidgets
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtGui import QStandardItem
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QGridLayout
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QTreeView
from PyQt5.QtWidgets import QAbstractItemView
packages = {
'tree': {
'parent1': ['child1', 'child2', 'child3'],
'parent2': ['child4', 'child5'],
'parent3': ['child6']
},
'metadata': {
'child1': {'description': 'child1 description', 'enabled': True},
'child2': {'description': 'child2 description', 'enabled': False},
'child3': {'description': 'child3 description', 'enabled': True},
'child4': {'description': 'child4 description', 'enabled': False},
'child5': {'description': 'child5 description', 'enabled': True},
'child6': {'description': 'child6 description', 'enabled': True}
}
}
class McveDialog(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.treeview = QTreeView()
# self.treeview.setHeaderHidden(True)
self.treeview.setUniformRowHeights(True)
# self.treeview.setEditTriggers(QAbstractItemView.NoEditTriggers)
# self.treeview.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.model = QStandardItemModel()
self.model.setHorizontalHeaderLabels(['Package', 'Description'])
metadata = packages['metadata']
tree = packages['tree']
for parent, childs in tree.items():
parent_item = QStandardItem(f'{parent}')
parent_item.setCheckState(True)
parent_item.setCheckable(True)
parent_item.setFlags(parent_item.flags() | Qt.ItemIsAutoTristate)
# parent_item.setFlags(parent_item.flags() | Qt.ItemIsUserTristate)
self.model.appendRow(parent_item)
for child in childs:
description = metadata[child]['description']
checked = metadata[child]['enabled']
child_item = QStandardItem(f'{child}')
check = Qt.Checked if checked else Qt.Unchecked
child_item.setCheckState(check)
child_item.setCheckable(True)
# child_item.setFlags(child_item.flags() |Qt.ItemIsAutoTristate)
parent_item.appendRow(child_item)
self.treeview.setModel(self.model)
self.model.itemChanged.connect(self.on_itemChanged)
layout = QGridLayout()
row = 0
layout.addWidget(self.treeview, row, 0, 1, 3)
row += 1
self.but_ok = QPushButton("OK")
layout.addWidget(self.but_ok, row, 1)
self.but_ok.clicked.connect(self.on_ok)
self.but_cancel = QPushButton("Cancel")
layout.addWidget(self.but_cancel, row, 2)
self.but_cancel.clicked.connect(self.on_cancel)
self.setLayout(layout)
self.setGeometry(300, 200, 460, 350)
def on_itemChanged(self, item):
pass
def on_ok(self):
pass
def on_cancel(self):
self.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
dialog = McveDialog()
dialog.setWindowTitle('Mcve dialog')
dialog.show()
sys.exit(app.exec_())
What I'm trying to achieve here, is that when a user selects all of a parent's children, the parent state becomes checked; if all the children are deselected, then the parent state becomes deselected; and finally if some of the children are selected, then the parent becomes partially checked. (And vice-versa, so if the user deselects a parent, all its children will be deselected, and if a user selects a parent, all its children will become selected).
In theory, this behaviour should be achieved by using Qt::ItemIsAutoTristate flag, which says:
The item's state depends on the state of its children. This enables automatic management of the state of parent items in QTreeWidget (checked if all children are checked, unchecked if all children are unchecked, or partially checked if only some children are checked).
But if you run the code above, you'll see the behaviour is not the one you'd expect after reading the docs. I've seen there is this bugreport, although i'm not sure if it's related to this, or if my snippet is just missing some stuff.
For instance, the above snippet allows you to do this:
Anyway, the question would be, how would you fix this widget so it'll behave as any package installer, where you can select/unselect/partially-select all subpackages at once having a common parent?
Aucun commentaire:
Enregistrer un commentaire