I am trying to implement a custom QTableView. For that I am subclassing QAbstractTableModel such that it takes a list of strings. Here the implementation.
class ListTableModel(qtc.QAbstractTableModel):
def __init__(self, data: List[List[str]], headers: List[str] = None, edit: List[Union[int, Tuple[int, int]]] = None,
checks: List[Union[int, Tuple[int, int]]] = None, *args, **kwargs):
super().__init__(*args, **kwargs)
self._data = data
self._headers = headers
self._edit = edit
self._checks = checks
self._check_state = {}
self.name = None
def get_name(self):
return self.name
def set_name(self, name: str):
self.name = name
def check_state(self, value, index):
if index in self._check_state:
return self._check_state[index]
else:
if value == 0:
return qtc.Qt.Unchecked
else:
return qtc.Qt.Checked
def data(self, index, role):
if index.isValid() or (0 <= index.row() < self.rowCount() and 0 <= index.column() < self.columnCount()):
val = self._data[index.row()][index.column()]
val = fast_real(val, coerce=False)
if (role == qtc.Qt.DisplayRole or role == qtc.Qt.EditRole) and not index.flags() & qtc.Qt.ItemIsUserCheckable:
if isinstance(val, float):
return f"{val:.4f}"
return str(val)
if role == qtc.Qt.CheckStateRole and index.flags() & qtc.Qt.ItemIsUserCheckable:
return self.check_state(val, index)
return None
return None
def setData(self, index, value, role):
if role == qtc.Qt.EditRole:
val = fast_real(value, coerce=False)
self._data[index.row()][index.column()] = val
return True
if role == qtc.Qt.CheckStateRole:
self._check_state[index] = value
return True
return False
def flags(self, index):
if self._edit is not None and index.column() in self._edit:
return qtc.Qt.ItemIsSelectable | qtc.Qt.ItemIsEnabled
if self._edit is not None and (index.row(), index.column()) in self._edit:
return qtc.Qt.ItemIsSelectable | qtc.Qt.ItemIsEnabled
if self._checks is not None and index.column() in self._checks:
return qtc.Qt.ItemIsSelectable | qtc.Qt.ItemIsEnabled | qtc.Qt.ItemIsUserCheckable
if self._checks is not None and (index.row(), index.column()) in self._checks:
return qtc.Qt.ItemIsSelectable | qtc.Qt.ItemIsEnabled | qtc.Qt.ItemIsUserCheckable
return qtc.Qt.ItemIsSelectable | qtc.Qt.ItemIsEnabled | qtc.Qt.ItemIsEditable
def rowCount(self, parent=None):
return len(self._data)
def columnCount(self, parent=None):
return len(self._data[0])
def headerData(self, section, orientation, role):
if role == qtc.Qt.DisplayRole:
if orientation == qtc.Qt.Horizontal and self._headers is not None:
return str(self._headers[section])
The class takes a list of list containing strings (representing the table). A list of strings representing the headers of the columns. The optional arguments edit
and checks
define which columns (if given as int) or cells (if given as tuple) are editable and checkable. The underlying data structure data
takes values of 0 if the corresponding checkbox is unchecked, or any other value if the corresponding checkbox is checked.
My first question is that the cells that are checkable actually show some extra space, apart from drawing the checkbox. A separating line in the middle of the cell is actually visible when selecting the cell. How can I eliminate this? In the data
method I control for cells that are checkable, and skip the display of the underlying data if it is. So I do not know how else to proceed here.
EXTRA: I would like to capture the signal that the model emits when any of the checkboxes are checked/unchecked. Any hint on this would be much appreciated as well.
Aucun commentaire:
Enregistrer un commentaire