One way to achieve this is to subclass QTableWidgetItem and re-implement the setData method. That way, you can control whether items accept values for certain roles.
To control the "checkability" for all items, you could add a class attribute to the subclass which could be tested whenever a value for the check-state role was passed to setData.
Here's what the subclass might look like:
class TableWidgetItem(QtGui.QTableWidgetItem):
_blocked = True
@classmethod
def blocked(cls):
return cls._checkable
@classmethod
def setBlocked(cls, checkable):
cls._checkable = bool(checkable)
def setData(self, role, value):
if role != QtCore.Qt.CheckStateRole or self.checkable():
QtGui.QTableWidgetItem.setData(self, role, value)
And the "checkability" of all items would be disabled like this:
TableWidgetItem.setCheckable(False)
UPDATE:
The above idea can be extended by adding a generic wrapper class for cell widgets.
The classes below will block changes to text and check-state for table-widget items, and also a range of keyboard and mouse events for cell widgets via an event-filter (other events can be blocked as required).
The cell-widgets would need to be created like this:
widget = CellWidget(self.table, QtGui.QLineEdit())
self.table.setCellWidget(row, column, widget)
and then accessed like this:
widget = self.table.cellWidget().widget()
Blocking for the whole table would be switched on like this:
TableWidgetItem.setBlocked(True)
CellWidget.setBlocked(True)
# or Blockable.setBlocked(True)
Here are the classes:
class Blockable(object):
_blocked = False
@classmethod
def blocked(cls):
return cls._blocked
@classmethod
def setBlocked(cls, blocked):
cls._blocked = bool(blocked)
class TableWidgetItem(Blockable, QtGui.QTableWidgetItem):
def setData(self, role, value):
if (not self.blocked() or (
role != QtCore.Qt.EditRole and
role != QtCore.Qt.CheckStateRole)):
QtGui.QTableWidgetItem.setData(self, role, value)
class CellWidget(Blockable, QtGui.QWidget):
def __init__(self, parent, widget):
QtGui.QWidget.__init__(self, parent)
self._widget = widget
layout = QtGui.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(widget)
widget.setParent(self)
widget.installEventFilter(self)
if hasattr(widget, 'viewport'):
widget.viewport().installEventFilter(self)
widget.show()
def widget(self):
return self._widget
def eventFilter(self, widget, event):
if self.blocked():
etype = event.type()
if (etype == QtCore.QEvent.KeyPress or
etype == QtCore.QEvent.KeyRelease or
etype == QtCore.QEvent.MouseButtonPress or
etype == QtCore.QEvent.MouseButtonRelease or
etype == QtCore.QEvent.MouseButtonDblClick or
etype == QtCore.QEvent.ContextMenu or
etype == QtCore.QEvent.Wheel):
return True
return QtGui.QWidget.eventFilter(self, widget, event)