QAbstractListModel data access
-
Hi!
I'm new to qt and what I'm trying to accomplish is to force QListView work as a grid, i.e i have a lot of entries, i can say how many and i can access them sequentially, that is why i want them fatched only as many as really needed. QAbstractListModel + QListView::setUniformItemSizes works almost fine, almost becuase the first thing it does is fetch last element, and i'm forced to read all data. The question is: Is it possible to avoid such a behavior?Thanks in advance!
-
Take a look at this tutorial: http://doc.qt.nokia.com/4.7-snapshot/itemviews-fetchmore.html
It basically adds items in chunks, as needed. Is this the behavior you want? -
You could of course also overwrite the data() method and if the data is already available use it, and otherwise parse the requested data (not sure about the delay that introduces, though). Since you already have the total number, reimplement rowCount() accordingly (That might be better, because it indicates to the user how much data is really available.
-
Wouldn't that be the whole point, that you don't know the total number of items from the start?
If you have rowCount() return the total number of items from the start, then the view will request the data for all items, which means you would have to fetch everything from the start.
-
[quote author="ionutl" date="1313071072"]Wouldn't that be the whole point, that you don't know the total number of items from the start?[/quote]
He said
[quote]
i can say how many
[/quote]I think the main reason here would be the delay in parsing/reading a large set of data (even if this is not necessary, e.g. if the user only want to see the first entry, etc. .
Concerning,
[quote]
If you have rowCount() return the total number of items from the start, then the view will request the data for all items, which means you would have to fetch everything from the start.[/quote]
The data is requested from the model whenever it is (re-)painted and not cached within the view (I looked it up in the code). -
Here is a minimal code
file: listviewmodel.h
@#pragma once
#include <QtGui>class Model : public QAbstractListModel
{
Q_OBJECTconst int Count;
public:
Model (int count) : Count (count) {}int rowCount (const QModelIndex&) const { return Count; } QVariant data (const QModelIndex& index, int role) const { if (!index.isValid () || index.row () >= Count || role != Qt::DisplayRole ) { return QVariant (); } qDebug () << index.row (); return QVariant (index.row ()); }
};
@
file: listmodel.cpp
@#include "listviewmodel.h"int main (int argc, char** argv)
{
QApplication app (argc, argv);QListView view; Model model (1 << 20); view.setUniformItemSizes (true); view.setLayoutMode (view.Batched); view.setModel (&model); view.show (); return app.exec ();
}
@
look at the outpout:
@1048575
0
1
2
3
4
5
6
7
8
9
10
11
12
@As you can see the first thing QListView has done, was QAbstractListModel (row = 1 << 20) even though layoutMode == Batched.
I would like somehow avoid access to the last elemnt unless its really needed. -
I know why it's happening. Consider the following code segment from listview.cpp
@
if (!cachedItemSize.isValid()) { // the last item is probaly the largest, so we use its size
int row = model->rowCount(root) - 1;
QModelIndex sample = model->index(row, column, root);
const QAbstractItemDelegate *delegate = delegateForIndex(sample);
cachedItemSize = delegate ? delegate->sizeHint(option, sample) : QSize();
}
@
This is not executed if setUniformItemSizes(true) is being called. Could that work for you? -
Yes, it seems you are right. But its executed if setUniformItemSizes (true).
I think this behavior is incorrect. If I've stated that all items have the same size (by setting uniformItemSizes = true) what is the reason to presume "the last item is probaly the largest, so we use its size", it will may turn last item wouldn't be shown at all? -
Oops, I meant, it's not executed if setUniformItemSizes(false) is being called. Sorry for the confusion.
-
"I've reported a Bug ...":https://bugreports.qt.nokia.com/browse/QTBUG-20898