Aashish_Gogna | 2022-08-09 11:10:54 UTC | #1
Hello Team,
I have created Qtreeview and Qtableview and set their models to respective Abstract classes. Functionality is: doubleclclicking on an element present in the treeview will create a new row in the tableview with some additional columns. One function in My code is to delete these entries when a button is clicked, which successfully deletes the entire table only once per run, and gives no result for further clicks on delete button even if the entries are present.
delete rows code is:
model.removeRows(position=0, rows=model.rowCount(0))
where removeRows function in tablemodel is written as:
def removeRows(self, position, rows=1, index=QtCore.QModelIndex()):
print(
"\n\t\t ...removeRows() Starting position: '%s'" % position, 'with the total rows to be deleted: ', rows)
self.beginRemoveRows(QtCore.QModelIndex(), position, position + rows - 1)
self.endRemoveRows()
Please suggest why the deletion activity deletes the rows only once per run and why the rowcount is always an increasing number even though the rows have already been deleted?
the code is :slight_smile:
Create GUI Applications with Python & Qt5 by Martin Fitzpatrick — (PyQt5 Edition) The hands-on guide to making apps with Python — Over 10,000 copies sold!
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data, data_header):
super().__init__()
self._data = data
self.header = data_header
def data(self, index, role):
if role == Qt.DisplayRole:
# See below for the nested-list data structure.
# .row() indexes into the outer list,
# .column() indexes into the sub-list
return self._data[index.column()][index.row()]
elif role == Qt.EditRole:
return self._data[index.column()][index.row()]
elif role == Qt.BackgroundRole:
# See below for the data structure.
value = self._data[index.column()][index.row()]
if index.column() == 6:
if value == "Not Started":
return QtGui.QColor("yellow")
elif value == "Started":
return QtGui.QColor("orange")
elif value == "Passed":
return QtGui.QColor("green")
elif value == "Failed":
return QtGui.QColor("red")
elif role == Qt.TextAlignmentRole:
value = self._data[index.column()][index.row()]
if isinstance(value, int) or isinstance(value, float):
# Align right, vertical middle.
return Qt.AlignVCenter + Qt.AlignRight
elif role == Qt.ForegroundRole:
value = self._data[index.column()][index.row()]
if (
(isinstance(value, int) or isinstance(value, float))
and value < 0
):
return QtGui.QColor('red')
else:
return QtCore.QVariant()
def flags(self, index):
if index.column() == 0 or index.column() == 1 or index.column() == 6 or index.column() == 7:
return Qt.ItemIsSelectable | Qt.ItemIsEnabled
else:
return Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable
def update(self, dataIn, data_header):
print('Updating Model')
self._data = dataIn
self.header = data_header
print('Datatable : {0}'.format(self._data))
def rowCount(self, index):
# The length of the outer list.
return len(self._data[0])
def columnCount(self, index):
# The following takes the first sub-list, and returns
# the length (only works if all rows are an equal length)
return len(self._data)
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.header[col]
return None
def setData(self, index, value, role=QtCore.Qt.EditRole):
if index.isValid() and 0 <= index.row():
if role == QtCore.Qt.EditRole:
self._data[index.column()][index.row()] = value
print("edit", value)
self.dataChanged.emit(index, index) # NOT WORKING
return True
else:
return False
else:
return False
@QtCore.pyqtSlot()
def addrow(self):
# print(self.rowCount(0))
self.beginInsertRows(QtCore.QModelIndex(), 0, 0)
ret = (self.insertRows(self.rowCount(0), 1))
self.endInsertRows()
# print(ret)
def removeRows(self, position, rows=1, index=QtCore.QModelIndex()):
print(
"\n\t\t ...removeRows() Starting position: '%s'" % position, 'with the total rows to be deleted: ', rows)
self.beginRemoveRows(QtCore.QModelIndex(), position, position + rows - 1)
# del self._data[position]
# self.items = self.items[:position] + self.items[position + rows:]
self.endRemoveRows()
def delete_row(self, index):
self.removeRows(index.row(), 1, QtCore.QModelIndex())
martin | 2021-07-23 14:47:09 UTC | #2
Hey! I'm a bit confused by your example code as there is nothing there to actually remove the data from the model. In the second (larger block) there are lines to do this, but they are commented out.
The beginRemoveRows
and endRemoveRows
is just there to notify the view that the data is being modified, you still need to make the modifications to the data yourself.
For a list of rows, you can just delete the start index n times (since subsequent elements will shift up). For example...
self.beginRemoveRows(QtCore.QModelIndex(), position, position + rows - 1)
for _ in range(rows):
del self._data[position]
self.endRemoveRows()