PDA

View Full Version : Clicking QTableView's Corner Button does not select all rows



Ashkan_s
19th September 2012, 08:54
I have a QTableView wich its corner button is enabled. Problem is when I click the button, only a portion of rows gets selected -in my case the first 256 rows, which are the currently loaded rows.

Here is an example:

#include <QtGui>
#include <QtSql>

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("D:\\tempDB\\mydb");

if (db.open()) {
QSqlQuery query;
QString str = "title";

query.exec("CREATE TABLE " + str + "(\
id INTEGER PRIMARY KEY AUTOINCREMENT,\
title1 VARCHAR(255),\
title2 VARCHAR(255))");

QSqlTableModel model;
model.setTable("title");
model.setEditStrategy(QSqlTableModel::OnManualSubm it);

QSqlRecord rec1 = db.record("title");
QSqlRecord rec4, rec3, rec2;

rec4 = rec3 = rec2 = rec1;

rec1.setValue("title1", "test1");
rec1.setValue("title2", "test11");
rec2.setValue("title1", "test2");
rec2.setValue("title2", "test22");
rec3.setValue("title1", "test3");
rec3.setValue("title2", "test33");
rec4.setValue("title1", "test4");
rec4.setValue("title2", "test44");

db.transaction();
model.insertRows(0, 1024);

for (int i = 0; i < 1024;)
{
model.setRecord(i++, rec1);
model.setRecord(i++, rec2);
model.setRecord(i++, rec3);
model.setRecord(i++, rec4);
}

model.submitAll();

db.commit();

model.select();

QTableView view;
view.setModel(&model);
view.resize(640, 480);
view.setCornerButtonEnabled(true);
view.show();

return app.exec();
}
else
{
return 1;
}
}


Running this example, clicking the corner button before scrolling down the view to the bottom, then scrolling the view down, will reproduce the problem.

Added after 18 minutes:

I know I can force the model to fetch all the data by putting

while (model.canFetchMore())
model.fetchMore();
in the code, but shouldn't it load all when I click the corner button?

Ashkan_s
19th September 2012, 13:40
I found a solution here (http://www.qtcentre.org/threads/31156-Cutom-signal-on-mouse-click-at-top-left-corner-of-QTableWidget) in the forum. I have re-implemented the QTableView::selectAll() in subclass, here is the code


void TableView::selectAll()
{
QSqlTableModel *model = (QSqlTableModel *)(this->model());
while(model->canFetchMore())
{
model->fetchMore();
}

QTableView::selectAll();
}

But my question still stands:
shouldn't it load all when I click the corner button?

Ashkan_s
20th September 2012, 16:52
It seems everything is working based on the number of currently loaded rows. Scroll to bottom does not scrolls to bottom because the model loads new rows, or QSqlTableModel::rowCount() returns the number of loaded rows.

Ashkan_s
21st September 2012, 22:42
I have changed the example that I had sent in the first post. Now there is a QSortFilterProxyModel between QSqlTableModel and QTableView. There's also a QLineEdit to filter the table rows.


#include <QtGui>
#include <QtSql>

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");

if (db.open()) {
QSqlQuery query;
QString str = "title";

query.exec("CREATE TABLE " + str + "(\
id INTEGER PRIMARY KEY AUTOINCREMENT,\
title1 VARCHAR(255),\
title2 VARCHAR(255))");

QSqlTableModel model;
model.setTable("title");
model.setEditStrategy(QSqlTableModel::OnManualSubm it);

QSortFilterProxyModel proxy;
proxy.setSourceModel(&model);
proxy.setDynamicSortFilter(true);
proxy.setFilterKeyColumn(2);

QSqlRecord rec1 = db.record("title");
QSqlRecord rec5, rec4, rec3, rec2;

rec5 = rec4 = rec3 = rec2 = rec1;

rec1.setValue("title1", "test1");
rec1.setValue("title2", "test11");
rec2.setValue("title1", "test2");
rec2.setValue("title2", "test22");
rec3.setValue("title1", "test3");
rec3.setValue("title2", "test33");
rec4.setValue("title1", "test4");
rec4.setValue("title2", "test44");
rec5.setValue("title1", "table5");
rec5.setValue("title2", "table55");

db.transaction();
model.insertRows(0, 10240);

for (int i = 0; i < 10240;)
{
if(i % 512 != 0)
model.setRecord(i++, rec1);
else
model.setRecord(i++, rec5);

model.setRecord(i++, rec2);
model.setRecord(i++, rec3);
model.setRecord(i++, rec4);
}

model.submitAll();

db.commit();

model.select();

QTableView view;
view.setModel(&proxy);
view.resize(640, 480);
view.show();

QLineEdit le;
le.show();

QObject::connect(&le, SIGNAL(textChanged(QString)), &proxy, SLOT(setFilterFixedString(QString)));

return app.exec();
}
else
{
return 1;
}
}


After running this, typing "ta" in the lineEdit to search for "table55", updates the view and one row appears. Now rotating the wheel button of mouse will cause other rows to be appear one by one.
Forcing the model to fetch all rows solves this problem.

My question is: To avoid fetching all rows, do I have to write my own SQL queries for filtering? Is there any other way?

Ashkan_s
10th October 2012, 17:13
OK, there is another way: Calling fetchMore() while the view has enough space to show more rows without scrolling.