Qt Forum

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

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

    QML and Qt Quick
    qml 5.5 c++ model-view model view prog modelview qtquick2 treeview
    4
    9
    5918
    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.
    • K
      Kofr last edited by 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!

      p3c0 1 Reply Last reply Reply Quote 0
      • p3c0
        p3c0 Moderators @Kofr last edited by 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")));
        

        157

        K 1 Reply Last reply Reply Quote 1
        • K
          Kofr @p3c0 last edited by

          @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
          }
          
          p3c0 1 Reply Last reply Reply Quote 0
          • p3c0
            p3c0 Moderators @Kofr last edited by 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();
            

            157

            K 1 Reply Last reply Reply Quote 1
            • K
              Kofr @p3c0 last edited by

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

              p3c0 1 Reply Last reply Reply Quote 0
              • p3c0
                p3c0 Moderators @Kofr last edited by

                @Kofr Nice. Happy Coding..

                157

                1 Reply Last reply Reply Quote 1
                • V
                  Valerian last edited by

                  @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 Reply Quote 0
                  • K
                    Kofr @Valerian last edited by

                    @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 Reply Quote 0
                    • S
                      Sumana last edited by

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