This example shows that the view does not query the whole model when it initializes:
Qt Code:
#include <QtWidgets> public: qDebug() << Q_FUNC_INFO << parent; if(parent.isValid()) return 0; return 1000; } return createIndex(row, column, (void*)0); } if(role == Qt::DisplayRole) return index.row()+1; } }; int main(int argc, char **argv) { QTreeView v; Model model; v.setModel(&model); v.show(); return app.exec(); }To copy to clipboard, switch view to plain text mode
these 2 statements are conflicting right ?
1. In my model rowCount is calling for all the top level items.
my model is :
Qt Code:
{ if ( ! hasIndex(row, column, parent) ) TreeItem *parentItem; if ( ! parent.isValid() ) parentItem = m_rootItem; else parentItem = static_cast<TreeItem*>( parent.internalPointer() ); TreeItem *childItem = parentItem->child( row ); if ( childItem ) return createIndex( row, column, childItem ); else } { if ( ! index.isValid() ) TreeItem *childItem = static_cast<TreeItem*>( index.internalPointer() ); TreeItem *parentItem = childItem->parent(); if ( (parentItem == m_rootItem) || (parentItem == NULL)) return createIndex( parentItem->row(), 0, parentItem ); } { if ( parent.column() > 0 ) return 0; TreeItem *parentItem; if ( ! parent.isValid() ) parentItem = m_rootItem; else parentItem = static_cast<TreeItem*>( parent.internalPointer() ); return parentItem->childCount(); }To copy to clipboard, switch view to plain text mode
2. When I change your model little bit on order to check tree function calling. in the index if(parent.isValid()) is not at all executing.
Qt Code:
qDebug() << Q_FUNC_INFO << parent; if(parent.isValid()) return 2; //each parent with 2 child return 10; // 10 top most parrents } if(parent.isValid()){ // this condition is not at all executing qDebug() << "Yes isValid = " << parent.child(row, column); return createIndex(row, column, (void*)parent.child(row, column).internalPointer()); //create &return child index } return createIndex(row, column, (void*)0); // return top most elements index's }To copy to clipboard, switch view to plain text mode
What wrong am I doing here ?
I don't want to use treeItems in my model for tree(if possible, I think it is possible with above implementation).
Last edited by prasad_N; 8th July 2015 at 19:35.
Thanks :-)
Yes, I didn't express myself clearly. I meant that it is the view which is causing what you see, not the model. I didn't mean to say that "the view has to query all the indexes".
This is the implementation of QAbstractItemModel::hasIndex():1. In my model rowCount is calling for all the top level items.
my model is :
Qt Code:
{ if ( ! hasIndex(row, column, parent) ) TreeItem *parentItem; if ( ! parent.isValid() ) parentItem = m_rootItem; else parentItem = static_cast<TreeItem*>( parent.internalPointer() ); TreeItem *childItem = parentItem->child( row ); if ( childItem ) return createIndex( row, column, childItem ); else } { if ( ! index.isValid() ) TreeItem *childItem = static_cast<TreeItem*>( index.internalPointer() ); TreeItem *parentItem = childItem->parent(); if ( (parentItem == m_rootItem) || (parentItem == NULL)) return createIndex( parentItem->row(), 0, parentItem ); } { if ( parent.column() > 0 ) return 0; TreeItem *parentItem; if ( ! parent.isValid() ) parentItem = m_rootItem; else parentItem = static_cast<TreeItem*>( parent.internalPointer() ); return parentItem->childCount(); }To copy to clipboard, switch view to plain text mode
Qt Code:
{ if (row < 0 || column < 0) return false; return row < rowCount(parent) && column < columnCount(parent); }To copy to clipboard, switch view to plain text mode
Therefore each time you call you index() implementation, it calls hasIndex() which in turn calls rowCount() for the parent. Possibly this applies to other methods and their default implementations.
Most likely you didn't change the base class to QAbstractItemModel. Apparently QTreeView has an optimization to not check child nodes for flat models.2. When I change your model little bit on order to check tree function calling. in the index if(parent.isValid()) is not at all executing.
Qt Code:
qDebug() << Q_FUNC_INFO << parent; if(parent.isValid()) return 2; //each parent with 2 child return 10; // 10 top most parrents } if(parent.isValid()){ // this condition is not at all executing qDebug() << "Yes isValid = " << parent.child(row, column); return createIndex(row, column, (void*)parent.child(row, column).internalPointer()); //create &return child index } return createIndex(row, column, (void*)0); // return top most elements index's }To copy to clipboard, switch view to plain text mode
What wrong am I doing here ?
Qt Code:
#include <QtWidgets> #define BASEMODEL QAbstractItemModel class Model : public BASEMODEL { public: qDebug() << Q_FUNC_INFO << parent; if(!parent.isValid()) return 10; if(parent.isValid() && !parent.parent().isValid()) return 2; // limit to two levels return 0; } qDebug() << Q_FUNC_INFO << row << column << parent; if(parent.isValid()) { qDebug() << Q_FUNC_INFO << "parent valid"; // 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 } qDebug() << Q_FUNC_INFO << ind; int id = ind.internalId(); return index(id, 0); // return top-level item } if(role == Qt::DisplayRole) return index.row()+1; } }; int main(int argc, char **argv) { QTreeView v; Model model; v.setModel(&model); v.show(); return app.exec(); }To copy to clipboard, switch view to plain text mode
Then don't use themI don't want to use treeItems in my model for tree(if possible, I think it is possible with above implementation).
By the way, changing the base class to QAbstractItemModel does cause the tree view to query rowCount for all the top-level items at start, I will try to see why this happens. You can probably switch some property and it will stop doing that.
Edit: It looks like during layout of the tree, the widget calls rowCount() on items that have children. What is worrying is that it also calls canFetchMore() && fetchMore() for them which in my opinion defeats the purpose of implementing those two methods at all at least for two level models.
Last edited by wysota; 8th July 2015 at 20:26.
but when I test your new model I have seen all the top levels items rowsCount() is getting called, I am struggling exactly with this behavior only.
The out put I observed is :Qt Code:
{ qDebug() << parent; //little change in debug msg if(!parent.isValid()) return 10; if(parent.isValid() && !parent.parent().isValid()) return 2; // limit to two levels return 0; } int main(int argc, char **argv) { QTreeView v; v.setFixedSize(200, 50); //set height to 50 so that view can accommodate 2 top level elements only Model model; v.setModel(&model); v.show(); return app.exec(); }To copy to clipboard, switch view to plain text mode
QModelIndex(-1,-1,0x0,QObject(0x0) )
QModelIndex(-1,-1,0x0,QObject(0x0) )
QModelIndex(-1,-1,0x0,QObject(0x0) )
QModelIndex(0,0,0xffffffff,QAbstractItemModel(0x28 fe18) )
QModelIndex(1,0,0xffffffff,QAbstractItemModel(0x28 fe18) )
QModelIndex(2,0,0xffffffff,QAbstractItemModel(0x28 fe18) )
QModelIndex(3,0,0xffffffff,QAbstractItemModel(0x28 fe18) )
QModelIndex(4,0,0xffffffff,QAbstractItemModel(0x28 fe18) )
QModelIndex(5,0,0xffffffff,QAbstractItemModel(0x28 fe18) )
QModelIndex(6,0,0xffffffff,QAbstractItemModel(0x28 fe18) )
QModelIndex(7,0,0xffffffff,QAbstractItemModel(0x28 fe18) )
QModelIndex(8,0,0xffffffff,QAbstractItemModel(0x28 fe18) )
QModelIndex(9,0,0xffffffff,QAbstractItemModel(0x28 fe18) )
//rowCount() is getting called for all top level items here.
One more thing I have observed is, When i return 10000000(top level items) in rowCount() (in old model you suggested & in new model also), My application got crashed with runtime error (on Windows 8, 64bit application).
And when I return 1000000 row count & when I try to scroll down its hanging like hell, not able to scroll at all.
Last edited by prasad_N; 9th July 2015 at 07:01.
Thanks :-)
Which Qt version are you using? How much RAM does your machine have?
I am using 4.8.6 & 5.4.0 with windows 8 and 4GB RAM, I tested on both the versions it failed.
Thanks :-)
Hi Any idea, why is this happening ?
Thanks :-)
4E9 bytes for 1E7 items yields 4E2 (=400) bytes per item. My guess is you are running out of memory![]()
No I am not, It is taking around 128MB (for 10000000 top level items) && 28MB (for 1000000 top level items).
still view is freezing like anything when I scroll, did you reproduce same when you pass more top level count.
Thanks :-)
If you call setUniformRowHeights(true) then there is no such effect. I can scroll the view very quickly.
By the way, I don't think you calculated the memory use correctly. For 10M top-level items with 2 child items each the application uses over 600MB for the data segment.
Last edited by wysota; 10th July 2015 at 08:21.
- forgot to set setUniformRowHeights(true), Its working fine now
- The only & main issue I have now is, rowCount() is still calling for all the top level items , Any idea how to prevent it.?
Sorry I ran 32-bit application, It is taking around 280MB in a same case.By the way, I don't think you calculated the memory use correctly. For 10M top-level items with 2 child items each the application uses over 600MB for the data segment.
Thanks :-)
Bookmarks