2010/3/2 Mark Summerfield <[email protected]>: > 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 >
Hello Mark, Thanks for your help, and specially for the great book you've written. It's been a really helpful source, very nice to read. It has saved me from quite a lot of endless trial and error loops! Back to the signals, I initially thought "rowsInserted" would be emitted as soon as the view entered editing mode, and since I needed something to reenable the controls - I had disabled them as soon in the beggining of addRecord - the idea was to use "dataChanged" because, since the model edit strategy was set to QSqlTableModel.OnRowChange, I thought it would be emitted only when the whole row was commited to the model. Anyway, your suggestion worked fine. Now I disable the buttons in the end of "addRecord" method, after calling edit on the view. Then I reenable the controls triggered by rowInserted signal, which happens really when the data is commited, so it reenables controls at the right time. By the way, I was using QSqlRelationalTableModel itself, not a subclass of it. Thank you! Cheers, Claudio _______________________________________________ PyQt mailing list [email protected] http://www.riverbankcomputing.com/mailman/listinfo/pyqt
