Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. [Solved] New TreeView does not connect to C++ model.
QtWS25 Last Chance

[Solved] New TreeView does not connect to C++ model.

Scheduled Pinned Locked Moved QML and Qt Quick
qml5.5c++model-viewmodel view progmodelviewqtquick2treeview
9 Posts 4 Posters 6.8k 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.
  • K Offline
    K Offline
    Kofr
    wrote on last edited by Kofr
    #1

    Hello guys, I was waiting long time before Qt 5.5 has been released because of new TreeView component.
    I am trying in agony to make it work with my model in C++ for a week.
    So, I am completely stuck in understanding how all this "kitchen" works.

    
        //main.qml
        
        import QtQuick 2.4
        import QtQuick.Controls 1.4
        import QtQuick.Window 2.2
        import dataModel 1.0
        
        ApplicationWindow {
            title: qsTr("Hello World")
            width: 640
            height: 480
            visible: true
        
            menuBar: MenuBar {
                Menu {
                    title: qsTr("&File")
                    MenuItem {
                        text: qsTr("&Open")
                        onTriggered: messageDialog.show(qsTr("Open action triggered"));
                    }
                    MenuItem {
                        text: qsTr("E&xit")
                        onTriggered: Qt.quit();
                    }
                }
            }
        
            TreeView {
                anchors.fill: parent
                model: DataModel
                TableViewColumn {
        
                    title: "Name"
                    role: "DisplayRole"
                    width: 300
        
                }
            }
        }
    
        //main.cpp
        #include <QApplication>
        #include <QQmlApplicationEngine>
        #include <QtGui>
        #include <QtQml>
        
        #include "treemodel.h"
        
        int main(int argc, char *argv[])
        {
            QApplication app(argc, argv);
        
            QQmlApplicationEngine engine;
            qmlRegisterType<TreeModel>("dataModel", 1, 0, "DataModel");
            engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        
            return app.exec();
        }
    
        //task.h
        
        #ifndef TASK_H
        #define TASK_H
        #include <QList>
        #include <QVariant>
        
        
        class Task
        {
        public:
            explicit Task(const QString &data, Task *parent = 0);
            ~Task();
        
            void appendChild(Task *child);
        
            Task *child(int row) const {return m_childItems.value(row);}
            int childCount() const;
            int columnCount() const {return 1;}
            QVariant data(int column) const;
            int row() const;
        
            QString getName() const {return name;}
        
            Task *parentItem();
        
        
        
        private:
            QList<Task*> m_childItems;
            //QList<QVariant> m_itemData;
            Task *m_parentItem;
            QString name;//data element for a while
        };
        
        #endif // TASK_H
    
        //task.cpp
        
        
        #include "task.h"
        #include <QVariant>
        #include <QDebug>
        
        Task::Task(const QString &data, Task *parent)
        {
            m_parentItem = parent;
            name = data;//to be modified
        }
        
        //Task::Task(QObject *parent) : QObject(parent)
        //{
        //    m_parentItem = parent;
        //}
        
        Task::~Task()
        {
        
        }
        
        void Task::appendChild(Task *child)
        {
            m_childItems.append(child);
            qDebug() << "appending a child";//it does not event shows
        }
        
        int Task::childCount() const
        {
            return m_childItems.count();
        
        }
        
        int Task::row() const
        {
            if (m_parentItem)
                return m_parentItem->m_childItems.indexOf(const_cast<Task*>(this));
            return -1;
        }
        
        Task *Task::parentItem()
        {
            return m_parentItem;
        }
    
        //treemodel.h
        
        #ifndef TREEMODEL_H
        #define TREEMODEL_H
        #include <QAbstractItemModel>
        #include "task.h"
        
        
        class TreeModel : public QAbstractItemModel
        {
        public:
            //TreeModel();
            explicit TreeModel(QObject *parent = 0);
            QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const Q_DECL_OVERRIDE;
            QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE;
            ~TreeModel();
            int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
            int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
            QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
        
            //void setupModelData(Task *parent);
        
        
            /*enum RoleNames {
                TaskNameRole = Qt::UserRole,
                TaskDateCreatedRole = Qt::UserRole + 1,
                TaskParentsRole = Qt::UserRole+2,
                TaskChildrensRole = Qt::UserRole+3,
                BrightnessRole = Qt::UserRole+4
            };*/
        private:
            QList<Task> m_data;
            Task * rootItem;
            //QHash<int, QByteArray> m_roleNames;
        };
        
        #endif // TREEMODEL_H
    
        //treemodel.cpp
        
        #include "treemodel.h"
        #include "task.h"
        
        TreeModel::TreeModel(QObject *parent)
            : QAbstractItemModel(parent)
        {
            rootItem = new Task(QString("default name"));
            //    m_roleNames[TaskNameRole] = "name";
            //    m_roleNames[TaskDateCreatedRole] = "dateCreated";
            //    m_roleNames[TaskParentsRole] = "parents";
            //    m_roleNames[TaskChildrensRole] = "childrens";
            //    m_roleNames[BrightnessRole] = "brightness";//to be changed
            //setupModelData(rootItem); //t
            rootItem->appendChild(new Task("alala1", rootItem) );
        }
        
        QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
        {
            if (!hasIndex(row, column, parent))
                return QModelIndex();
        
            Task *parentItem;
        
            if (!parent.isValid())
                parentItem = rootItem;
            else
                parentItem = static_cast<Task*>(parent.internalPointer());
        
            Task *childItem = parentItem->child(row);
            if (childItem)
                return createIndex(row, column, childItem);
            else
                return QModelIndex();
            //Q_UNUSED(parent);
            //if (row >= pkts.count() || row < 0 || column >= 8)
            //  return QModelIndex();
        
            //QStringList *pkt = pkts[row];
        
            //return createIndex(row, column, 0/*No Hierarchy yet*/);
        
        }
        
        QModelIndex TreeModel::parent(const QModelIndex &index) const
        {
            if (!index.isValid())
                return QModelIndex();
        
            Task *childItem = static_cast<Task*>(index.internalPointer());
            Task *parentItem = childItem->parentItem();
        
            if (parentItem == rootItem)
                return QModelIndex();
        
            return createIndex(parentItem->row(), 0, parentItem);//0 because tree structure. Trees have only children in first column
        }
        
        int TreeModel::rowCount(const QModelIndex &parent) const
        {
            Task *parentItem;
            /*if (parent.column() > 0)
                return 0;*/
        
            if (!parent.isValid())
                parentItem = rootItem;
            else
                parentItem = static_cast<Task*>(parent.internalPointer());
        
            return parentItem->childCount();
        }
        
        int TreeModel::columnCount(const QModelIndex &parent) const
        {
            if (parent.isValid())
                return static_cast<Task*>(parent.internalPointer())->columnCount();
            else
                return rootItem->columnCount();
        }
        QVariant TreeModel::data(const QModelIndex &index, int role) const
        {
            if (!index.isValid())
                return QVariant();
        
            if (role != Qt::DisplayRole)
                return QVariant();
        
            Task *item = static_cast<Task*>(index.internalPointer());
            return item->getName();//for a while
        
        
        }
        
        //void TreeModel::setupModelData(Task *parent)
        //{
        
        //}
        
        TreeModel::~TreeModel()
        {
            delete rootItem;
        }
    

    How to make TreeView to show what is inside my C++ model? Please correct me if you see some bullsh!t!

    p3c0P 1 Reply Last reply
    0
    • K Kofr

      Hello guys, I was waiting long time before Qt 5.5 has been released because of new TreeView component.
      I am trying in agony to make it work with my model in C++ for a week.
      So, I am completely stuck in understanding how all this "kitchen" works.

      
          //main.qml
          
          import QtQuick 2.4
          import QtQuick.Controls 1.4
          import QtQuick.Window 2.2
          import dataModel 1.0
          
          ApplicationWindow {
              title: qsTr("Hello World")
              width: 640
              height: 480
              visible: true
          
              menuBar: MenuBar {
                  Menu {
                      title: qsTr("&File")
                      MenuItem {
                          text: qsTr("&Open")
                          onTriggered: messageDialog.show(qsTr("Open action triggered"));
                      }
                      MenuItem {
                          text: qsTr("E&xit")
                          onTriggered: Qt.quit();
                      }
                  }
              }
          
              TreeView {
                  anchors.fill: parent
                  model: DataModel
                  TableViewColumn {
          
                      title: "Name"
                      role: "DisplayRole"
                      width: 300
          
                  }
              }
          }
      
          //main.cpp
          #include <QApplication>
          #include <QQmlApplicationEngine>
          #include <QtGui>
          #include <QtQml>
          
          #include "treemodel.h"
          
          int main(int argc, char *argv[])
          {
              QApplication app(argc, argv);
          
              QQmlApplicationEngine engine;
              qmlRegisterType<TreeModel>("dataModel", 1, 0, "DataModel");
              engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
          
              return app.exec();
          }
      
          //task.h
          
          #ifndef TASK_H
          #define TASK_H
          #include <QList>
          #include <QVariant>
          
          
          class Task
          {
          public:
              explicit Task(const QString &data, Task *parent = 0);
              ~Task();
          
              void appendChild(Task *child);
          
              Task *child(int row) const {return m_childItems.value(row);}
              int childCount() const;
              int columnCount() const {return 1;}
              QVariant data(int column) const;
              int row() const;
          
              QString getName() const {return name;}
          
              Task *parentItem();
          
          
          
          private:
              QList<Task*> m_childItems;
              //QList<QVariant> m_itemData;
              Task *m_parentItem;
              QString name;//data element for a while
          };
          
          #endif // TASK_H
      
          //task.cpp
          
          
          #include "task.h"
          #include <QVariant>
          #include <QDebug>
          
          Task::Task(const QString &data, Task *parent)
          {
              m_parentItem = parent;
              name = data;//to be modified
          }
          
          //Task::Task(QObject *parent) : QObject(parent)
          //{
          //    m_parentItem = parent;
          //}
          
          Task::~Task()
          {
          
          }
          
          void Task::appendChild(Task *child)
          {
              m_childItems.append(child);
              qDebug() << "appending a child";//it does not event shows
          }
          
          int Task::childCount() const
          {
              return m_childItems.count();
          
          }
          
          int Task::row() const
          {
              if (m_parentItem)
                  return m_parentItem->m_childItems.indexOf(const_cast<Task*>(this));
              return -1;
          }
          
          Task *Task::parentItem()
          {
              return m_parentItem;
          }
      
          //treemodel.h
          
          #ifndef TREEMODEL_H
          #define TREEMODEL_H
          #include <QAbstractItemModel>
          #include "task.h"
          
          
          class TreeModel : public QAbstractItemModel
          {
          public:
              //TreeModel();
              explicit TreeModel(QObject *parent = 0);
              QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const Q_DECL_OVERRIDE;
              QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE;
              ~TreeModel();
              int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
              int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
              QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
          
              //void setupModelData(Task *parent);
          
          
              /*enum RoleNames {
                  TaskNameRole = Qt::UserRole,
                  TaskDateCreatedRole = Qt::UserRole + 1,
                  TaskParentsRole = Qt::UserRole+2,
                  TaskChildrensRole = Qt::UserRole+3,
                  BrightnessRole = Qt::UserRole+4
              };*/
          private:
              QList<Task> m_data;
              Task * rootItem;
              //QHash<int, QByteArray> m_roleNames;
          };
          
          #endif // TREEMODEL_H
      
          //treemodel.cpp
          
          #include "treemodel.h"
          #include "task.h"
          
          TreeModel::TreeModel(QObject *parent)
              : QAbstractItemModel(parent)
          {
              rootItem = new Task(QString("default name"));
              //    m_roleNames[TaskNameRole] = "name";
              //    m_roleNames[TaskDateCreatedRole] = "dateCreated";
              //    m_roleNames[TaskParentsRole] = "parents";
              //    m_roleNames[TaskChildrensRole] = "childrens";
              //    m_roleNames[BrightnessRole] = "brightness";//to be changed
              //setupModelData(rootItem); //t
              rootItem->appendChild(new Task("alala1", rootItem) );
          }
          
          QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
          {
              if (!hasIndex(row, column, parent))
                  return QModelIndex();
          
              Task *parentItem;
          
              if (!parent.isValid())
                  parentItem = rootItem;
              else
                  parentItem = static_cast<Task*>(parent.internalPointer());
          
              Task *childItem = parentItem->child(row);
              if (childItem)
                  return createIndex(row, column, childItem);
              else
                  return QModelIndex();
              //Q_UNUSED(parent);
              //if (row >= pkts.count() || row < 0 || column >= 8)
              //  return QModelIndex();
          
              //QStringList *pkt = pkts[row];
          
              //return createIndex(row, column, 0/*No Hierarchy yet*/);
          
          }
          
          QModelIndex TreeModel::parent(const QModelIndex &index) const
          {
              if (!index.isValid())
                  return QModelIndex();
          
              Task *childItem = static_cast<Task*>(index.internalPointer());
              Task *parentItem = childItem->parentItem();
          
              if (parentItem == rootItem)
                  return QModelIndex();
          
              return createIndex(parentItem->row(), 0, parentItem);//0 because tree structure. Trees have only children in first column
          }
          
          int TreeModel::rowCount(const QModelIndex &parent) const
          {
              Task *parentItem;
              /*if (parent.column() > 0)
                  return 0;*/
          
              if (!parent.isValid())
                  parentItem = rootItem;
              else
                  parentItem = static_cast<Task*>(parent.internalPointer());
          
              return parentItem->childCount();
          }
          
          int TreeModel::columnCount(const QModelIndex &parent) const
          {
              if (parent.isValid())
                  return static_cast<Task*>(parent.internalPointer())->columnCount();
              else
                  return rootItem->columnCount();
          }
          QVariant TreeModel::data(const QModelIndex &index, int role) const
          {
              if (!index.isValid())
                  return QVariant();
          
              if (role != Qt::DisplayRole)
                  return QVariant();
          
              Task *item = static_cast<Task*>(index.internalPointer());
              return item->getName();//for a while
          
          
          }
          
          //void TreeModel::setupModelData(Task *parent)
          //{
          
          //}
          
          TreeModel::~TreeModel()
          {
              delete rootItem;
          }
      

      How to make TreeView to show what is inside my C++ model? Please correct me if you see some bullsh!t!

      p3c0P Offline
      p3c0P Offline
      p3c0
      Moderators
      wrote on last edited by p3c0
      #2

      Hi @Kofr,
      I find 2 issues here:

      • When using C++ models subclassed from item models always re-implement roleNames because that it how the C++ model comes to know which data to send to the QML.

      • You have registered the component using qmlRegisterType but not initialized it in QML. You will need to do this:

      DataModel {
          id: myModel
      }
      

      and then assign it

      TreeView {
          anchors.fill: parent
          model: myModel
      }
      

      OR
      instead you can also set the model as a context property in main.cpp

      TreeModel treemodel;
      engine.rootContext()->setContextProperty("myModel",treemodel);
      engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
      

      157

      K 1 Reply Last reply
      1
      • p3c0P p3c0

        Hi @Kofr,
        I find 2 issues here:

        • When using C++ models subclassed from item models always re-implement roleNames because that it how the C++ model comes to know which data to send to the QML.

        • You have registered the component using qmlRegisterType but not initialized it in QML. You will need to do this:

        DataModel {
            id: myModel
        }
        

        and then assign it

        TreeView {
            anchors.fill: parent
            model: myModel
        }
        

        OR
        instead you can also set the model as a context property in main.cpp

        TreeModel treemodel;
        engine.rootContext()->setContextProperty("myModel",treemodel);
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        
        K Offline
        K Offline
        Kofr
        wrote on last edited by
        #3

        @p3c0 thank you. How to know which role the Tree to show?

        
                    title: "Name"
                    role: "DisplayRole"
                    width: 300
                }
        

        does this mean that now our Tree shows Qt::DisplayRole ??

        I am listing my TreeModel::data() function to show that it must return data with any role. However this function is never called (no debug messages).

        QVariant TreeModel::data(const QModelIndex &index, int role) const
        {
            if (!index.isValid()) {
                qDebug() << "data() - index is invalid";//it does not event shows
                return QVariant();
            }
        
            //if (role != Qt::DisplayRole)
              //  return QVariant();
        
            Task *item = static_cast<Task*>(index.internalPointer());
            qDebug() << "data() - Data is about to be returned";//it does not event shows
            return item->getName();//for a while
        }
        
        p3c0P 1 Reply Last reply
        0
        • K Kofr

          @p3c0 thank you. How to know which role the Tree to show?

          
                      title: "Name"
                      role: "DisplayRole"
                      width: 300
                  }
          

          does this mean that now our Tree shows Qt::DisplayRole ??

          I am listing my TreeModel::data() function to show that it must return data with any role. However this function is never called (no debug messages).

          QVariant TreeModel::data(const QModelIndex &index, int role) const
          {
              if (!index.isValid()) {
                  qDebug() << "data() - index is invalid";//it does not event shows
                  return QVariant();
              }
          
              //if (role != Qt::DisplayRole)
                //  return QVariant();
          
              Task *item = static_cast<Task*>(index.internalPointer());
              qDebug() << "data() - Data is about to be returned";//it does not event shows
              return item->getName();//for a while
          }
          
          p3c0P Offline
          p3c0P Offline
          p3c0
          Moderators
          wrote on last edited by p3c0
          #4

          @Kofr No. These roles are different and should match exactly with those in C++ model. This problem is all due to roles not found. Re-implement the roleNames as follows:

          
          QHash<int, QByteArray> TreeModel::roleNames() const
          {
              QHash<int, QByteArray> roles;
              roles[TypeRole] = "DisplayRole";
              return roles;
          }
          
          //and define role names
          enum RoleNames {
              TypeRole = Qt::UserRole + 10,
          };
          
          //and then in data() ofcourse use as
          if (role != TypeRole)
                  return QVariant();
          

          157

          K 1 Reply Last reply
          1
          • p3c0P p3c0

            @Kofr No. These roles are different and should match exactly with those in C++ model. This problem is all due to roles not found. Re-implement the roleNames as follows:

            
            QHash<int, QByteArray> TreeModel::roleNames() const
            {
                QHash<int, QByteArray> roles;
                roles[TypeRole] = "DisplayRole";
                return roles;
            }
            
            //and define role names
            enum RoleNames {
                TypeRole = Qt::UserRole + 10,
            };
            
            //and then in data() ofcourse use as
            if (role != TypeRole)
                    return QVariant();
            
            K Offline
            K Offline
            Kofr
            wrote on last edited by
            #5

            @p3c0 Great success! Now it works.
            stage 1 is complete. Now running to make it editable.

            p3c0P 1 Reply Last reply
            0
            • K Kofr

              @p3c0 Great success! Now it works.
              stage 1 is complete. Now running to make it editable.

              p3c0P Offline
              p3c0P Offline
              p3c0
              Moderators
              wrote on last edited by
              #6

              @Kofr Nice. Happy Coding..

              157

              1 Reply Last reply
              1
              • V Offline
                V Offline
                Valerian
                wrote on last edited by
                #7

                @Kofr @p3c0
                I need some help regarding re-ordering of the item of the QAbstractItemModel. I have put a MouseArea in the itemDelegate which allows me to drag an item. I need some help to call C++ function of the QAbstractItemModel to move items to support the dynamic re-ordering. Kindly advice

                K 1 Reply Last reply
                0
                • V Valerian

                  @Kofr @p3c0
                  I need some help regarding re-ordering of the item of the QAbstractItemModel. I have put a MouseArea in the itemDelegate which allows me to drag an item. I need some help to call C++ function of the QAbstractItemModel to move items to support the dynamic re-ordering. Kindly advice

                  K Offline
                  K Offline
                  Kofr
                  wrote on last edited by
                  #8

                  @Valerian I did not do d&d yet. In my idea you should register a signal to be emitted whenever you move mouse in the area of new position and call swap function.
                  Do you feel something like this?

                  1 Reply Last reply
                  0
                  • S Offline
                    S Offline
                    Sumana
                    wrote on last edited by
                    #9

                    @Kofr I am stuck into a similar problem, Can you by any chance provide the working code where the TreeView(with parent-child relation) is editable too? Considering that this post was really long back, but it will be a huge help if the code (completed with the qml and C++ too) is provided! Thanks in advance!

                    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