当前,我正在创建一个QTreeView,其中第三列委托设置为ComboBox进行编辑。但是,我想让用户能够使用给定的数据切换不同的视图,如下图所示。您如何建议我处理将ComboBox分配给指定单元格的正确行/列,如下图所示?
平面列表版本效果很好,我不确定如何处理其他显示选项。
是否有一种方法可以设置为每行/列提供QComboBox作为编辑器的委托?
import os, sys, pprint
sys.path.append(os.environ.get('PS_SITEPACKAGES'))
from Qt import QtGui, QtWidgets, QtCore
import pprint
class VersionProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
super(VersionProxyModel, self).__init__(*args, **kwargs)
self.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
def checkParents(self, index):
while (index.isValid()):
if super(VersionProxyModel, self).filterAcceptsRow(index.row(), index.parent()):
return True
index = index.parent()
return False
def checkChildren(self, index):
for i in range(0, self.sourceModel().rowCount(index)):
if super(VersionProxyModel, self).filterAcceptsRow(i, index):
return True
# recursive
for i in range(0, self.sourceModel().rowCount(index)):
self.checkChildren(self.sourceModel().index(i, 0, index))
return False
def filterAcceptsRow(self, source_row, parent):
if super(VersionProxyModel, self).filterAcceptsRow(source_row, parent):
return True
if self.checkChildren(self.sourceModel().index(source_row, 0, parent)):
return True
return self.checkParents(parent)
class ComboBoxDelegate(QtWidgets.QStyledItemDelegate):
def paint(self, painter, option, index):
if isinstance(self.parent(), QtWidgets.QAbstractItemView):
self.parent().openPersistentEditor(index)
super(ComboBoxDelegate, self).paint(painter, option, index)
def createEditor(self, parent, option, index):
editor = QtWidgets.QComboBox(parent)
editor.currentIndexChanged.connect(self.commitEditor)
return editor
@QtCore.Slot()
def commitEditor(self):
editor = self.sender()
self.commitData.emit(editor)
if isinstance(self.parent(), QtWidgets.QAbstractItemView):
self.parent().updateEditorGeometries()
def setEditorData(self, editor, index):
values = index.data(QtCore.Qt.UserRole + 100)
val = index.data(QtCore.Qt.UserRole + 101)
editor.clear()
for i, x in enumerate(values):
editor.addItem(x['fullname'], x)
if val['fullname'] == x['fullname']:
editor.setCurrentIndex(i)
def setModelData(self, editor, model, index):
values = index.data(QtCore.Qt.UserRole + 100)
ix = editor.currentIndex()
model.setData(index, values[ix] , QtCore.Qt.UserRole + 101)
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
class Window(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.resize(800, 400)
self.FLATLIST = {
'Leslie': [
{'fullname': 'medic_skin_v001', 'entity': 'Medic', 'type': 'Bulky'}
],
'Mike': [
{'fullname': 'tech_skin_v001', 'entity': 'Tech', 'type': 'Average'},
{'fullname': 'tech_skin_v002', 'entity': 'Tech', 'type': 'Average'}
],
'Kevin': [
{'fullname': 'tech_skin_v001', 'entity': 'Tech', 'type': 'Average'},
],
'Michelle': [
{'fullname': 'warrior_skin_v001', 'entity': 'Warrior', 'type': 'Athletic'},
{'fullname': 'warrior_skin_v002', 'entity': 'Warrior', 'type': 'Athletic'},
{'fullname': 'warrior_skin_v003', 'entity': 'Warrior', 'type': 'Athletic'}]
}
self.uiDisplayA = QtWidgets.QPushButton('Display Flat List')
self.uiDisplayA.clicked.connect(self.slotDisplayA)
self.uiDisplayB = QtWidgets.QPushButton('Display Grouped By Entity')
self.uiDisplayB.clicked.connect(self.slotDisplayB)
self.uiSearch = QtWidgets.QLineEdit()
self.versionModel = QtGui.QStandardItemModel()
self.versionProxyModel = VersionProxyModel()
self.versionProxyModel.setSourceModel(self.versionModel)
self.versionProxyModel.setDynamicSortFilter(True)
self.uiVersionTreeView = QtWidgets.QTreeView()
self.uiVersionTreeView.sortByColumn(0, QtCore.Qt.AscendingOrder)
self.uiVersionTreeView.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.uiVersionTreeView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.uiVersionTreeView.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.uiVersionTreeView.setModel(self.versionProxyModel)
# self.uiVersionTreeView.setRootIsDecorated(False)
delegate = ComboBoxDelegate(self.uiVersionTreeView)
self.uiVersionTreeView.setItemDelegateForColumn(3, delegate)
# layout
self.displayLayout = QtWidgets.QHBoxLayout()
self.displayLayout.addWidget(self.uiDisplayA)
self.displayLayout.addWidget(self.uiDisplayB)
self.layout = QtWidgets.QVBoxLayout()
self.layout.addLayout(self.displayLayout)
self.layout.addWidget(self.uiSearch)
self.layout.addWidget(self.uiVersionTreeView)
self.setLayout(self.layout)
# signals/slots
self.uiSearch.textChanged.connect(self.versionProxyModel.setFilterWildcard)
self.slotDisplayA()
def group_by_entity(self, items):
grouped = {}
for k, v in items.items():
if not v: continue
key = v[0].get('entity', 'unknown')
if key not in grouped.keys():
grouped[key] = {}
grouped[key][k] = v
return grouped
def slotDisplayA(self):
sortColumn = self.uiVersionTreeView.header().sortIndicatorSection()
sortDirection = self.uiVersionTreeView.header().sortIndicatorOrder()
self.versionModel.clear()
self.uiVersionTreeView.setSortingEnabled(False)
self.versionModel.setHorizontalHeaderLabels(['Entity', 'Type', 'Name', 'Versions'])
for key, values in self.FLATLIST.items():
col1 = QtGui.QStandardItem(values[0]['entity'])
col2 = QtGui.QStandardItem(values[0]['type'])
col3 = QtGui.QStandardItem(key)
col4 = QtGui.QStandardItem()
self.versionModel.appendRow([col1, col2, col3, col4])
col2.setData(QtGui.QColor(80,150,200), role=QtCore.Qt.ForegroundRole)
col4.setData(values, QtCore.Qt.UserRole + 100)
col4.setData(values[0], QtCore.Qt.UserRole + 101)
# Restore
self.uiVersionTreeView.setSortingEnabled(True)
self.uiVersionTreeView.sortByColumn(sortColumn, sortDirection)
self.uiVersionTreeView.expandAll()
for i in range(self.versionModel.columnCount()):
self.uiVersionTreeView.resizeColumnToContents(i)
def slotDisplayB(self):
sortColumn = self.uiVersionTreeView.header().sortIndicatorSection()
sortDirection = self.uiVersionTreeView.header().sortIndicatorOrder()
self.versionModel.clear()
self.uiVersionTreeView.setSortingEnabled(False)
self.versionModel.setHorizontalHeaderLabels(['Type', 'Name', 'Versions'])
# add each entity
ENTIYLIST = self.group_by_entity(self.FLATLIST)
pprint.pprint(ENTIYLIST, indent=4)
for key, values in ENTIYLIST.items():
parent = QtGui.QStandardItem(key)
self.versionModel.appendRow(parent)
# add entity children
for childKey, childValues in values.items():
child1 = QtGui.QStandardItem(childValues[0]['type'])
child2 = QtGui.QStandardItem(childKey)
child3 = QtGui.QStandardItem()
parent.appendRow([child1, child2, child3])
child1.setData(QtGui.QColor(80,150,200), role=QtCore.Qt.ForegroundRole)
# Restore
self.uiVersionTreeView.setSortingEnabled(True)
self.uiVersionTreeView.sortByColumn(sortColumn, sortDirection)
self.uiVersionTreeView.expandAll()
for i in range(self.versionModel.columnCount()):
self.uiVersionTreeView.resizeColumnToContents(i)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = Window()
ex.show()
app.exec_()