Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Starting work with QTreeView, QAbstractItemModel

    General and Desktop
    2
    2
    11256
    Loading More Posts
    • 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
      lauku last edited by

      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 Reply Quote 0
      • jazzycamel
        jazzycamel last edited by

        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 Reply Quote 0
        • First post
          Last post