I have a model QStandardItemModel
and subscribe to itemChanged()
signal, where I get the changed item.
Is there any way how to get value of changed item before this change?
QtCore.QObject.connect(self, QtCore.SIGNAL("itemChanged(QStandardItem *)"), self.sModelChanged)
Reference this answer in past. (Qt, C++)
Before read my answer, I show how to implement in pyqt4. It's not my idea, But I will show how to do that.
The class QtGui.QStandardItemModel
have only void itemChanged (QStandardItem*)
. So you have to create your custom signal itself.
1) For this case, I recommend to inheritance class QtGui.QStandardItemModel
to create own class to implement get value of changed item before this change.
2) Next, override bool QStandardItemModel.setData (self, QModelIndex index, QVariant value, int role = Qt.EditRole)
should be fine to track data changed (But it can't track in contractor initiated).
3) And create signal your own before set data;
Implemented example (PyQt4, Python);
import sys
from PyQt4 import QtGui, QtCore
class QNonStandardItemModel (QtGui.QStandardItemModel):
itemBeforeAndAfterChanged = QtCore.pyqtSignal(QtCore.QModelIndex, int, QtCore.QVariant, QtCore.QVariant)
def setData (self, indexQModelIndex, afterValueQVariant, role = QtCore.Qt.EditRole):
beforeValueQVariant = self.data(indexQModelIndex, role)
self.itemBeforeAndAfterChanged.emit(indexQModelIndex, role, beforeValueQVariant, afterValueQVariant)
return QtGui.QStandardItemModel.setData(self, indexQModelIndex, afterValueQVariant, role)
myQApplication = QtGui.QApplication([])
myQTreeView = QtGui.QTreeView()
headerQStandardItemModel = QNonStandardItemModel()
def callback (indexQModelIndex, role, beforeValueQVariant, afterValueQVariant):
print '#' * 80
print 'Before:', beforeValueQVariant.toString()
print 'After:', afterValueQVariant.toString()
print 'Role:', role
headerQStandardItemModel.itemBeforeAndAfterChanged.connect(callback)
headerQStandardItemModel.setHorizontalHeaderLabels([''] * 4)
myQTreeView.setModel(headerQStandardItemModel)
row1QStandardItem = QtGui.QStandardItem('ROW 1')
row1QStandardItem.appendRow([QtGui.QStandardItem(''), QtGui.QStandardItem('COLUMN 1'), QtGui.QStandardItem('COLUMN 2'), QtGui.QStandardItem('COLUMN 3')])
headerQStandardItemModel.appendRow(row1QStandardItem)
myQTreeView.show()
sys.exit(myQApplication.exec_())
There is no a standard way to get notified when QStandardItem
is changed. However, you can easily implement it:
- Create a new class inherited from
QStandardItem
.
- Reimplement
clone
to create this class objects from the model.
- Reimplement
setData
method and notify the item is changed. See below two ways how to do that.
- Set new class as prototype to the model (
setItemPrototype
).
There are two ways to go further:
- Inherit you item class from
QObject
also to emit a signal from setData
and subscribe to each item somewhere (I wouldn't do that).
- Add signal
itemAboutToChange
to QStandardItemModel
.
I expand on #2:
- Create a new class inherited from
QStandardItemModel
.
- Add macro
Q_OBJECT
and new signal itemAboutToChange(QStandardItem*)
- In
setData
of a class derived from QStandardItem
call the signal from the model.
Here is how to call the signal:
QMetaObject.invokeMethod(self.model(), "itemAboutToChange", Qt::DirectConnection, Q_ARG(QStandardItem*, self));