PDA

View Full Version : Updating header data is too slow as data grows high in Model view architecture.



prasad_N
11th July 2015, 14:21
Hi,

I am using model view for displaying large data (tree view with millions of rows), I have customized my model & view (QAbstractItemModel, QTreeView).
What I have observed is as number of rows (data) grows high, updating of headers & selection becomes too slow.

I am changing the header data each time I click an item (if row is even number one header set, if odd another header set).
If my model has 1 - 1000000 rows, the header is updating as expected (no delay in updating header on clicking item).
I test by returning 10000000 rows(top level items) in model & when I started clicking on items header data is updating very slowly & items selection also becomes very slow.
When I tested with 20000000 rows it becomes further late.

Here is My implementation:

Model:


Model::Model(QObject *parent) :
QAbstractItemModel(parent)
{

}

Model::~Model()
{

}

void Model::setHeaderData(QStringList& head)
{
m_head = head; //m_header is QString List for headers
}

void Model::headerChanged(int row) //This is slot connected to view, will be called when an items clicked in view with index.row() as parameter.
{
QStringList head;
if(row%2){
head << " Head1 " << " Head2 " << " Head3 " << " Head4 " << " Head5 " << " Head6 " << " Head7 " << " Head8 " ;
}
else{
head << " Head11 " << " Head12 " << " Head13 " << " Head14 " << " Head15 " << " Head16 " << " Head17 " << " Head18 " ;
}
m_head = head;
emit headerDataChanged(Qt::Horizontal, 0, head.size() - 1);
}

QVariant Model::headerData ( int section, Qt::Orientation orientation, int role ) const
{
if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
{
return m_head.at(section);
}
else if ( orientation == Qt::Vertical && role == Qt::DisplayRole ){
return section;
}
return QVariant();
}

int Model::columnCount(const QModelIndex &parent) const
{
return 8;
}

int Model::rowCount(const QModelIndex &parent) const
{
if(!parent.isValid()) return 20000000;
if(parent.isValid() && !parent.parent().isValid()) return 2; // limit to two levels
return 0;
}

QModelIndex Model::index(int row, int column, const QModelIndex &parent) const
{
if(parent.isValid())
{
// we only need id of the parent since it identifies the item
return createIndex(row, column, parent.row());
}
return createIndex(row, column, -1); // top level item has invalid parent
}

QModelIndex Model::parent(const QModelIndex &ind) const
{
if(!ind.isValid()) return QModelIndex();
int id = ind.internalId();
if( id == -1) return QModelIndex();
return index(id, 0); // return top-level item
}

QVariant Model::data(const QModelIndex &index, int role ) const
{
if(role == Qt::DisplayRole) return index.row()+1;
return QVariant();
}



Any Idea why updating headers is too slow when number of items becomes more ???


Thanks in advance.

ChrisW67
11th July 2015, 22:51
My guess, turn off automatic column resizing in your view:
QHeaderView::setSectionResizeMode(), or QHeaderView::setResizeMode(), with something other than QHeaderView::ResizeToContents.

prasad_N
12th July 2015, 08:54
My guess, turn off automatic column resizing in your view:
QHeaderView::setSectionResizeMode(), or QHeaderView::setResizeMode(), with something other than QHeaderView::ResizeToContents.

I have tried all the possible combinations of serResizeMode (interactive, fixed, stretch, resizeToColumnContent), I could see same amount of delay in updating headers & selection each time.

prasad_N
13th July 2015, 18:13
Any suggestions from Qt experts ??

ChrisW67
13th July 2015, 21:40
Any attempt to identify the actual source of the slowness on your part?

jefftee
14th July 2015, 03:20
Any Idea why updating headers is too slow when number of items becomes more ???
You are setting the vertical header with the row number, so yes, as you have more rows, you will have more vertical headers to set. Have you tried not using vertical headers to see if that is indeed the reason your app slows down as you increase the number of rows?

prasad_N
14th July 2015, 05:22
Any attempt to identify the actual source of the slowness on your part?

Yes, for each mouse click on item it is calling row count for all the top level items (this can be one of the problem, My post regarding this & I did not get any solution for both of these problems http://www.qtcentre.org/threads/63038-rowCount()-is-calling-for-all-the-top-level-items?highlight= ).

Added after 5 minutes:


You are setting the vertical header with the row number, so yes, as you have more rows, you will have more vertical headers to set. Have you tried not using vertical headers to see if that is indeed the reason your app slows down as you increase the number of rows?

Not actually, I have 2 header sets each of them are 8 (there is no dependency on rows here), And when I remove variable headers or remove complete headers then there is no slowness in my app as soon as my clicking on items its getting selected (Probably you can experiment little by take my mode).

One reason could be in my reply #7

prasad_N
15th July 2015, 19:22
Here is my code, I have tried to find a solution for this but could not find any.
can some one suggest a way to get over this?

Mode:

Model::Model(QObject *parent): QAbstractItemModel(parent)
{

}

Model::~Model()
{

}

void Model::setHeaderData(QStringList& head)
{
m_head = head;
}

void Model::headerChanged(QModelIndex index)
{
int row = index.row();
QStringList head;
if(row%2){
head << " Head1 " << " Head2 " << " Head3 " << " Head4 " << " Head5 " << " Head6 " << " Head7 " << " Head8 " << "head9" ;
}
else{
head << " Head11 " << " Head12 " << " Head13 " << " Head14 " << " Head15 " << " Head16 " << " Head17 " << " Head18 " ;
}
m_head = head;
emit headerDataChanged(Qt::Horizontal, 0, head.size() - 1);
}

QVariant Model::headerData ( int section, Qt::Orientation orientation, int role ) const
{
if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
{
return m_head.at(section);
}
else if ( orientation == Qt::Vertical && role == Qt::DisplayRole ){
return section;
}
return QVariant();
}

int Model::columnCount(const QModelIndex &parent) const
{
return m_head.size();
}

int Model::rowCount(const QModelIndex &parent) const
{
if(!parent.isValid()){
return 10000000;
}
if(parent.isValid() && !parent.parent().isValid()){
qDebug() << parent; // This is calling for 20000000 times for each mouse click & causing problem
return 2; // limit to two levels
}
return 0;
}

QModelIndex Model::index(int row, int column, const QModelIndex &parent) const
{
if(!parent.isValid())
{
return createIndex(row, column, -1); // top level item has invalid parent
}
// we only need id of the parent since it identifies the item
return createIndex(row, column, parent.row());
}

QModelIndex Model::parent(const QModelIndex &ind) const
{
if(!ind.isValid()) return QModelIndex();
int id = ind.internalId();
if( id == -1) return QModelIndex();
return index(id, 0); // return top-level item
}



QVariant Model::data(const QModelIndex &index, int role ) const
{
if(role == Qt::DisplayRole) return index.row()+1;
return QVariant();
}


View:

treeview::treeview(Model* model)
{
setModel(model);
connect(this, SIGNAL(clicked(QModelIndex)), model, SLOT( headerChanged(QModelIndex) ));
setUniformRowHeights(true);
}

treeview::~treeview()
{
}

main:

int main(int argc, char **argv)
{
QApplication app(argc, argv);
Model model;
treeview v(&model);
v.setFixedSize(700, 800);

QStringList head;
head << " Head1 " << " Head2 " << " Head3 " << " Head4 " << " Head5 " << " Head6 " << " Head7 " << " Head8 " ;
model.setHeaderData(head);
v.setModel(&model);
v.show();
return app.exec();
}


Thanks in advance.

prasad_N
16th July 2015, 19:44
got the solution finally, if any one has similar issue, please look at the below post replay's from #15 to #23

http://www.qtcentre.org/threads/63038-rowCount()-is-calling-for-all-the-top-level-items?p=279554#post279554