PyQt4 - How can I store the value of a QTableWidget cell before cellChanged signal is emitted
-
I am writing a program that uses
QTableWidget
as a front-end for an sqlite database.When any cell of the table is changed, it emits a
cellChanged
signal that updates the database.However, I now need to check the new value of the cell against a variable that is stored in the program, and if it goes through, the new value is approved, but if it doesn't, the old value of the cell is restored.
Here is an example code of what I want to do:
#!/usr/bin/python3 import sys from PyQt4 import QtCore, QtGui app = QtGui.QApplication(sys.argv) table = QtGui.QTableWidget() def update_db(row, col): old_value = SOME_WAY_TO_STORE_THE_OLD_VALUE_OF_THE_CELL new_value = table.item(row, col).text() if new_value == VARIABLE: pass else: table.item(row, col).setText(old_value) table.cellChanged.connect(update_db) table.show() sys.exit(app.exec_())
I have found this solution, which relies on subclassing the
QStandardItemModel
to store the old value of an item in aQTreeView
. This would work with theQTableView
as well.But this solution doesn't work with the
QTableWidget
, because itssetModel()
function is a private method, not public.The problem is, going back to use the
QTableView
is going to waste a lot of time for me, as I have already usedQTableWidget
in a lot of parts of the program.One workaround that solves the problem for me in all but one case is using the
currentCellChanged
signal to call a function that stores the cell's value. This relies on the fact that the user will need to navigate to the cell to be able to change its value.However, this won't work if the user decides to change the cell that is already selected.
Is there a way for me to achieve what I want without going back and replacing all instances of
QTableWidget
withQTableView
. -
Hi and welcome to devnet,
So basically, your user can only change to that variable value or keep the current, correct ?
-
Hi @SGaist.. Thank you very much.
The user isn't even changing to the variable value. I used this bit
if new_value == VARIABLE:
in the original post just as an example, because I didn't think it will make much difference.Seeing that it might do, let me explain more explicitly what I need to do. Initially, when the user inputs the very first data into the cell, as I said, the database is updated, and a file is created named exactly as the text that the user entered.
Therefore, when the user wants to change that cell again, I would like to show a
QMessageBox
that confirms if the user actually wants that change or not.The variable I mentioned in the original post is basically the user's response to the message box.
If the user confirms the change, then the original file will be deleted, the new value will be kept, and a new file will be created.
But if the user doesn't actually want the change to happen, then the old value will be restored.
So, a more accurate example code would be something like that:
if user_input == 'yes': pass else: table.item(row, col).setText(old_value)
I hope this clarifies my intent and sorry for any confusion I might have caused.
-
Then it sounds like you should implement a custom QStyledItemDelegate, do your validation in the setModelData.
-
Thanks for the help @SGaist.. any ideas where I can find good examples of how to use the
QStyledItemDelegate
with theQTableWidget
, as I can't seem to find any.Also, someone on StackOverflow suggested implementing an Undo/Redo framework and using it to restore the original value. However, I am not sure if that would work well with what I want to do.
What do you think?
-
I keep finding examples of how to customize the
QStyledItemDelegate
, but they are all in c++, and frankly, I know nothing about c++.This example, for instance, goes into creating a custom delegate and overriding the
setModelData()
, but I am not able to translate it into PyQt.All I can find is the PyQt class references which, of course, do not explain how to use the delegates in a real scenario.
-
It's essentially the same, most of the time you have some translation to do from one language to the other, but the logic is exactly the same.