PDA

View Full Version : Why does the last row remain in QTableView until the page is reloaded ?



zed220
10th August 2017, 10:01
Hi All,

I'm using [Qt] QTableView and QSqlQueryModel with SQLite Database, I'm trying to delete rows from the QTableView(from the database) by clicking on a row which opens up another page where I carry out the deletion and using 'emit' signal and slot to update the parent page, it all works fine till the VERY LAST ROW. It deletes from the database but remains in the
QTableView until I reload the page, why ?


while(qry.next())
{
QSqlQueryModel *model = new QSqlQueryModel(ui->tableView_staffLog);
model->setQuery(qry);
model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
model->setHeaderData(1, Qt::Horizontal, QObject::tr("Name"));
model->setHeaderData(2, Qt::Horizontal, QObject::tr("Depart"));
model->setHeaderData(3, Qt::Horizontal, QObject::tr("Car Reg"));
model->setHeaderData(4, Qt::Horizontal, QObject::tr("Srt Date"));
model->setHeaderData(5, Qt::Horizontal, QObject::tr("End Date"));
model->setHeaderData(6, Qt::Horizontal, QObject::tr("Contact"));
model->setHeaderData(7, Qt::Horizontal, QObject::tr("Photo"));
ui->tableView_staffLog->setModel(model);
}
connect(ui->tableView_staffLog, SIGNAL(pressed(const QModelIndex&)), this,
SLOT(on_tableView_staffLog_clicked(const QModelIndex&)));
}
void ControlPanel::on_tableView_staffLog_clicked(const QModelIndex& index)
{
const QAbstractItemModel* tableModel = ui->tableView_staffLog->model();
int emp_id = tableModel->data(tableModel->index(index.row(),0), Qt::DisplayRole).toInt();

employeedetails = EmployeeDetails::instance(emp_id, index.row(), this);
connect( employeedetails, SIGNAL(employeeDeleted(int)), this, SLOT(deleteEmployee(int)) );
employeedetails->show();
}

Child page

query.prepare("UPDATE employee SET is_hidden = '1' WHERE emp_id = (:emp_id)");
query.bindValue(":emp_id", emp_id);
success = query.exec();
if(!success)
{
qDebug() << "removeEmployee error: "
<< query.lastError();
}
else
{
if( tableRow >= 0 )
emit employeeDeleted(tableRow);
this->close();
}

high_flyer
10th August 2017, 10:52
show the deleteEmployee() slot.

zed220
10th August 2017, 12:19
Thanks for your reply


void ControlPanel::deleteEmployee(int row)
{
loadAllData();
}

It basically reloads all the data in parent page.

high_flyer
10th August 2017, 14:56
*sigh*
Do you want to be helped or not?

Show us the code that removes employees from your model, the problem is probably there.

zed220
10th August 2017, 15:14
Thanks for your reply again, I have already posted that code it's a soft delete meaning it UPDATES and hides the record instead of complete delete.

query.prepare("UPDATE employee SET is_hidden = '1' WHERE emp_id = (:emp_id)");
query.bindValue(":emp_id", emp_id);
success = query.exec();
if(!success)
{
qDebug() << "removeEmployee error: "
<< query.lastError();
}
else
{
if( tableRow >= 0 )
emit employeeDeleted(tableRow);
this->close();
}

d_stranz
10th August 2017, 18:58
while(qry.next())
{
QSqlQueryModel *model = new QSqlQueryModel(ui->tableView_staffLog);
model->setQuery(qry);
model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
model->setHeaderData(1, Qt::Horizontal, QObject::tr("Name"));
model->setHeaderData(2, Qt::Horizontal, QObject::tr("Depart"));
model->setHeaderData(3, Qt::Horizontal, QObject::tr("Car Reg"));
model->setHeaderData(4, Qt::Horizontal, QObject::tr("Srt Date"));
model->setHeaderData(5, Qt::Horizontal, QObject::tr("End Date"));
model->setHeaderData(6, Qt::Horizontal, QObject::tr("Contact"));
model->setHeaderData(7, Qt::Horizontal, QObject::tr("Photo"));
ui->tableView_staffLog->setModel(model);
}


This code makes no sense at all. Why would you create a new model for *every* result in your query? Each time through the loop, a new model is created, and you set it onto your table view (which replaces the model you created and set on the previous time through the loop).

Quite likely, this is the source of your bug. If the query returns no result, this loop isn't executed so the model held by the table is not replaced. That model still holds the last row.

zed220
11th August 2017, 11:03
QSqlQueryModel *model = new QSqlQueryModel(ui->tableView_staffLog);
qry.prepare( "Some Query" );
if( !qry.exec() )
qDebug() << qry.lastError();
else
{
while(qry.next())
{
model->setQuery(qry);
model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
model->setHeaderData(1, Qt::Horizontal, QObject::tr("Name"));
model->setHeaderData(2, Qt::Horizontal, QObject::tr("Depart"));
model->setHeaderData(3, Qt::Horizontal, QObject::tr("Car Reg"));
model->setHeaderData(4, Qt::Horizontal, QObject::tr("Srt Date"));
model->setHeaderData(5, Qt::Horizontal, QObject::tr("End Date"));
model->setHeaderData(6, Qt::Horizontal, QObject::tr("Contact"));
model->setHeaderData(7, Qt::Horizontal, QObject::tr("Photo"));
ui->tableView_staffLog->setModel(model);
}

Thanks for your reply I have changed it according to your suggestion unfortunately it didn't help.

d_stranz
11th August 2017, 16:22
Thanks for your reply I have changed it according to your suggestion unfortunately it didn't help.

Your code still shows a basic misunderstanding. There is absolutely no need to set the model header data on every call to qry.next(). Set it once, after you create the model in line 1. The header data never changes so why set it repeatedly for every result in every query?

Think about what is happening in line 7: If the query succeeds (qry.exec() returns true) but the result contains ZERO rows (because you have successfully emptied the table), then qry.next() returns false and the code inside the while loop does not get executed. In particular, the line



model->setQuery( qry );


does not get executed, so the model is left holding the last query, which contained ONE result.

zed220
11th August 2017, 16:54
d_stranz blue that was 10/10, I've been at it past two bloody days. Success at last Thank you

d_stranz
11th August 2017, 21:17
Sure, no worries. One more thing:


QSqlQueryModel *model = new QSqlQueryModel(ui->tableView_staffLog);

This also needs to be done only once, when you create the class that contains this code. You do not need to create a new model each time you do a query (eg. on each data reload). Create the model one time, set it on the table, and remember the pointer as a member variable of your class (or retrieve it from the table in the data reload method via QAbstractItemView::model()). The only things you need to do in your reload data method are:

- prepare the query (maybe; if it is the same query every time, then make it a member variable too and prepare it once)
- exec() the query
- if exec() returns true, set the query on the model, otherwise clear() the model.

Everything else - setting the header data, setting the model on the view, etc. can be done once in the constructor.