I am trying to restrict selection of a tree to a particular column.
I am using delegates heavily to create custom per-item-per-column behaviors, editors, etc. I was hop
The first interesting thing is that since Python can't overload a method, my select method seems to simply be called twice, once for each type in argument 0. Here is an example to illustrate this as well as the basic setup. My QTreeWidget's tree it called 'tree' (self.tree
)
# in __init__ of my QTreeWidget:
sel_model = ColumnSelectionModel(self.tree.model())
self.tree.setSelectionModel(sel_model)
class ColumnSelectionModel(QtGui.QItemSelectionModel):
def select(self, selection, selectionFlags):
"""
Runs both QItemSelectionModel.select methods::
1. select(QtCore.QModelIndex, QItemSelectionModel.SelectionFlags)
2. select(QtGui.QItemSelection, QItemSelectionModel.SelectionFlags)
The first seems to run on mouse down and mouse up.
The second seems to run on mouse down, up and drag
"""
print("select(%s, %s)" % (type(selection), type(selectionFlags)))
if isinstance(selection, QtGui.QItemSelection):
infos = []
for index in selection.indexes():
infos.append(("index=%s row=%s column=%s"
% (index, index.row(), index.column())))
print ", ".join(infos)
elif isinstance(selection, QtCore.QModelIndex):
index = selection
print("index=%s row=%s column=%s" % (index, index.row(), index.column()))
else:
raise Exception("Unexpected type for arg 0: '%s'" % type(selection))
super(ColumnSelectionModel, self).select(selection, selectionFlags)
This appears to solve my problem:
class ColumnSelectionModel(QtGui.QItemSelectionModel):
def __init__(self, model):
super(ColumnSelectionModel, self).__init__(model)
self.selectable_columns = [0]
""" Set the columns that are allowed to be selected """
def select(self, selection, selectionFlags):
"""
Ignores any selection changes if an item is not in one of the columns
in the self.selectable_columns list.
Is run by both QItemSelectionModel.select methods::
1. select(QtCore.QModelIndex, QItemSelectionModel.SelectionFlags)
2. select(QtGui.QItemSelection, QItemSelectionModel.SelectionFlags)
The first seems to run on mouse down and mouse up.
The second seems to run on mouse down, up and drag
"""
if isinstance(selection, QtGui.QItemSelection):
# This is the overload with the QItemSelection passed to arg 0
# Loop over all the items and if any are not in selectable_columns
# ignore this event. This works because it is run for every change
# so the offending selection index will always be the newest
indexes = selection.indexes()
for i in xrange(len(indexes)):
index = indexes[i]
if not index.column() in self.selectable_columns:
return
elif isinstance(selection, QtCore.QModelIndex):
# This is the overload with the QModelIndex passed to arg 0
# If this index isn't in selectable_columns, just ignore this event
index = selection
if not index.column() in self.selectable_columns:
return
else: # Just in case
raise Exception("Unexpected type for arg 0: '%s'" % type(selection))
# Fall through. Select as normal
super(ColumnSelectionModel, self).select(selection, selectionFlags)
In my final implementation, I plan to delegate the decision to my delegate system, making this generic and, in theory, able to dynamically ignore any index I want.