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. Using pointer in C++ model for QML
Forum Updated to NodeBB v4.3 + New Features

Using pointer in C++ model for QML

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
3 Posts 3 Posters 839 Views 1 Watching
  • 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.
  • J Offline
    J Offline
    JorisC
    wrote on 15 Aug 2021, 03:35 last edited by JorisC
    #1

    Dear All,

    I'm currently coding a c++ model for display it in a ListVieew in QML side. This point is OK for me, I have followed the c++ model in QML tutorial (https://www.youtube.com/watch?v=9BcAYDlpuT8&list=WL&index=29&t=1280s)

    Problem: Contrary to the turorial, in my C++ list class I have a structure which contains a pointer ( serie_graphe* serie;) and I don't know how to access it in QML side. In QML side, I would like to deal with something like "model.serie"

    serielist.h

    #ifndef SERIELIST_H
    #define SERIELIST_H
    
    #include <QObject>
    #include <QVector>
    #include <serie_graphe.h>
    
    struct SerieItem
    {
        bool selection;
        serie_graphe* serie;
        QString nom;
        int id;
    };
    
    class SerieList : public QObject
    {
       Q_OBJECT
    public:
        explicit SerieList(QObject *parent = nullptr);
    
        QVector<SerieItem> items() const;
    
        bool setItemAt(int index, const SerieItem &item);
    
    signals:
        void preItemAppended();
        void postItemAppended();
    
    public slots:
        void appendItem(serie_graphe* nouvelle_serie);
    
    public:
        QVector<SerieItem> mItems;
    
        int numero = 0;
    };
    
    #endif // SERIELIST_H
    

    serielist.cpp

    #include "serielist.h"
    
    SerieList::SerieList(QObject *parent) : QObject(parent)
    {
    //    mItems.append({ true, QStringLiteral("Nick ta reum")});
    //    mItems.append({ false, QStringLiteral("Fix the sink") });
    }
    
    QVector<SerieItem> SerieList::items() const
    {
        return mItems;
    }
    
    bool SerieList::setItemAt(int index, const SerieItem &item)
    {
        if (index < 0 || index >= mItems.size())
            return false;
    
        const SerieItem &oldItem = mItems.at(index);
        if (item.selection == oldItem.selection && item.nom == oldItem.nom)
            return false;
    
        mItems[index] = item;
        return true;
    }
    
    void SerieList::appendItem(serie_graphe* nouvelle_serie)
    {
        emit preItemAppended();
    
        SerieItem item;
        item.selection = false;
        item.serie = nouvelle_serie;
        item.nom = nouvelle_serie->nom_serie;
        item.id = numero;
        mItems.append(item);
    
        numero++;                           //On incrémente le numéro de série en vue d'un prochain ajout
    
        emit postItemAppended();
    }
    

    Unfortunately, in the data function in seriemodel.cpp, I cannot handle "serieRole" with a Qvariant in my model (seriemodel class) ...

    seriemodel.cpp

    #include "seriemodel.h"
    
    #include "serielist.h"
    
    SerieModel::SerieModel(QObject *parent)
        :QAbstractListModel(parent)
        , mList(nullptr)
    {
    }
    
    
    int SerieModel::rowCount(const QModelIndex &parent) const
    {
        if (parent.isValid() || !mList )
            return 0;
    
        return mList->items().size();
    }
    
    
    QVariant SerieModel::data(const QModelIndex &index, int role) const
    {
        if (!index.isValid() || !mList)
            return QVariant();
    
        const SerieItem item = mList->items().at(index.row());
        switch (role) {
        case SelectionRole:
            return QVariant(item.selection);
        case NomRole:
            return QVariant(item.nom);
        case SerieRole:
            return QVariant(item.serie);            //PROBLEM HERE because item.serie is a pointer .... and cannot be handle with QVARIANT
        case IDRole:
            return QVariant(item.id);
        }
    
        return QVariant();
    }
    
    
    Qt::ItemFlags SerieModel::flags(const QModelIndex &index) const
    {
        if (!index.isValid())
            return Qt::NoItemFlags;
    
        return Qt::ItemIsEditable; // FIXME: Implement me!
    }
    
    QHash<int, QByteArray> SerieModel::roleNames() const
    {
        QHash<int, QByteArray> names;
        names[SelectionRole] = "selection";
        names[NomRole] = "nom";
        names[SerieRole] = "serie";
        names[IDRole] = "id";
        return names;
    }
    
    SerieList *SerieModel::list() const
    {
        return mList;
    }
    
    void SerieModel::setList(SerieList *list)
    {
        beginResetModel();
    
        if (mList)
            mList->disconnect(this);
    
        mList = list;
    
        if (mList) {
            connect(mList, &SerieList::preItemAppended, this, [=]() {
                const int index = mList->items().size();
                beginInsertRows(QModelIndex(), index, index);
            });
            connect(mList, &SerieList::postItemAppended, this, [=]() {
                endInsertRows();
            });
           }
        endResetModel();
    
    
    }
    

    seriemodel.h

    #ifndef SERIEMODEL_H
    #define SERIEMODEL_H
    
    #include <QAbstractListModel>
    
    class SerieList;
    
    class SerieModel : public QAbstractListModel
    {
        Q_OBJECT
        Q_PROPERTY(SerieList *list READ list WRITE setList)
    
    public:
        explicit SerieModel(QObject *parent = nullptr);
    
        enum {
            SelectionRole = Qt::UserRole,
            NomRole,
            SerieRole,
            IDRole
        };
    
        // Basic functionality:
        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    
        // Editable:
    //    bool setData(const QModelIndex &index, const QVariant &value,
    //                int role = Qt::EditRole) override;
    
        Qt::ItemFlags flags(const QModelIndex& index) const override;
    
        virtual QHash<int, QByteArray> roleNames() const override;
    
        SerieList *list() const;
        void setList(SerieList *list);
    
    private:
        SerieList *mList;
    };
    
    #endif // SERIEMODEL_H
    

    In QML I would like for example:

    ListView {
                implicitWidth: parent.width
                implicitHeight:parent.height
                anchors.fill: parent
                clip: true
    
                model: SerieModel {
                    list: serieList
                }
    
                delegate: RowLayout {
                    width: parent.width
                    height: 30
    
                    CheckBox {
                        checked: model.selection
                        onClicked: {model.selection = checked;serieList_activePlot.appendItem(model.serie);} //HERE I would like to use model.serie
                    }
    
                    Text {
                        text: model.nom
                        Layout.fillWidth: true
                        minimumPixelSize: 10
                    }
    

    Thank you in advance if someone can help me to handle this pointer in order to use it in my model.serie.

    Regards,
    JC

    raven-worxR 1 Reply Last reply 15 Aug 2021, 09:15
    0
    • J JorisC
      15 Aug 2021, 03:35

      Dear All,

      I'm currently coding a c++ model for display it in a ListVieew in QML side. This point is OK for me, I have followed the c++ model in QML tutorial (https://www.youtube.com/watch?v=9BcAYDlpuT8&list=WL&index=29&t=1280s)

      Problem: Contrary to the turorial, in my C++ list class I have a structure which contains a pointer ( serie_graphe* serie;) and I don't know how to access it in QML side. In QML side, I would like to deal with something like "model.serie"

      serielist.h

      #ifndef SERIELIST_H
      #define SERIELIST_H
      
      #include <QObject>
      #include <QVector>
      #include <serie_graphe.h>
      
      struct SerieItem
      {
          bool selection;
          serie_graphe* serie;
          QString nom;
          int id;
      };
      
      class SerieList : public QObject
      {
         Q_OBJECT
      public:
          explicit SerieList(QObject *parent = nullptr);
      
          QVector<SerieItem> items() const;
      
          bool setItemAt(int index, const SerieItem &item);
      
      signals:
          void preItemAppended();
          void postItemAppended();
      
      public slots:
          void appendItem(serie_graphe* nouvelle_serie);
      
      public:
          QVector<SerieItem> mItems;
      
          int numero = 0;
      };
      
      #endif // SERIELIST_H
      

      serielist.cpp

      #include "serielist.h"
      
      SerieList::SerieList(QObject *parent) : QObject(parent)
      {
      //    mItems.append({ true, QStringLiteral("Nick ta reum")});
      //    mItems.append({ false, QStringLiteral("Fix the sink") });
      }
      
      QVector<SerieItem> SerieList::items() const
      {
          return mItems;
      }
      
      bool SerieList::setItemAt(int index, const SerieItem &item)
      {
          if (index < 0 || index >= mItems.size())
              return false;
      
          const SerieItem &oldItem = mItems.at(index);
          if (item.selection == oldItem.selection && item.nom == oldItem.nom)
              return false;
      
          mItems[index] = item;
          return true;
      }
      
      void SerieList::appendItem(serie_graphe* nouvelle_serie)
      {
          emit preItemAppended();
      
          SerieItem item;
          item.selection = false;
          item.serie = nouvelle_serie;
          item.nom = nouvelle_serie->nom_serie;
          item.id = numero;
          mItems.append(item);
      
          numero++;                           //On incrémente le numéro de série en vue d'un prochain ajout
      
          emit postItemAppended();
      }
      

      Unfortunately, in the data function in seriemodel.cpp, I cannot handle "serieRole" with a Qvariant in my model (seriemodel class) ...

      seriemodel.cpp

      #include "seriemodel.h"
      
      #include "serielist.h"
      
      SerieModel::SerieModel(QObject *parent)
          :QAbstractListModel(parent)
          , mList(nullptr)
      {
      }
      
      
      int SerieModel::rowCount(const QModelIndex &parent) const
      {
          if (parent.isValid() || !mList )
              return 0;
      
          return mList->items().size();
      }
      
      
      QVariant SerieModel::data(const QModelIndex &index, int role) const
      {
          if (!index.isValid() || !mList)
              return QVariant();
      
          const SerieItem item = mList->items().at(index.row());
          switch (role) {
          case SelectionRole:
              return QVariant(item.selection);
          case NomRole:
              return QVariant(item.nom);
          case SerieRole:
              return QVariant(item.serie);            //PROBLEM HERE because item.serie is a pointer .... and cannot be handle with QVARIANT
          case IDRole:
              return QVariant(item.id);
          }
      
          return QVariant();
      }
      
      
      Qt::ItemFlags SerieModel::flags(const QModelIndex &index) const
      {
          if (!index.isValid())
              return Qt::NoItemFlags;
      
          return Qt::ItemIsEditable; // FIXME: Implement me!
      }
      
      QHash<int, QByteArray> SerieModel::roleNames() const
      {
          QHash<int, QByteArray> names;
          names[SelectionRole] = "selection";
          names[NomRole] = "nom";
          names[SerieRole] = "serie";
          names[IDRole] = "id";
          return names;
      }
      
      SerieList *SerieModel::list() const
      {
          return mList;
      }
      
      void SerieModel::setList(SerieList *list)
      {
          beginResetModel();
      
          if (mList)
              mList->disconnect(this);
      
          mList = list;
      
          if (mList) {
              connect(mList, &SerieList::preItemAppended, this, [=]() {
                  const int index = mList->items().size();
                  beginInsertRows(QModelIndex(), index, index);
              });
              connect(mList, &SerieList::postItemAppended, this, [=]() {
                  endInsertRows();
              });
             }
          endResetModel();
      
      
      }
      

      seriemodel.h

      #ifndef SERIEMODEL_H
      #define SERIEMODEL_H
      
      #include <QAbstractListModel>
      
      class SerieList;
      
      class SerieModel : public QAbstractListModel
      {
          Q_OBJECT
          Q_PROPERTY(SerieList *list READ list WRITE setList)
      
      public:
          explicit SerieModel(QObject *parent = nullptr);
      
          enum {
              SelectionRole = Qt::UserRole,
              NomRole,
              SerieRole,
              IDRole
          };
      
          // Basic functionality:
          int rowCount(const QModelIndex &parent = QModelIndex()) const override;
      
          QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
      
          // Editable:
      //    bool setData(const QModelIndex &index, const QVariant &value,
      //                int role = Qt::EditRole) override;
      
          Qt::ItemFlags flags(const QModelIndex& index) const override;
      
          virtual QHash<int, QByteArray> roleNames() const override;
      
          SerieList *list() const;
          void setList(SerieList *list);
      
      private:
          SerieList *mList;
      };
      
      #endif // SERIEMODEL_H
      

      In QML I would like for example:

      ListView {
                  implicitWidth: parent.width
                  implicitHeight:parent.height
                  anchors.fill: parent
                  clip: true
      
                  model: SerieModel {
                      list: serieList
                  }
      
                  delegate: RowLayout {
                      width: parent.width
                      height: 30
      
                      CheckBox {
                          checked: model.selection
                          onClicked: {model.selection = checked;serieList_activePlot.appendItem(model.serie);} //HERE I would like to use model.serie
                      }
      
                      Text {
                          text: model.nom
                          Layout.fillWidth: true
                          minimumPixelSize: 10
                      }
      

      Thank you in advance if someone can help me to handle this pointer in order to use it in my model.serie.

      Regards,
      JC

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on 15 Aug 2021, 09:15 last edited by raven-worx
      #2

      @JorisC
      the only way to make QML aware of the "serie_graphe" type is by letting "serie_graphe" derive from QObject.
      Otherwise you would need to route each member/property of "serie_graphe" with adedicated item role.
      Or convert your "serie_graphe" to a QVariantMap (key-value like)

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      0
      • J Offline
        J Offline
        jalali_shikha
        wrote on 5 Jan 2022, 09:03 last edited by
        #3

        @JorisC said in Using pointer in C++ model for QML:

            return QVariant(item.serie);            //PROBLEM HERE because item.serie is a pointer .... and cannot be handle with QVARIANT
        

        You can use return QVariant::fromValue(item.serie);

        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