
Originally Posted by
prasad_N
these 2 statements are conflicting right ?
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".
1. In my model rowCount is calling for all the top level items.
my model is :
{
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 );
}
int TreeModel
::rowCount( const QModelIndex &parent
) const {
if ( parent.column() > 0 )
return 0;
TreeItem *parentItem;
if ( ! parent.isValid() )
parentItem = m_rootItem;
else
parentItem = static_cast<TreeItem*>( parent.internalPointer() );
return parentItem->childCount();
}
QModelIndex TreeModel::index( int row, int column, const QModelIndex &parent ) const
{
if ( ! hasIndex(row, column, parent) )
return QModelIndex();
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
return QModelIndex();
}
QModelIndex TreeModel::parent( const QModelIndex &index ) const
{
if ( ! index.isValid() )
return QModelIndex();
TreeItem *childItem = static_cast<TreeItem*>( index.internalPointer() );
TreeItem *parentItem = childItem->parent();
if ( (parentItem == m_rootItem) || (parentItem == NULL))
return QModelIndex();
return createIndex( parentItem->row(), 0, parentItem );
}
int TreeModel::rowCount( const QModelIndex &parent ) const
{
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
This is the implementation of QAbstractItemModel::hasIndex():
{
if (row < 0 || column < 0)
return false;
return row < rowCount(parent) && column < columnCount(parent);
}
bool QAbstractItemModel::hasIndex(int row, int column, const QModelIndex &parent) const
{
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.
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.
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
}
int rowCount(const QModelIndex &parent = QModelIndex()) const {
qDebug() << Q_FUNC_INFO << parent;
if(parent.isValid()) return 2; //each parent with 2 child
return 10; // 10 top most parrents
}
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const {
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 ?
Most likely you didn't change the base class to QAbstractItemModel. Apparently QTreeView has an optimization to not check child nodes for flat models.
#include <QtWidgets>
#define BASEMODEL QAbstractItemModel
class Model : public BASEMODEL {
public:
Model
(QObject *parent
= 0) : BASEMODEL
(parent
) {}
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) {
Model model;
v.setModel(&model);
v.show();
return app.exec();
}
#include <QtWidgets>
#define BASEMODEL QAbstractItemModel
class Model : public BASEMODEL {
public:
Model(QObject *parent = 0) : BASEMODEL(parent) {}
int columnCount(const QModelIndex &parent = QModelIndex()) const { return 1; }
int rowCount(const QModelIndex &parent = QModelIndex()) const {
qDebug() << Q_FUNC_INFO << parent;
if(!parent.isValid()) return 10;
if(parent.isValid() && !parent.parent().isValid()) return 2; // limit to two levels
return 0;
}
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const {
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
}
QModelIndex parent(const QModelIndex &ind) const {
qDebug() << Q_FUNC_INFO << ind;
if(!ind.isValid()) return QModelIndex();
int id = ind.internalId();
if( id == -1) return QModelIndex();
return index(id, 0); // return top-level item
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const {
if(role == Qt::DisplayRole) return index.row()+1;
return QVariant();
}
};
int main(int argc, char **argv) {
QApplication app(argc, argv);
QTreeView v;
Model model;
v.setModel(&model);
v.show();
return app.exec();
}
To copy to clipboard, switch view to plain text mode
I don't want to use treeItems in my model for tree(if possible, I think it is possible with above implementation).
Then don't use them 
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.
Bookmarks