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?



  • 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 .....



  • 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.



  • 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.



  • Maybe there are problems with linking parent and children?

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



  • [quote author="Denis Kormalev" date="1280381190"]Maybe there are problems with linking parent and children?
    [/quote]
    No, link works as it should.

    @int AccountModel::rowCount(const QModelIndex& Index /= QModelIndex()/) const
    {
    TRACE_LOG("Start routine");
    if(!Index.isValid())
    return 0;
    AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
    Q_ASSERT(pItem != nullptr);
    return static_cast<int>(pItem->ChildCount());
    }@

    @QVariant AccountModel::data(const QModelIndex& Index,
    int Role) const
    {
    TRACE_LOG("Start routine");
    if(!Index.isValid())
    return QVariant();
    AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
    Q_ASSERT(pItem != nullptr);
    return pItem->Data(Role);
    }@

    @Qt::ItemFlags AccountModel::flags(const QModelIndex& Index) const
    {
    TRACE_LOG("Start routine");
    if (!Index.isValid())
    return 0;
    return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable
    | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
    }@

    @QModelIndex AccountModel::index(int Row,
    int Column,
    const QModelIndex& Index /= QModelIndex()/) const
    {
    TRACE_LOG("Start routine");
    if(!Index.isValid())
    return RootElement();
    AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
    Q_ASSERT(pItem != nullptr);
    AccountItem::ChildType Child = pItem->Child(static_cast<size_t>(Row));
    if(Child != c_InvalidChild)
    return createIndex(Row, Column, static_cast<void*>(Child));
    return QModelIndex();
    }@

    @QModelIndex AccountModel::parent(const QModelIndex& Index) const
    {
    TRACE_LOG("Start routine");
    if(!Index.isValid())
    return QModelIndex();
    AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
    Q_ASSERT(pItem != nullptr);
    AccountItem* pParent = pItem->Parent();
    //It is a one of the children...
    if(pParent != nullptr)
    return createIndex(pParent->Position(), 0, static_cast<void*>(pParent));
    //... or it is the root element.
    else
    return QModelIndex();
    }@

    @bool AccountModel::setData(const QModelIndex& Index,
    const QVariant& Value,
    int Role /= Qt::EditRole/)
    {
    TRACE_LOG("Start routine");
    if(!Index.isValid())
    return false;
    AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
    Q_ASSERT(pItem != nullptr);
    pItem->SetData(Role, Value);
    return true;
    }@

    @bool AccountModel::insertRows(int Row,
    int Count,
    const QModelIndex& Index /= QModelIndex()/)
    {
    TRACE_LOG("Start routine");
    if(!Index.isValid())
    return false;
    AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
    Q_ASSERT(pItem != nullptr);
    if(pItem->ChildCount() < static_cast<size_t>(Row) || Row < 0)
    return false;
    beginInsertRows(Index, Row, Row + Count - 1);
    for(int i = Row; i < Row + Count; ++i)
    {
    AccountItem* pNewItem = new AccountItem(nullptr);
    if(!pItem->InsertChild(pNewItem, static_cast<size_t>(i)))
    {
    WARN_LOG("Unable to insert child");
    delete pNewItem;
    return false;
    }
    }
    endInsertRows();
    return true;
    }@

    @bool AccountModel::hasChildren(const QModelIndex& Index /= QModelIndex()/) const
    {
    TRACE_LOG("Start routine");
    if(!Index.isValid())
    return false;
    AccountItem* pItem = static_cast<AccountItem*>(Index.internalPointer());
    Q_ASSERT(pItem != nullptr);
    return pItem->ChildCount();
    }@



  • 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.



  • 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.



  • 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?



  • [quote author="moellney" date="1280347222"]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.[/quote]

    Thank you!

    For those who experiance this problem, I'll describe my own case (maybe a common one). I had this simple data():
    @
    switch (role) {
    case Qt::DisplayRole:
    return "o_O";
    default:
    return false;
    }
    @
    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:
    @
    switch (role) {
    case Qt::DisplayRole:
    return "o_O";
    case Qt::SizeHintRole:
    return QSize(100, 100);
    default:
    return false;
    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.