PDA

View Full Version : QTableView connected with QSqlTableModel flickers (scrolls to the bottom and returns)



ironexmaiden
20th August 2017, 17:46
Hello everyone I have a problem using table view. I have a tableview connected with a QSqlTableModel. On its 2nd column I want to have check state to control the row's Status (active/inactive) but when I try to push the check box QTableView scrolls to the bottom and returns to it's previous position. Is there any solution?




bool ProjectsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(index.column() == STATUS_INDEX) {
QSqlRecord rec = this->record(index.row());
QString qrstr;

qrstr = (rec.field(index.column()).value().toInt() == 1) ? "update " + tableName() + " set Status=0 where BRACE_ID=" : "update " + tableName() + " set Status=1 where BRACE_ID=";
qrstr += QString().setNum(index.row()+1);

braceDatabase->exec(qrstr.toUtf8().constData());
return true;
}

return false;
}

void DataBase::updateTablesSlot()
{
if(projectsModel)
projectsModel->select();
if(attributesModel)
attributesModel->select();
if(targetsModel)
targetsModel->select();
}

void DataBase::exec(const std::string &querystr)
{
QSqlQuery qr(db);
qr.exec(querystr.c_str());
//qDebug() <<"Command :" << querystr.c_str() << "-> "<< query->lastError().text();
updateTables();
}



12564

d_stranz
20th August 2017, 18:19
Each time you change a check box, you are re-executing the update query that fills the table. The requires the table to erase its contents and then replace everything with new values.

Instead of this, look at the description of QSqlTableModel::editStrategy() in QSqlTableModel::submit(). If you do this properly, I do not think it is necessary for you to manually execute an update query; calling submit() will update the model (and database) and will result in an update of only the rows or fields that have changes.

ironexmaiden
20th August 2017, 21:41
Ok but I have a question. How can I achieve the status change through edistrategy and submit ? I tried the updateRowInTable function but Qt doc doesn't suggest to use this function directly

d_stranz
21st August 2017, 01:13
Read the description and look at the example code here (https://doc.qt.io/qt-5/sql-model.html). I think you are confused into thinking that -you- have to issue SQL queries to update the database and the view. You don't. The QSqlTableModel::setData() modifies the field at the QModelIndex that is passed in; you optionally call submit() which will both update the database for you -and- cause the table view to update.

If you set the edit strategy to OnFieldChange, then the changes will be submitted automatically when the editing is complete (you do not need to call submit()). If you set the edit strategy to OnRowChange, the changes will be submitted when editing moves to a different row (again, you do not need to call submit()). If the edit strategy is OnManualSubmit, then -you- have to call submit() or submitAll() to force the changes into the database.

The difference among these three strategies is -when- the changes are updated in the database. The QSqlTableModel is a layer that sits between your database and your table view. Editing changes that the user makes in the table view are stored (cached) in the model until they are submitted to the database. Depending on the edit strategy, the changes can be submitted immediately after each field is edited (OnFieldChange), when the selected row changes (OnRowChange), or when your program tells the model to update the database (OnManualChange).

Which strategy you choose depends on how you want your program to interact with the database.

Unless you are doing something special in data() or setData(), I don't think you need to derive from QSqlTableModel at all. The example I linked to uses QSqlTableModel itself; the model, database, and view work together to ensure everything is synchronized.

ironexmaiden
21st August 2017, 13:23
Thank you for your time, may I didn't study the documentation enough. I will try to re-organise the code and I will update the issue

ironexmaiden
22nd August 2017, 23:39
I changed my code and I remove the sql query exec I tried to modify the data with the setData but unfortunately nothing happened




bool AttributesModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(index.column() == STATUS_INDEX) {
bool ret = QSqlTableModel::setData(index, value == Qt::Checked ? Qt::Unchecked : Qt::Checked, role);
database().commit();
this->submitAll();
return ret;
}
return QSqlTableModel::setData(index, value, role);
}