[PyQt] QAbstractItemModel's "dataChanged" signal not working?
Mark Summerfield
list at qtrac.plus.com
Tue Mar 2 09:45:16 GMT 2010
On 2010-02-27, Claudio Felix wrote:
> Hi everyone,
>
> I'm using a QSqlRelationalTableModel for a simple dialog where I can
> add/delete periods related to a particular customer, which is chosen
> by a QComboBox. The periods table is filtered by customer (whose ID is
> a foreign key) and shown through a QTableView. There's an "Add" button
> which basically inserts a new row in the Periods table and sets the
> view to edit mode, so the period data can be entered:
>
> def addRecord(self):
> row = self.model.rowCount()
> customerid = self._getRecordID(self.customerComboBox,
> self.customersModel, "CUSTOMER_ID")
> self.enableControls(False)
> self.model.insertRow(row)
> index = self.model.index(row, CUSTOMER_ID)
> self.model.setData(index, QVariant(customerid))
> index = self.model.index(row, PERIOD_YEAR)
> self.periodsTableView.setCurrentIndex(index)
> self.periodsTableView.edit(index)
>
> I noticed that, while the view is in edit mode (with the asterisk '*'
> appearing in the leftmost field), if the user clicks on the add button
> again, an empty row appears in the view and the asterisk appears in
> the next row, with this message on the console:
>
> edit: index was invalid
> edit: editing failed
>
> The same problem happens in the "assetmanager.pyw" example from the
> (great!) book "Rapid GUI Programming with Python and QT", which is my
> main guide. That way, in my limited experience with PyQT, I tried to
> work around the undesirable behavior creating the method
> "enableControls" for the dialog, which is called in the addRecord
> method so it makes it impossible for the user to click on "add" again
> while the view is in edit mode. The idea then was to re-enable the
> controls when the data was finally committed by the view. That's when
> the main problem comes up. I tried to use the model's "dataChanged"
> signal for calling my "enableControls" method, but it looks like it
> never gets emitted, although the record does get written to the
> database table. Does anybody can confirm that or help me avoiding the
> problem at all? I used the following signature for the signal, exactly
> the same shown on QAbstractItemModel's documentation:
>
> self.connect(self.model, SIGNAL("dataChanged(const QModelIndex&,const
> QModelIndex&)"), self.enableControls)
>
> That line is declared in my dialog's __init__, along with all the
> other (working) signals. self.model referes to the
> QSqlRelationalTableModel.
>
> Thanks for any help!
Hi Claudio,
I must admit that I've grown very frustrated with Qt's database support,
particularly with SQLite. I've found that the book's database examples
(which all use SQLite since that is supplied with Qt) exhibit varying
differences in behavior depending on the Qt version.
Regarding your specific problem, I can't see anything obviously wrong
with your connection. Personally, I would have written it as
self.connect(self.model, SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
self.enableControls)
but that should make no difference.
Is your model a QSqlRelationalTableModel or a subclass? If it is a
subclass and you have reimplemented setData() then you must emit the
dataChanged() signal in your reimplemented setData() method. But if
you're using QSqlRelationalTableModel directly then it isn't obvious to
me what you're doing wrong. However, dataChanged() might be the wrong
signal for reenabling the Add button since it is emitted for every
change to every field, whereas I'd have thought you wanted to enable the
Add button only when the record was inserted? So maybe you could try
connecting to the QAbstractItemModel::rowsInserted() signal?
I had a quick go at changing assetmanager.pyw to do this but without
success (using PyQt 4.6 and Qt 4.5.2); maybe things have improved with
Qt 4.6.
--
Mark Summerfield, Qtrac Ltd, www.qtrac.eu
C++, Python, Qt, PyQt - training and consultancy
"C++ GUI Programming with Qt 4" - ISBN 0132354160
More information about the PyQt
mailing list