PDA

View Full Version : Edit TableView Content



emorgen
1st June 2010, 16:55
Hi,

I'm trying to figure out how to edit the content of a qtableview.

I have a QTableView which displays sqlite data from a QSqlQuery.


QSqlQuery query("SELECT * FROM IdentityLog", db);
while (query.next()) {

int event = query.value(3).toInt();

switch ( event )
{
case 1:
//set value;
break;
case 2:
//set value
break;
default:
break;
}
}

model->setQuery( query );
}

Where and how do I set the value. I do not want to edit the database, only the table. I've been reading through the classes for QTableView and for QSqlQuery but I can't figure out how to modify the value at a certain index.

Any help is greatly appreciated. Thanks in advance!

Emorgen

CeeKey
1st June 2010, 17:25
Hi emorgen,

you have to use QAbstractTableModel or QSqlQueryModel to set values into QTableView. If you inherent from one of that model, you have to override the data() method to set the values. Maybe this will help you: http://doc.trolltech.com/4.6/itemviews-addressbook.html

JD2000
1st June 2010, 18:50
As an aside, QT does not guarantee to order that data is returned in when using 'SELECT *' so value(3) may not always be what you expect.

emorgen
1st June 2010, 20:44
I am using a QSqlQueryModel and I look at the record() function and it returns a QSqlRecord. QSqlRecord has a setValue member that says it can be used if the content is not read only.

I check and my data is not set to read only, yet everytime I try and use setValue it does not modify my tables.


you have to use QAbstractTableModel or QSqlQueryModel to set values into QTableView. If you inherent from one of that model, you have to override the data() method to set the values.
I have started working on a new class that does this and it should work but I am still curious if this is necessary. It seems like QSqlQueryModel has the capabilities to edit it's data.


Thanks,

Emorgen

Coises
2nd June 2010, 02:26
Where and how do I set the value. I do not want to edit the database, only the table.

Let me be sure I understand what you want. You want to display data from an SQL query to the user in a QTableView. You want the user to be able to edit the displayed data in table view. You don’t want any changes the user makes to affect the database copy, though... just the information to be used in this instance of the running program. Is that correct?

It strikes me that the simplest way to do that would be to select the data you need into a new, temporary database table, then access that table using a QSqlTableModel (not a QSqlQueryModel).


I am using a QSqlQueryModel and I look at the record() function and it returns a QSqlRecord. QSqlRecord has a setValue member that says it can be used if the content is not read only.

The first sentence of the documentation for QSqlQueryModel states that it provides a read-only data model. You can’t change data through that model.

You could subclass that model to allow for changing data, but QSqlTableModel already does that. The thing that’s different about your case (if I’ve understood correctly) is that you want to keep the edited values separate from the original table, letting them “override” the values in the database only for the current run of the program, then discarding them. Doing this by subclassing QSqlQueryModel would require building your own mini-database of the changed values and making sure the data function in your subclass returns the edited value when there is one, but falls back to the database value for items that were not edited. In my opinion, it would be much simpler to make a temporary table that can be discarded when your program finishes, then use an editable model (QSqlTableModel) to access that table, unless there is some good reason you can’t use a temporary table.

Coises
2nd June 2010, 12:54
I do not want to edit the database, only the table.

My earlier post was incorrect about needing a temporary table; you can use QSqlTableModel::setEditStrategy(QSqlTableModel::On ManualSubmit (http://doc.qt.nokia.com/latest/qsqltablemodel.html#EditStrategy-enum)) to have the model cache the edits for you, then call QSqlTableModel::revertAll() to discard them.

Use QSqlTableModel::setData to change data in the model from your program.

emorgen
2nd June 2010, 22:03
The first sentence of the documentation for QSqlQueryModel states that it provides a read-only data model. You can’t change data through that model.
Strange, I checked the isReadOnly and it said false. I guess the copy is editable so it edits the copy but will not alter the original.

I originally was using a QSqlTableModel but I went to a query because I want to add restrictions to the table. I was afraid it will still attempt to read the database before the filter which could be costly.

Anyway, I'll give it a try and let you know how it goes. Thanks for the suggestions.

Coises
2nd June 2010, 23:00
Strange, I checked the isReadOnly and it said false.

One of the nice things about Qt is that sometimes you can figure something out by just opening up the source code and taking a look. Here’s the code for QSqlQueryModel::record(int):
QSqlRecord QSqlQueryModel::record(int row) const
{
Q_D(const QSqlQueryModel);
if (row < 0)
return d->rec;

QSqlRecord rec = d->rec;
for (int i = 0; i < rec.count(); ++i)
rec.setValue(i, data(createIndex(row, i), Qt::EditRole));
return rec;
}
Without looking very far, we can see that all the QSqlFields in the returned QSqlRecord are set using QSqlRecord::setValue just before the record is returned; and the code for that function is:
void QSqlRecord::setValue(int index, const QVariant& val)
{
if (!d->contains(index))
return;
detach();
d->fields[index].setValue(val);
} where d->fields is a QVector<QSqlField>.

Since QSqlField::setValue is defined to do nothing when QSqlField::isReadOnly returns true, we can conclude that isReadOnly for a field in a record from a QSqlQueryModel returns no useful information: it must always have been set to false.


I guess the copy is editable so it edits the copy but will not alter the original.

Only the fields in the QSqlRecord returned to you are writable; changing them will not affect the model (neither the database nor what is seen in an attached view); and QSqlQueryModel::setData will not work, because it has not been re-implemented from QAbstractItemModel::setData.


I originally was using a QSqlTableModel but I went to a query because I want to add restrictions to the table. I was afraid it will still attempt to read the database before the filter which could be costly.

According to the documentation at QSqlTableModel::setFilter, that function sets up a WHERE clause; and as long as you call it before you call QSqlTableModel::select(), you won’t query the database except using the WHERE clause.