July 28, 2010

ixSci ixSci
Lab Rat
203 posts

QTreeView doesn’t display anything from custom model

 

Hello!

I have a custom model which is descendant of QAbstractItemModel and I have a custom tree view which is descendant of QTreeView(it implements several events and doesn’t violate any logic). At the start I have no elements in the model but the root element. Interactively I’m adding new elements to the model and they are added to the model correctly.

The problem is that I have only a blank rectangle in place of my tree. Any my rows manipulation does nothing and I don’t understand what the trouble is. I’m using beginInsertRows\endInsertRows pairs and it doesn’t help.
Can anybody explain why such a thing can be?

9 replies

July 28, 2010

moellney moellney
Lab Rat
16 posts

Last time I had this, i forgot to respect the role parameter in the models data method. I just returned the data to display as a QString in a variant independent from the role parameter.

But actually one of the roles was the size of the field to show the string in the QItemList. Maybe the problem is similiar….

But without a small code example …..

July 28, 2010

Denis Kormalev Denis Kormalev
Lab Rat
1654 posts

As previous comment said problem can be in incorrect roles. Also maybe you have problem with returning children for root element. But of course without code nobody can say something more particular.

July 29, 2010

ixSci ixSci
Lab Rat
203 posts

Ok, code of what method should I show? I intentionally didn’t provide any because it has plenty details of realization which doesn’t relevant to the model itself.
BTW, I’ve set breakpoint to the data() and setData() methods and they have been never invoked.

July 29, 2010

Denis Kormalev Denis Kormalev
Lab Rat
1654 posts

Maybe there are problems with linking parent and children?

Show only code that override parent class methods, it should help.

July 29, 2010

ixSci ixSci
Lab Rat
203 posts

Denis Kormalev wrote:
Maybe there are problems with linking parent and children?

No, link works as it should.

  1. int AccountModel::rowCount(const QModelIndex& Index /*= QModelIndex()*/) const
  2. {
  3.     TRACE_LOG("Start routine");
  4.     if(!Index.isValid())
  5.         return 0;
  6.     AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
  7.     Q_ASSERT(pItem != nullptr);
  8.     return static_cast<int>(pItem->ChildCount());
  9. }

  1. QVariant AccountModel::data(const QModelIndex& Index,
  2.                             int Role) const
  3. {
  4.     TRACE_LOG("Start routine");
  5.     if(!Index.isValid())
  6.         return QVariant();
  7.     AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
  8.     Q_ASSERT(pItem != nullptr);
  9.     return pItem->Data(Role);
  10. }

  1. Qt::ItemFlags AccountModel::flags(const QModelIndex& Index) const
  2. {
  3.     TRACE_LOG("Start routine");
  4.     if (!Index.isValid())
  5.          return 0;
  6.     return  Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable
  7.            | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
  8. }

  1. QModelIndex AccountModel::index(int Row,
  2.                                 int Column,
  3.                                 const QModelIndex& Index /*= QModelIndex()*/) const
  4. {
  5.     TRACE_LOG("Start routine");
  6.     if(!Index.isValid())
  7.         return RootElement();
  8.     AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
  9.     Q_ASSERT(pItem != nullptr);
  10.     AccountItem::ChildType Child = pItem->Child(static_cast<size_t>(Row));
  11.     if(Child != c_InvalidChild)
  12.         return createIndex(Row, Column, static_cast<void*>(Child));
  13.     return QModelIndex();
  14. }

  1. QModelIndex AccountModel::parent(const QModelIndex& Index) const
  2. {
  3.     TRACE_LOG("Start routine");
  4.     if(!Index.isValid())
  5.         return QModelIndex();
  6.     AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
  7.     Q_ASSERT(pItem != nullptr);
  8.     AccountItem* pParent = pItem->Parent();
  9.     //It is a one of the children...
  10.     if(pParent != nullptr)
  11.         return createIndex(pParent->Position(), 0, static_cast<void*>(pParent));
  12.     //... or it is the root element.
  13.     else
  14.         return QModelIndex();
  15. }

  1. bool AccountModel::setData(const QModelIndex& Index,
  2.                            const QVariant& Value,
  3.                            int Role /*= Qt::EditRole*/)
  4. {
  5.     TRACE_LOG("Start routine");
  6.     if(!Index.isValid())
  7.         return false;
  8.     AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
  9.     Q_ASSERT(pItem != nullptr);
  10.     pItem->SetData(Role, Value);
  11.     return true;
  12. }

  1. bool AccountModel::insertRows(int Row,
  2.                               int Count,
  3.                               const QModelIndex& Index /*= QModelIndex()*/)
  4. {
  5.     TRACE_LOG("Start routine");
  6.     if(!Index.isValid())
  7.         return false;
  8.     AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
  9.     Q_ASSERT(pItem != nullptr);
  10.     if(pItem->ChildCount() < static_cast<size_t>(Row) || Row < 0)
  11.         return false;
  12.     beginInsertRows(Index, Row, Row + Count - 1);
  13.     for(int i = Row; i < Row + Count; ++i)
  14.     {
  15.         AccountItem* pNewItem = new AccountItem(nullptr);
  16.         if(!pItem->InsertChild(pNewItem, static_cast<size_t>(i)))
  17.         {
  18.             WARN_LOG("Unable to insert child");
  19.             delete pNewItem;
  20.             return false;
  21.         }
  22.     }
  23.     endInsertRows();
  24.     return true;
  25. }

  1. bool AccountModel::hasChildren(const QModelIndex& Index /*= QModelIndex()*/) const
  2. {
  3.     TRACE_LOG("Start routine");
  4.     if(!Index.isValid())
  5.         return false;
  6.     AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
  7.     Q_ASSERT(pItem != nullptr);
  8.     return pItem->ChildCount();
  9. }

July 29, 2010

Denis Kormalev Denis Kormalev
Lab Rat
1654 posts

At quick look it looks ok. Maybe problem with indexes? Look for index validity in hasChildren() and rowCount() methods. Maybe it will help to discover problem.

July 29, 2010

ixSci ixSci
Lab Rat
203 posts

Ok, I’ve got it. I have no hidden root element before but it seems that view insists to have one. When I added the hidden root element and added one child to him, top element in the tree was appeared. Thank you for the right clue.

July 30, 2010

ixSci ixSci
Lab Rat
203 posts

I have another question related to the topic.

When I create model with the only one element(actually the top root element) QTreeView doesn’t show anything. It waits until the root gets at least one child and then start to draw my tree. And when it draws the tree it uses only the top root index and displays only one element. But I have two elements! It seems weird to me. Why QTreeView doesn’t show element if it is the only one element and it was selected as the tree root? And why it shows only one element after I add child to the top root and use Model Index of the top root instead of the child index when retrieve its data?

April 3, 2013

Maaaks Maaaks
Lab Rat
10 posts
moellney wrote:
Last time I had this, i forgot to respect the role parameter in the models data method. I just returned the data to display as a QString in a variant independent from the role parameter.

Thank you!

For those who experiance this problem, I’ll describe my own case (maybe a common one). I had this simple data():

  1. switch (role) {
  2.  case Qt::DisplayRole:
  3.   return "o_O";
  4.  default:
  5.   return false;
  6. }

and my tree view looked empty.

After reading this thread, I added debug output to this method and understood that the first and the only role that was asked to my model was role=13 (Qt::SizeHintRole). As soon as I returned false, the tree decided not to ask any more data for any cell.

So, this version of data() worked better:

  1. switch (role) {
  2.  case Qt::DisplayRole:
  3.   return "o_O";
  4.  case Qt::SizeHintRole:
  5.   return QSize(100, 100);
  6.  default:
  7.   return false;
  8. }

 
  ‹‹ QXmlSchemaValidator and QAbstractMessageHandler      Building QT Embedded Widgets on Windows 7 ››

You must log in to post a reply. Not a member yet? Register here!