PDA

View Full Version : QsqlTableModel not fetching all rows after update



KillGabio
15th July 2013, 07:24
Hi everyone. Im having the following problem. I can fetch all the rows of my query and view this model with the QTableView.

But the problem comes when, after updating a cell, the view of the model trims again only showing the first 256 rows. Here is the class:


WidgetModificacion::WidgetModificacion(QWidget *parent, int tipo_tabla) :
QWidget(parent),
ui(new Ui::WidgetModificacion)
{
ui->setupUi(this);
this->tipo_tabla = tipo_tabla;
db = QSqlDatabase::database ("app_db");
if (db.isOpen ()){
model = new QSqlTableModel (this, db);
switch (tipo_tabla){
case 0:
model->setTable ("TABLE_PRODUCTOS");
break;
case 1:
model->setTable ("TABLE_CLIENTES");
break;
}
model->setEditStrategy(QSqlTableModel::OnFieldChange);
model->setSort (1, Qt::AscendingOrder);
model->select ();
while (model->canFetchMore()) model->fetchMore();
this->ui->tableView->setModel (model);
QStyledItemDelegate *display = new NumberRepresentation(this);
ui->tableView->setItemDelegateForColumn (0, display);
ui->tableView->setItemDelegateForColumn (4, display);
ui->tableView->setColumnWidth(1,250);
connect (this->model, SIGNAL(beforeUpdate (int, QSqlRecord &)), this, SLOT (actualizar_fecha (int, QSqlRecord &)));
}
else{
QMessageBox::critical(0, qApp->tr("Cannot open database"),
qApp->tr("Unable to establish a database connection.\n"
"Llamar a Agus.\n\n"
"Click Cancel to exit."), QMessageBox::Cancel);
}
}

WidgetModificacion::~WidgetModificacion()
{
delete ui;
}

void WidgetModificacion::on_cerrar_clicked()
{
emit finaliza_modificacion (QString (":ImagesMilk/Iconos/uvacopa.png"));
this->db.close ();
this->close ();
}

void WidgetModificacion::actualizar_fecha (int row, QSqlRecord & record){
if (tipo_tabla == 0){
QSqlQuery *query = new QSqlQuery (db);
query->prepare ("UPDATE TABLE_PRODUCTOS SET fecha_modificacion = SYSDATE WHERE id_codigo_barra = :value");
query->bindValue (":value", this->ui->tableView->model ()->data (this->ui->tableView->model ()->index (row, 0)).toString ());
query->exec ();
//while (model->canFetchMore()) model->fetchMore();
//this->ui->tableView->setModel (model);
}
}

The code that is commented i've alredy tried it, and doesnt work. What i want is to modify the cell and stay at the same position of the table i was before the update. Thank you all in advance.

ChrisW67
16th July 2013, 04:48
The query does not add rows to the table so line 55 would achieves nothing anyway.
Line 56 does nothing because the model pointer has not changed and the view does nothing as a result.

QSqlTableModel does not watch the underlying data for changes. If you do not update rows through the model then it has no way to know underlying data has changed. You need to do one of these things:

Update through the model. Your query requires looping over all rows in the table, creating a model index, and calling setData(), but preserves current index and selection.
Call reset() on the model after a behind-the-model data change. This is faster but will lose the view's current cell and selection. If you have a unique ID for a row then you can cache that, reset the model, the use match() to find the unique ID and reinstate the current cell.



Line 51 in an unnecessary heap allocation and memory leak.

KillGabio
17th July 2013, 05:53
Thank you for replying. Line 51 modified :P

I tried calling the reset but nothing changes. Rows showed change to 256 after the edit.

There is no selection, the user only changes the value of one cell so i think i dont have to iterate, right? So i call setData() from the index of interest but still the same, rows trim to 256.



void WidgetModificacion::actualizar_fecha (int row, QSqlRecord & record){
if (tipo_tabla == 0){
QSqlQuery query = QSqlQuery (db);
query.prepare("UPDATE TABLE_PRODUCTOS SET fecha_modificacion = SYSDATE WHERE id_codigo_barra = :value");
query.bindValue (":value", this->ui->tableView->model ()->data (this->ui->tableView->model ()->index (row, 0)).toString ());
query.exec ();
}
//ui->tableView->reset();
model->setData(model->index(row,5), QDateTime::currentDateTime().toString(),Qt::Displa yRole);
while (model->canFetchMore())model->fetchMore();
}

The value is always updated after edit and i can see that value modified but rows set to 256 anyways.

ChrisW67
17th July 2013, 06:07
You reset the QSqlTableModel and it re-executes the underlying query and, as always, fetches rows lazily. If you want to fetch all the rows again then use canFetchMore() and fetchMore().

If you are only updating a single cell then look up its QModelIndex and call setData() and the view will look after itself. Exactly when that update is written to the underlying database and the effect on selections/current cell is a function of the model's edit strategy.