I currently have a QListWidget that displays many items that are user selectable (and dragable). In my application, when an item is checked it will be reordered above the unchecked items. The user can also drag/drop to adjust the order of the checked items.
The problem the users have is that there are a TON of these check boxes and they are not grouped logically on the screen. Thus, I'd like to introduce grouping of some kind. Here is an example of how it currently works.
from PyQt4 import QtGui, QtCore
import sys
rows = [
{'text': 'Row1', 'value': 1, 'group': 1},
{'text': 'Row2', 'value': 2, 'group': 1},
{'text': 'Row3', 'value': 3, 'group': 1},
{'text': 'Row4', 'value': 4, 'group': 2},
{'text': 'Row5', 'value': 5, 'group': 2},
{'text': 'Row6', 'value': 6, 'group': 3},
{'text': 'Row7', 'value': 7, 'group': 3},
{'text': 'Row8', 'value': 8, 'group': 3},
{'text': 'Row9', 'value': 9, 'group': 2},
{'text': 'Row10', 'value': 10, 'group': 'testing'}
]
class MyList(QtGui.QListWidget):
def __init__(self):
QtGui.QListWidget.__init__(self)
for row in rows:
item = QtGui.QListWidgetItem(row['text'])
# These are utilizing the ItemDataRole; 33 and 34 are among the first user defined values
# http://pyqt.sourceforge.net/Docs/PyQt4/qt.html#ItemDataRole-enum
item.setData(33, row['value'])
item.setData(34, row['group'])
item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
item.setCheckState(QtCore.Qt.Unchecked)
self.addItem(item)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
my_list = MyList()
my_list.show()
sys.exit(app.exec_())
This produces an application like this:
What I want to do is group the items that have similar groups under a similar heading. When an item is checked, it'd appear above the groups. Initially, this looks like a QTreeWidget/View, except that the checked items need to appear outside of the existing tree.
Example (text output):
[CHECKED ITEMS APPEAR HERE]
Group 1
Row1
Row2
Row3
Group 2
Row4
Row5
Row9
Group 3
Row6
Row7
Row8
Group testing
Row10
Is there a way to group items in a QListWidget, preferable so that the 'header' can be selected and all child elements can be autoselected?
to list items in groups here a simalar question: How to list items as groups in QListWidget
if headeritems and normal items are different in one property they can be handled differently in slot. I'm not quite certain, if it's the way you want. I tried to place checked items on the top and select all items of a group by click on the headeritem.
By selecting another signal and modyfiing the slot there are many possibilities, to change the behaviour. Here my code (i tried it in PyPt5 by replacing QtGui by QtWidgets
from PyQt4 import QtGui, QtCore
import sys
rows = [
{'text': 'Row1', 'value': 1, 'group': 1},
{'text': 'Row2', 'value': 2, 'group': 1},
{'text': 'Row3', 'value': 3, 'group': 1},
{'text': 'Row4', 'value': 4, 'group': 2},
{'text': 'Row5', 'value': 5, 'group': 2},
{'text': 'Row6', 'value': 6, 'group': 3},
{'text': 'Row7', 'value': 7, 'group': 3},
{'text': 'Row8', 'value': 8, 'group': 3},
{'text': 'Row9', 'value': 9, 'group': 2},
{'text': 'Row10', 'value': 10, 'group': 'testing'}
]
grouptitles = [1, 2, 3,'testing'] # list of grouptitles
def gruppe(d): # function for sorting the itemlist
return str(d['group'])
rows.sort(key=gruppe,reverse=False) # sort rows by groups
class MyList(QtGui.QListWidget):
def __init__(self):
QtGui.QListWidget.__init__(self)
self.setMinimumHeight(270)
for t in grouptitles:
item = QtGui.QListWidgetItem('Group {}'.format(t))
item.setData(33, 'header')
item.setData(34, t)
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
self.addItem(item)
for row in rows:
if row['group'] == t:
item = QtGui.QListWidgetItem(row['text'])
# These are utilizing the ItemDataRole; 33 and 34 are among the first user defined values
# http://pyqt.sourceforge.net/Docs/PyQt4/qt.html#ItemDataRole-enum
item.setData(33, row['value'])
item.setData(34, row['group'])
item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
item.setCheckState(QtCore.Qt.Unchecked)
self.addItem(item)
else:
pass
self.setSelectionMode(QtGui.QAbstractItemView.MultiSelection) #
self.itemClicked.connect(self.selManager) # select an appropriate signal
def selManager(self, item):
if item.data(33) == 'header':
groupcode = item.data(34)
for i in range(0,self.count()):
if self.item(i).data(34) == groupcode and self.item(i).data(33) != 'header':
b = True if self.item(i).isSelected() == False else False
self.item(i).setSelected(b)
else:
if item.checkState() == QtCore.Qt.Unchecked:
item.setCheckState(QtCore.Qt.Checked)
self.moveItem(self.currentRow(),0)
else:
item.setCheckState(QtCore.Qt.Unchecked)
text = 'Group {}'.format(item.data(34))
new = self.indexFromItem(self.findItems(text, QtCore.Qt.MatchExactly)[0]).row() # find the row of the headeritem
self.moveItem(self.currentRow(), new) # moving back to group
def moveItem(self, old, new): # from row(old) to row(new)
ni = self.takeItem(old)
self.insertItem(new,ni)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
my_list = MyList()
my_list.show()
sys.exit(app.exec_())