Paul Jackways Paul Jackways - 2 months ago 18
Python Question

How do I get the information that the user has changed in a table in PyQT with Python and SQLite3

I have a table that comes up on my GUI. The user can edit this table from the GUI. how do I get all of the information that has been edited and update it in the database? The user checks the checkbox for each row they want to have updated to the database, so I have a list of all rows that require updating. I want to have a list of tuples, where each tuple is a row of new values that need to be updated, given that the ID field remains unchanged (I also want to know how to make the user unable to edit some fields).

def click_btn_mailouts(self):
self.screen_name = "mailouts"
self.cur.execute("""SELECT s.StudentID, s.FullName, m.PreviouslyMailed, m.nextMail, m.learnersDate, m.RestrictedDate, m.DefensiveDate FROM
StudentProfile s LEFT JOIN Mailouts m ON s.studentID=m.studentID""")
self.all_data = self.cur.fetchall()

self.table.setRowCount(len(self.all_data))
self.tableFields = ["Check","Full name","Previously mailed?","Next mail","learnersDate","Restricted date","Defensive driving date"]
self.table.setColumnCount(len(self.tableFields))
self.table.setHorizontalHeaderLabels(self.tableFields)
self.checkbox_list = []
for i, item in enumerate(self.all_data):
FullName = QtGui.QTableWidgetItem(str(item[1]))
PreviouslyMailed = QtGui.QTableWidgetItem(str(item[2]))
LearnersDate = QtGui.QTableWidgetItem(str(item[3]))
RestrictedDate = QtGui.QTableWidgetItem(str(item[4]))
DefensiveDate = QtGui.QTableWidgetItem(str(item[5]))
NextMail = QtGui.QTableWidgetItem(str(item[6]))
self.table.setItem(i, 1, FullName)
self.table.setItem(i, 2, PreviouslyMailed)
self.table.setItem(i, 3, LearnersDate)
self.table.setItem(i, 4, RestrictedDate)
self.table.setItem(i, 5, DefensiveDate)
self.table.setItem(i, 6, NextMail)
chkBoxItem = QtGui.QTableWidgetItem()
chkBoxItem.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
chkBoxItem.setCheckState(QtCore.Qt.Unchecked)
self.checkbox_list.append(chkBoxItem)
self.table.setItem(i, 0, self.checkbox_list[i])

"""here is the format that I have for the edit function"""

def click_btn_edit(self):
checkedRows = []
for i, checkbox in enumerate(self.checkbox_list):
if checkbox.checkState() == QtCore.Qt.Checked:
checkedRows.append(i)
"""as the list itterates, if the checkbox item is ticked,
it passes through the if statement, otherwise it is ignored.
checkedRows becomes a list of all the indexes in the table where
an edit needs to be made"""


So basically I need to know how to get the changes made in the QTableWidget in the GUI given a list of indexes where changes have been made, and somehow get those changes updated into the database. It would also be helpful to know how to stop the user from editing some of the fields, as that would mess up the database.

Answer

You can do a few different things.

To prevent editing, you can just remove the edit flag for the items you don't want the user to edit

FullName.setFlags(FullName.flags() & ~Qt.ItemIsEditable)

It looks like you're storing the original data (i.e. self.all_data). You could just compare the data in the selected table cells with the original data and only update fields that have changed.

You could also connect to the itemChanged signal for the table widget and keep a running list of all the indexes that have changed since the last refresh

    ...
    self.changed_items = set()
    self.table.itemChanged.connect(self.log_change)

def log_change(self, item):
    self.changed_items.add(item)

Alternatively, depending on how much control you want, you can also create a QItemDelegate to do all of this.

Comments