Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Starting work with QTreeView, QAbstractItemModel

Starting work with QTreeView, QAbstractItemModel

Scheduled Pinned Locked Moved General and Desktop
2 Posts 2 Posters 11.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    lauku
    wrote on last edited by
    #1

    Hello.

    I am having problems with forcing QAbstractItemModel to work with QTreeView. I am aiming to create a simple contact list, and to do it I try to implement a very basic functionalities and then to extend it - but I'm struggling even with it. The code is compiling but nothing shows up in the widget.

    As a startpoint I chose Simple Tree example from "here":http://qt-project.org/doc/qt-4.8/itemviews-simpletreemodel.html .
    I have changed the Item to contain only QString, but after adding items, nothing is presented - as if QTreeView didn't read any data from model.

    the code is as follows:
    main.cpp
    @#include <QtGui/QApplication>
    #include <QTreeView>
    #include <QDebug>
    #include "rostermodel.h"
    #include "rosteritem.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    QTreeView *view = new QTreeView;
    
    RosterItem *it = new RosterItem(QString("Kris"));
    RosterModel *model = new RosterModel();
    model->addItem(it);
    it = new RosterItem(QString("Adam"));
    model->addItem(it);
    it = new RosterItem(QString("Sylvia"));
    model->addItem(it);
    view->setModel(model);
    view->show();
    
    return a.exec&#40;&#41;;
    

    }@

    rosteritem.h
    @class RosterItem
    {
    public:
    RosterItem(QString name, RosterItem *parent=0);
    ~RosterItem();

    void appendChild(RosterItem *cont);
    RosterItem *child(int row);
    int childCount() const;
    int columnCount() const;
    QVariant data() const;
    int row() const;
    RosterItem *parent();
    

    private:
    QList<RosterItem*> childItems;
    QString name;
    RosterItem *parentItem;

    };@

    rosteritem.cpp
    @#include "rosteritem.h"

    RosterItem::RosterItem(QString nam, RosterItem *parent):
    name(nam),parentItem(parent)
    {
    }

    RosterItem::~RosterItem()
    {
    qDeleteAll(childItems);
    }

    void RosterItem::appendChild(RosterItem *cont)
    {
    childItems.append(cont);
    }

    RosterItem* RosterItem::child(int row)
    {
    return childItems.value(row);
    }

    int RosterItem::childCount() const
    {
    return childItems.size();
    }

    int RosterItem::columnCount() const
    {
    return 1;
    }

    QVariant RosterItem::data() const
    {
    return name;
    }

    RosterItem* RosterItem::parent()
    {
    return parentItem;
    }

    int RosterItem::row() const
    {
    if(parentItem)
    {
    return parentItem->childItems.indexOf(const_cast<RosterItem*>(this));
    }
    return 0;
    }@

    rostermodel.h
    @#include <QAbstractItemModel>
    #include <QModelIndex>
    #include "rosteritem.h"

    class RosterModel : public QAbstractItemModel
    {
    Q_OBJECT
    public:
    explicit RosterModel(QObject parent = 0);
    ~RosterModel();
    Qt::ItemFlags flags(const QModelIndex &index) const;
    QVariant data(const QModelIndex &index, int role) const;
    void addItem(RosterItem
    item);
    QModelIndex parent(const QModelIndex &child) const;
    QModelIndex index(int row, int column, const QModelIndex &parent) const;
    int rowCount(const QModelIndex &parent) const;
    int columnCount(const QModelIndex &parent) const;
    QVariant headerData(int section, Qt::Orientation orientation,
    int role) const;

    private:
    RosterItem *root;
    };@

    rostermodel.cpp
    @#include "rostermodel.h"

    RosterModel::RosterModel(QObject *parent) :
    QAbstractItemModel(parent)
    {
    root=new RosterItem(QString("ROSTER"));
    }

    RosterModel::~RosterModel()
    {
    delete root;
    }

    Qt::ItemFlags RosterModel::flags(const QModelIndex &index) const
    {
    if (!index.isValid())
    return 0;

    return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    

    }

    QVariant RosterModel::data(const QModelIndex &index, int role) const
    {
    if (!index.isValid())
    return QVariant();

    if (role != Qt::DisplayRole)
        return QVariant();
    
    RosterItem *item = static_cast<RosterItem*>(index.internalPointer());
    
    return item->data();
    

    }

    void RosterModel::addItem(RosterItem *item)
    {
    root->appendChild(item);
    }

    QVariant RosterModel::headerData(int section, Qt::Orientation orientation,
    int role) const
    {
    return root->data();
    }

    QModelIndex RosterModel::parent(const QModelIndex &child) const
    {
    if (!child.isValid())return QModelIndex();

    RosterItem *childItem = static_cast<RosterItem*>(child.internalPointer());
    RosterItem *parentItem = childItem->parent();
    
    if (parentItem == root)
        return QModelIndex();
    
    return createIndex(parentItem->row(), 0, parentItem);
    

    }

    QModelIndex RosterModel::index(int row, int column, const QModelIndex &parent)
    const
    {
    if (!hasIndex(row, column, parent))
    return QModelIndex();

    RosterItem *parentItem;
    
    if (!parent.isValid())
        parentItem = root;
    else
        parentItem = static_cast<RosterItem*>(parent.internalPointer());
    
    RosterItem *childItem = parentItem->child(row);
    if (childItem) return createIndex(
                row, column, childItem);
    else return QModelIndex();
    

    }

    int RosterModel::columnCount(const QModelIndex &parent) const
    {
    if(parent.isValid())return 1;
    else return 0;
    }

    int RosterModel::rowCount(const QModelIndex &parent) const
    {
    RosterItem *parentItem;
    if (parent.column() > 0)
    return 0;

    if (!parent.isValid())
        parentItem = root;
    else
        parentItem = static_cast<RosterItem*>(parent.internalPointer());
    
    return parentItem->childCount();
    

    }
    @

    Thanks in advance for any advices.

    1 Reply Last reply
    0
    • jazzycamelJ Offline
      jazzycamelJ Offline
      jazzycamel
      wrote on last edited by
      #2

      Hi lauku,

      There were a few issues with your code:

      1. Your columnCount() was always returning 0 (i.e. no columns) because you required a valid parent to return 1 and "root" has no valid parents...

      2. None of your RosterItem's had a parent which meant that in your parent() function, when you call createIndex(), the first argument was invalid.

      3. Your headerData() function didn't check the role for which data was requested so you would never have had a visible header:

      I've corrected all these errors as shown below (see lines 8-10, 47-48 and 85-86 in rostermodel.cpp):

      main.cpp
      @
      #include <QtGui/QApplication>
      #include <QTreeView>
      #include <QDebug>
      #include "rostermodel.h"
      #include "rosteritem.h"

      int main(int argc, char *argv[])
      {
      QApplication a(argc, argv);

      QTreeView *view = new QTreeView;
      RosterModel *model = new RosterModel();
      view->setModel(model);
      view->show();
      
      return a.exec&#40;&#41;;
      

      }
      @

      rostermodel.cpp
      @
      #include "rostermodel.h"

      RosterModel::RosterModel(QObject *parent) :
      QAbstractItemModel(parent)
      {
      root=new RosterItem(QString("ROSTER"));

      root->appendChild(new RosterItem(QString("Kris"), root));
      root->appendChild(new RosterItem(QString("Adam"), root));
      root->appendChild(new RosterItem(QString("Sylvia"), root));
      

      }

      RosterModel::~RosterModel()
      {
      delete root;
      }

      Qt::ItemFlags RosterModel::flags(const QModelIndex &index) const
      {
      if (!index.isValid())
      return 0;

      return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
      

      }

      QVariant RosterModel::data(const QModelIndex &index, int role) const
      {
      if (!index.isValid())
      return QVariant();

      if (role != Qt::DisplayRole)
          return QVariant();
      
      RosterItem *item = static_cast<RosterItem*>(index.internalPointer());
      
      return item->data();
      

      }

      void RosterModel::addItem(RosterItem *item)
      {
      root->appendChild(item);
      }

      QVariant RosterModel::headerData(int section, Qt::Orientation orientation,
      int role) const
      {
      if(orientation==Qt::Horizontal && role==Qt::DisplayRole) return root->data();
      return QVariant();
      }

      QModelIndex RosterModel::parent(const QModelIndex &child) const
      {
      if (!child.isValid())return QModelIndex();

      RosterItem *childItem = static_cast<RosterItem*>(child.internalPointer());
      RosterItem *parentItem = childItem->parent();
      
      if (parentItem == root)
          return QModelIndex();
      
      return createIndex(parentItem->row(), 0, parentItem);
      

      }

      QModelIndex RosterModel::index(int row, int column, const QModelIndex &parent)
      const
      {
      if (!hasIndex(row, column, parent))
      return QModelIndex();

      RosterItem *parentItem;
      
      if (!parent.isValid())
          parentItem = root;
      else
          parentItem = static_cast<RosterItem*>(parent.internalPointer());
      
      RosterItem *childItem = parentItem->child(row);
      if (childItem) return createIndex(
                  row, column, childItem);
      else return QModelIndex();
      

      }

      int RosterModel::columnCount(const QModelIndex &parent) const
      {
      if(parent.isValid()) return static_cast<RosterItem*>(parent.internalPointer())->columnCount();
      return root->columnCount();
      }

      int RosterModel::rowCount(const QModelIndex &parent) const
      {
      RosterItem *parentItem;
      if (parent.column() > 0)
      return 0;

      if (!parent.isValid())
          parentItem = root;
      else
          parentItem = static_cast<RosterItem*>(parent.internalPointer());
      
      return parentItem->childCount();
      

      }
      @

      Hope this helps ;o)

      For the avoidance of doubt:

      1. All my code samples (C++ or Python) are tested before posting
      2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved