
Originally Posted by
RolandHughes
Thanks for taking the time to respond. Not exactly an answer, but a response, so thanks for taking the time to do it.
Not very kind of you to say that.
I looked at the source file you indicated and it confirms what I suspected/see happening. The "view", meaning the scrolling region, is not getting content trimmed/updated. The model is physically removing data from itself and some black bag stuff is being updated behind the scene, but the "text" the scrolling area knows about is not being cleaned.
What exactly do you mean by "the text the scrolling area knows about"? The view does not hold the model data anywhere, that's the model's responsibility.
Before we go off on a tangent allow me to provide a picture. Other than being illustrative and conceptually what is happening, it has no relationship to what is actually being done.
Consider the model to be a bookshelf of some fixed size able to support limitless weight but only so many feet wide. When the db scrollbar (scrolling by ID, not by pixel like the view scroll area) is moved it sees if the model has any rows for the new ID and then tells the view to scroll N or -N pixels to get to the first of what could be many rows for that ID (i.e. Some books are many inches thicker than others). When the ID is not there the it tells the model to get more books. The model shoves those books onto one end or the other of the shelf. It then makes note how many books need to fall off the other end for things to fit, does a beginRemove(), deletes the data, then does an endRemove(). It's not a math problem with pixels/row because it does scroll to correct information.
Debug statements for the hidden viewport scroll bar show the pixel position growing and growing and growing. Despite the fact the model has physically removed the data and done the begin/end remove stuff, the scroll area is not tidied up.
I don't know how you are implementing your model and your view but according to me you have two choices compliant with the item-views architecture. Basically you can either report the proper size of the model and cache its data partially or modify the model to fit what is displayed in the view using insert/remove rows. I'm assuming you have taken the latter approach so I will focus on the former one first.
Here is an example which implements a model with 40M items where only 1k items are kept in memory at once (unfortunately the index is int-based so we can't have much more rows).
#include <QApplication>
#include <QAbstractTableModel>
#include <QTableView>
#include <QContiguousCache>
#include <QtDebug>
public:
m_from(from),
m_to(to)
{
m_cache.setCapacity(cacheSize);
}
int rowCount
(const QModelIndex &parent
= QModelIndex()) const { return parent.
isValid() ?
0 : m_to
-m_from
+1;
} if(role
!= Qt
::DisplayRole) return QVariant();
int row = index.row();
while(row > m_cache.lastIndex())
m_cache.append(populate(m_cache.lastIndex()+1));
while(row < m_cache.firstIndex())
m_cache.prepend(populate(m_cache.firstIndex()-1));
return m_cache.at(row);
}
protected:
int populate(int row) const {
return row*2; // simple populate function
}
private:
mutable QContiguousCache<int> m_cache;
int m_from;
int m_to;
};
int main(int argc, char *argv[])
{
Model model(0, 40000000L, 1000);
view.setModel(&model);
view.show();
return a.exec();
}
#include <QApplication>
#include <QAbstractTableModel>
#include <QTableView>
#include <QContiguousCache>
#include <QtDebug>
class Model : public QAbstractTableModel {
public:
Model(int from, int to, int cacheSize, QObject *parent = 0) : QAbstractTableModel(parent),
m_from(from),
m_to(to)
{
m_cache.setCapacity(cacheSize);
}
int rowCount(const QModelIndex &parent = QModelIndex()) const { return parent.isValid() ? 0 : m_to-m_from+1; }
int columnCount(const QModelIndex &parent = QModelIndex()) const { return 1; }
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const {
if(role != Qt::DisplayRole) return QVariant();
int row = index.row();
if(row > m_to) return QVariant();
if(row < m_from) return QVariant();
while(row > m_cache.lastIndex())
m_cache.append(populate(m_cache.lastIndex()+1));
while(row < m_cache.firstIndex())
m_cache.prepend(populate(m_cache.firstIndex()-1));
return m_cache.at(row);
}
protected:
int populate(int row) const {
return row*2; // simple populate function
}
private:
mutable QContiguousCache<int> m_cache;
int m_from;
int m_to;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTableView view;
Model model(0, 40000000L, 1000);
view.setModel(&model);
view.show();
return a.exec();
}
To copy to clipboard, switch view to plain text mode
You can fine tune the model by providing some look-ahead buffer, add data in batches and/or use a thread to populate the look-ahead buffer. The docs for QContignousCache might give you some ideas.
As for the other approach, maybe we could have a look at your code or some example which behaves in a similar fashion? Are you making use of canFetchMore()/fetchMore()?
Bookmarks