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. Best way to access a cpp structure in QML
QtWS25 Last Chance

Best way to access a cpp structure in QML

Scheduled Pinned Locked Moved Solved QML and Qt Quick
qmlqtquickqtquick2qvariant
19 Posts 6 Posters 19.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.
  • P Offline
    P Offline
    pra7
    wrote on 12 Aug 2017, 12:34 last edited by
    #1

    I need to pass structures between cpp and QML. If i use property i should create an individual set and get functions, My structure contains minimum 5 members so i felt it's not good to use set and get for all those members.
    Following is an example of what i am trying to do :

    MyClass.h

    #include <QObject>
    #include <QDebug>
    using namespace std;
    
    struct MyStruct
    {
        int val;
        QString name1 ;
        QString name2 ;
        QString name3 ;
        QString name4 ;
    };
    
    class MyClass:public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QVariant myVariant READ getmyVariant
                    WRITE setmyVariant NOTIFY myVariantChanged)
    
    public:
        explicit MyClass(QObject *parent = nullptr);
        MyStruct strObj;
        
         QVariant getmyVariant() const
         {
             QVariant var;
             var.setValue(strObj);
             return var;
         }
    
    void setmyVariant(<Arguments>)
    {
        //How to set the value from QML
    }
    
    signals:
    void myVariantChanged();
    
    }
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include <QDebug>
    #include <QObject>
    
    #include "MyClass.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine;
    
        MyClass classObj;
    
        engine.rootContext()->setContextProperty("classObj",&classObj);
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    

    Main.qml

    import QtQuick 2.6
    import QtQuick.Controls 2.2
    import QtQuick.Window 2.3
    
    ApplicationWindow {
    
        id: applicationWindow
    
        visible: true
        width: 600
        height: 400
        title: qsTr("My App")
    
        MainForm{
            id : mainform
    
            Component.onCompleted: {
            console.log("name===="+classObj.myVariant.name1) //***undefined
            }
        }
    }
    

    If i print just (classObj.myVariant) i am getting QVariant(MyStruct) but when i tried to access any parameter like classObj.myVariant.name1 i am getting "undefined" and also how to set a variant from QML?

    1 Reply Last reply
    0
    • ? A Former User
      12 Aug 2017, 18:13

      Hi! Simple answer is: no. To make the members' names available to QML your object has to derive from QObject and expose the members via Q_PROPERTY. If, for some reason, you need to keep the struct as it is, you'll need to provide a wrapper class as an interface to QML, like:

      #ifndef MYWRAPPER_H
      #define MYWRAPPER_H
      
      #include <QObject>
      
      class MyStruct;
      
      class MyWrapper : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(int val READ val WRITE setVal NOTIFY valChanged)
          // ...
      
      public:
          explicit MyWrapper(QObject *parent = nullptr);
          ~MyWrapper();
      
          int val() const;
          void setVal(int v);
          // ...
      
      signals:
          valChanged(int);
          // ...
      
      private:
          MyStruct *m_myStruct;
      };
      
      #endif // MYWRAPPER_H
      

      A QVariant with a POD inside does not expose its members' names to the QML environment. If you want to go with QVariant and have names you need to use QVariantMap. Here is a class "Car" that exposes your MyStruct as a QVariantMap:

      car.h

      #ifndef CAR_H
      #define CAR_H
      
      #include <QObject>
      #include <QVariantMap>
      #include "mystruct.h"
      
      class Car : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(QVariantMap myStruct READ getMyStruct WRITE setMyStruct NOTIFY myStructChanged)
      
      public:
          Car(QObject *parent = nullptr);
      
          QVariantMap getMyStruct() const;
          void setMyStruct(QVariantMap myStruct);
      
      signals:
          void myStructChanged(QVariantMap myStruct);
      
      private:
          MyStruct m_myStruct;
      };
      
      #endif // CAR_H
      

      car.cpp

      #include "car.h"
      #include "myadapter.h"
      
      Car::Car(QObject *parent)
          : QObject(parent)
      {
      }
      
      QVariantMap Car::getMyStruct() const
      {
          return myStructToQVariantMap(m_myStruct);
      }
      
      void Car::setMyStruct(QVariantMap myStruct)
      {
          MyStruct newValue = myStructFromQVariantMap(myStruct);
          if (myStructEqual(m_myStruct, newValue))
              return;
          m_myStruct = newValue;
          emit myStructChanged(myStruct);
      }
      

      It relies on some helper functions:
      myadapter.h

      #ifndef MYADAPTER_H
      #define MYADAPTER_H
      
      #include "mystruct.h"
      #include <QVariantMap>
      
      QVariantMap myStructToQVariantMap(MyStruct const &myStruct);
      MyStruct myStructFromQVariantMap(QVariantMap const &vm);
      bool myStructEqual(MyStruct const &myStruct1, MyStruct const &myStruct2);
      
      #endif // MYADAPTER_H
      

      myadapter.cpp

      #include "myadapter.h"
      
      QVariantMap myStructToQVariantMap(const MyStruct &myStruct)
      {
          QVariantMap res;
          res.insert("val", myStruct.val);
          res.insert("name1", myStruct.name1);
          res.insert("name2", myStruct.name2);
          res.insert("name3", myStruct.name3);
          res.insert("name4", myStruct.name4);
          return res;
      }
      
      MyStruct myStructFromQVariantMap(const QVariantMap &vm)
      {
          MyStruct res;
          res.val = vm.value("val").toInt();
          res.name1 = vm.value("name1").toString();
          res.name2 = vm.value("name2").toString();
          res.name3 = vm.value("name3").toString();
          res.name4 = vm.value("name4").toString();
          return res;
      }
      
      bool myStructEqual(MyStruct const &myStruct1, MyStruct const &myStruct2)
      {
          if (myStruct1.val != myStruct2.val) return false;
          if (myStruct1.name1 != myStruct2.name1) return false;
          if (myStruct1.name2 != myStruct2.name2) return false;
          if (myStruct1.name3 != myStruct2.name3) return false;
          if (myStruct1.name4 != myStruct2.name4) return false;
          return true;
      }
      

      As you can see, this QVariantMap approach is pretty cumbersome and obviously involves a lot of copying. But at least you can now access "the members" by their names in QML and you get the notifications when the MyStruct object changes.

          Forum.Car {
              id: myCar
          }
      
          Row {
              anchors.centerIn: parent
              spacing: 20
      
              Button {
                  text: "click me"
                  onClicked: {
                      var obj = myCar.myStruct // retrieve a copy of the struct
                      obj.val = 42 // set value in the copy
                      myCar.myStruct = obj // replace old struct with the copy
                  }
              }
      
              Label {
                  text: myCar.myStruct.val
              }
          }
      
      P Offline
      P Offline
      pra7
      wrote on 12 Aug 2017, 18:56 last edited by
      #6

      @Wieland Thanks!!! for your suggestion after lot of reading and searching I got the answer ,Actually we can use structs or any object which is not derived from QObject by using Q_GADGET :

      struct MyStruct {
          Q_GADGET
          int m_val;
          QString m_name1;
          QString m_name2;
          QString m_name3;
          QString m_name4;
          Q_PROPERTY(int val MEMBER m_val)
          Q_PROPERTY(QString name1 MEMBER m_name1)
          Q_PROPERTY(QString name2 MEMBER m_name2)
          Q_PROPERTY(QString name3 MEMBER m_name3)
          Q_PROPERTY(QString name4 MEMBER m_name4)
      };
      

      Then in my class i just replaced QVariant as below :

      class MyClass:public QObject
      {
          Q_OBJECT
          Q_PROPERTY(MyStruct mystr READ getMyStruct
                      WRITE setMyStruct NOTIFY myStructChanged)
      
      public:
          explicit MyClass(QObject *parent = nullptr);
          MyStruct strObj;
      
           // Edit: changed get function
           MyStruct getMyStruct() const
           {
               return strObj;
           }
      
      // Edit: Added set function
           void setMyStruct(myStruct val)
              {
                  mystr = val;
                  emit myStructChanged();
              }
      signals:
      void myStructChanged();
      
      }
      

      Now in QML file i can just use classObj.mystr.name1 to access the members and i can just use classObj.mystr.name1 = "abc" to set the values.

      ? S 2 Replies Last reply 12 Aug 2017, 20:30
      4
      • timdayT Offline
        timdayT Offline
        timday
        wrote on 12 Aug 2017, 18:01 last edited by timday 8 Dec 2017, 18:01
        #2

        If your struct really is just 5 QStrings, personally I'd just use a QStringList (which I believe QVariant supports nicely) to communicate its state into (and from) the QML/Javascript domain.

        ? 1 Reply Last reply 12 Aug 2017, 18:26
        0
        • ? Offline
          ? Offline
          A Former User
          wrote on 12 Aug 2017, 18:13 last edited by A Former User 8 Dec 2017, 18:18
          #3

          Hi! Simple answer is: no. To make the members' names available to QML your object has to derive from QObject and expose the members via Q_PROPERTY. If, for some reason, you need to keep the struct as it is, you'll need to provide a wrapper class as an interface to QML, like:

          #ifndef MYWRAPPER_H
          #define MYWRAPPER_H
          
          #include <QObject>
          
          class MyStruct;
          
          class MyWrapper : public QObject
          {
              Q_OBJECT
              Q_PROPERTY(int val READ val WRITE setVal NOTIFY valChanged)
              // ...
          
          public:
              explicit MyWrapper(QObject *parent = nullptr);
              ~MyWrapper();
          
              int val() const;
              void setVal(int v);
              // ...
          
          signals:
              valChanged(int);
              // ...
          
          private:
              MyStruct *m_myStruct;
          };
          
          #endif // MYWRAPPER_H
          

          A QVariant with a POD inside does not expose its members' names to the QML environment. If you want to go with QVariant and have names you need to use QVariantMap. Here is a class "Car" that exposes your MyStruct as a QVariantMap:

          car.h

          #ifndef CAR_H
          #define CAR_H
          
          #include <QObject>
          #include <QVariantMap>
          #include "mystruct.h"
          
          class Car : public QObject
          {
              Q_OBJECT
              Q_PROPERTY(QVariantMap myStruct READ getMyStruct WRITE setMyStruct NOTIFY myStructChanged)
          
          public:
              Car(QObject *parent = nullptr);
          
              QVariantMap getMyStruct() const;
              void setMyStruct(QVariantMap myStruct);
          
          signals:
              void myStructChanged(QVariantMap myStruct);
          
          private:
              MyStruct m_myStruct;
          };
          
          #endif // CAR_H
          

          car.cpp

          #include "car.h"
          #include "myadapter.h"
          
          Car::Car(QObject *parent)
              : QObject(parent)
          {
          }
          
          QVariantMap Car::getMyStruct() const
          {
              return myStructToQVariantMap(m_myStruct);
          }
          
          void Car::setMyStruct(QVariantMap myStruct)
          {
              MyStruct newValue = myStructFromQVariantMap(myStruct);
              if (myStructEqual(m_myStruct, newValue))
                  return;
              m_myStruct = newValue;
              emit myStructChanged(myStruct);
          }
          

          It relies on some helper functions:
          myadapter.h

          #ifndef MYADAPTER_H
          #define MYADAPTER_H
          
          #include "mystruct.h"
          #include <QVariantMap>
          
          QVariantMap myStructToQVariantMap(MyStruct const &myStruct);
          MyStruct myStructFromQVariantMap(QVariantMap const &vm);
          bool myStructEqual(MyStruct const &myStruct1, MyStruct const &myStruct2);
          
          #endif // MYADAPTER_H
          

          myadapter.cpp

          #include "myadapter.h"
          
          QVariantMap myStructToQVariantMap(const MyStruct &myStruct)
          {
              QVariantMap res;
              res.insert("val", myStruct.val);
              res.insert("name1", myStruct.name1);
              res.insert("name2", myStruct.name2);
              res.insert("name3", myStruct.name3);
              res.insert("name4", myStruct.name4);
              return res;
          }
          
          MyStruct myStructFromQVariantMap(const QVariantMap &vm)
          {
              MyStruct res;
              res.val = vm.value("val").toInt();
              res.name1 = vm.value("name1").toString();
              res.name2 = vm.value("name2").toString();
              res.name3 = vm.value("name3").toString();
              res.name4 = vm.value("name4").toString();
              return res;
          }
          
          bool myStructEqual(MyStruct const &myStruct1, MyStruct const &myStruct2)
          {
              if (myStruct1.val != myStruct2.val) return false;
              if (myStruct1.name1 != myStruct2.name1) return false;
              if (myStruct1.name2 != myStruct2.name2) return false;
              if (myStruct1.name3 != myStruct2.name3) return false;
              if (myStruct1.name4 != myStruct2.name4) return false;
              return true;
          }
          

          As you can see, this QVariantMap approach is pretty cumbersome and obviously involves a lot of copying. But at least you can now access "the members" by their names in QML and you get the notifications when the MyStruct object changes.

              Forum.Car {
                  id: myCar
              }
          
              Row {
                  anchors.centerIn: parent
                  spacing: 20
          
                  Button {
                      text: "click me"
                      onClicked: {
                          var obj = myCar.myStruct // retrieve a copy of the struct
                          obj.val = 42 // set value in the copy
                          myCar.myStruct = obj // replace old struct with the copy
                      }
                  }
          
                  Label {
                      text: myCar.myStruct.val
                  }
              }
          
          P 1 Reply Last reply 12 Aug 2017, 18:56
          4
          • timdayT timday
            12 Aug 2017, 18:01

            If your struct really is just 5 QStrings, personally I'd just use a QStringList (which I believe QVariant supports nicely) to communicate its state into (and from) the QML/Javascript domain.

            ? Offline
            ? Offline
            A Former User
            wrote on 12 Aug 2017, 18:26 last edited by
            #4

            @timday QStringList is directly supported by QML, no need to go through QVariant.

            P 1 Reply Last reply 12 Aug 2017, 18:52
            3
            • ? A Former User
              12 Aug 2017, 18:26

              @timday QStringList is directly supported by QML, no need to go through QVariant.

              P Offline
              P Offline
              Praveen_2017
              wrote on 12 Aug 2017, 18:52 last edited by Praveen_2017 8 Dec 2017, 18:53
              #5
              This post is deleted!
              1 Reply Last reply
              0
              • ? A Former User
                12 Aug 2017, 18:13

                Hi! Simple answer is: no. To make the members' names available to QML your object has to derive from QObject and expose the members via Q_PROPERTY. If, for some reason, you need to keep the struct as it is, you'll need to provide a wrapper class as an interface to QML, like:

                #ifndef MYWRAPPER_H
                #define MYWRAPPER_H
                
                #include <QObject>
                
                class MyStruct;
                
                class MyWrapper : public QObject
                {
                    Q_OBJECT
                    Q_PROPERTY(int val READ val WRITE setVal NOTIFY valChanged)
                    // ...
                
                public:
                    explicit MyWrapper(QObject *parent = nullptr);
                    ~MyWrapper();
                
                    int val() const;
                    void setVal(int v);
                    // ...
                
                signals:
                    valChanged(int);
                    // ...
                
                private:
                    MyStruct *m_myStruct;
                };
                
                #endif // MYWRAPPER_H
                

                A QVariant with a POD inside does not expose its members' names to the QML environment. If you want to go with QVariant and have names you need to use QVariantMap. Here is a class "Car" that exposes your MyStruct as a QVariantMap:

                car.h

                #ifndef CAR_H
                #define CAR_H
                
                #include <QObject>
                #include <QVariantMap>
                #include "mystruct.h"
                
                class Car : public QObject
                {
                    Q_OBJECT
                    Q_PROPERTY(QVariantMap myStruct READ getMyStruct WRITE setMyStruct NOTIFY myStructChanged)
                
                public:
                    Car(QObject *parent = nullptr);
                
                    QVariantMap getMyStruct() const;
                    void setMyStruct(QVariantMap myStruct);
                
                signals:
                    void myStructChanged(QVariantMap myStruct);
                
                private:
                    MyStruct m_myStruct;
                };
                
                #endif // CAR_H
                

                car.cpp

                #include "car.h"
                #include "myadapter.h"
                
                Car::Car(QObject *parent)
                    : QObject(parent)
                {
                }
                
                QVariantMap Car::getMyStruct() const
                {
                    return myStructToQVariantMap(m_myStruct);
                }
                
                void Car::setMyStruct(QVariantMap myStruct)
                {
                    MyStruct newValue = myStructFromQVariantMap(myStruct);
                    if (myStructEqual(m_myStruct, newValue))
                        return;
                    m_myStruct = newValue;
                    emit myStructChanged(myStruct);
                }
                

                It relies on some helper functions:
                myadapter.h

                #ifndef MYADAPTER_H
                #define MYADAPTER_H
                
                #include "mystruct.h"
                #include <QVariantMap>
                
                QVariantMap myStructToQVariantMap(MyStruct const &myStruct);
                MyStruct myStructFromQVariantMap(QVariantMap const &vm);
                bool myStructEqual(MyStruct const &myStruct1, MyStruct const &myStruct2);
                
                #endif // MYADAPTER_H
                

                myadapter.cpp

                #include "myadapter.h"
                
                QVariantMap myStructToQVariantMap(const MyStruct &myStruct)
                {
                    QVariantMap res;
                    res.insert("val", myStruct.val);
                    res.insert("name1", myStruct.name1);
                    res.insert("name2", myStruct.name2);
                    res.insert("name3", myStruct.name3);
                    res.insert("name4", myStruct.name4);
                    return res;
                }
                
                MyStruct myStructFromQVariantMap(const QVariantMap &vm)
                {
                    MyStruct res;
                    res.val = vm.value("val").toInt();
                    res.name1 = vm.value("name1").toString();
                    res.name2 = vm.value("name2").toString();
                    res.name3 = vm.value("name3").toString();
                    res.name4 = vm.value("name4").toString();
                    return res;
                }
                
                bool myStructEqual(MyStruct const &myStruct1, MyStruct const &myStruct2)
                {
                    if (myStruct1.val != myStruct2.val) return false;
                    if (myStruct1.name1 != myStruct2.name1) return false;
                    if (myStruct1.name2 != myStruct2.name2) return false;
                    if (myStruct1.name3 != myStruct2.name3) return false;
                    if (myStruct1.name4 != myStruct2.name4) return false;
                    return true;
                }
                

                As you can see, this QVariantMap approach is pretty cumbersome and obviously involves a lot of copying. But at least you can now access "the members" by their names in QML and you get the notifications when the MyStruct object changes.

                    Forum.Car {
                        id: myCar
                    }
                
                    Row {
                        anchors.centerIn: parent
                        spacing: 20
                
                        Button {
                            text: "click me"
                            onClicked: {
                                var obj = myCar.myStruct // retrieve a copy of the struct
                                obj.val = 42 // set value in the copy
                                myCar.myStruct = obj // replace old struct with the copy
                            }
                        }
                
                        Label {
                            text: myCar.myStruct.val
                        }
                    }
                
                P Offline
                P Offline
                pra7
                wrote on 12 Aug 2017, 18:56 last edited by
                #6

                @Wieland Thanks!!! for your suggestion after lot of reading and searching I got the answer ,Actually we can use structs or any object which is not derived from QObject by using Q_GADGET :

                struct MyStruct {
                    Q_GADGET
                    int m_val;
                    QString m_name1;
                    QString m_name2;
                    QString m_name3;
                    QString m_name4;
                    Q_PROPERTY(int val MEMBER m_val)
                    Q_PROPERTY(QString name1 MEMBER m_name1)
                    Q_PROPERTY(QString name2 MEMBER m_name2)
                    Q_PROPERTY(QString name3 MEMBER m_name3)
                    Q_PROPERTY(QString name4 MEMBER m_name4)
                };
                

                Then in my class i just replaced QVariant as below :

                class MyClass:public QObject
                {
                    Q_OBJECT
                    Q_PROPERTY(MyStruct mystr READ getMyStruct
                                WRITE setMyStruct NOTIFY myStructChanged)
                
                public:
                    explicit MyClass(QObject *parent = nullptr);
                    MyStruct strObj;
                
                     // Edit: changed get function
                     MyStruct getMyStruct() const
                     {
                         return strObj;
                     }
                
                // Edit: Added set function
                     void setMyStruct(myStruct val)
                        {
                            mystr = val;
                            emit myStructChanged();
                        }
                signals:
                void myStructChanged();
                
                }
                

                Now in QML file i can just use classObj.mystr.name1 to access the members and i can just use classObj.mystr.name1 = "abc" to set the values.

                ? S 2 Replies Last reply 12 Aug 2017, 20:30
                4
                • P pra7
                  12 Aug 2017, 18:56

                  @Wieland Thanks!!! for your suggestion after lot of reading and searching I got the answer ,Actually we can use structs or any object which is not derived from QObject by using Q_GADGET :

                  struct MyStruct {
                      Q_GADGET
                      int m_val;
                      QString m_name1;
                      QString m_name2;
                      QString m_name3;
                      QString m_name4;
                      Q_PROPERTY(int val MEMBER m_val)
                      Q_PROPERTY(QString name1 MEMBER m_name1)
                      Q_PROPERTY(QString name2 MEMBER m_name2)
                      Q_PROPERTY(QString name3 MEMBER m_name3)
                      Q_PROPERTY(QString name4 MEMBER m_name4)
                  };
                  

                  Then in my class i just replaced QVariant as below :

                  class MyClass:public QObject
                  {
                      Q_OBJECT
                      Q_PROPERTY(MyStruct mystr READ getMyStruct
                                  WRITE setMyStruct NOTIFY myStructChanged)
                  
                  public:
                      explicit MyClass(QObject *parent = nullptr);
                      MyStruct strObj;
                  
                       // Edit: changed get function
                       MyStruct getMyStruct() const
                       {
                           return strObj;
                       }
                  
                  // Edit: Added set function
                       void setMyStruct(myStruct val)
                          {
                              mystr = val;
                              emit myStructChanged();
                          }
                  signals:
                  void myStructChanged();
                  
                  }
                  

                  Now in QML file i can just use classObj.mystr.name1 to access the members and i can just use classObj.mystr.name1 = "abc" to set the values.

                  ? Offline
                  ? Offline
                  A Former User
                  wrote on 12 Aug 2017, 20:30 last edited by
                  #7

                  @pra7 Yes, that's possible, too. Just note that with that solution, MyStruct won't send notifications when a member changes. This is how basic QML types (e.g. color) are implemented.

                  1 Reply Last reply
                  3
                  • ? Offline
                    ? Offline
                    A Former User
                    wrote on 13 Aug 2017, 00:32 last edited by A Former User
                    #8

                    One more thing, you did this...

                    struct MyStruct {
                        Q_GADGET 
                        int m_val;
                        QString m_name1;
                        QString m_name2;
                        QString m_name3;
                        QString m_name4;
                        Q_PROPERTY(int val MEMBER m_val)
                        Q_PROPERTY(QString name1 MEMBER m_name1)
                        Q_PROPERTY(QString name2 MEMBER m_name2)
                        Q_PROPERTY(QString name3 MEMBER m_name3)
                        Q_PROPERTY(QString name4 MEMBER m_name4)
                    };
                    

                    ... where you put Q_GADGET in the public section. This has the side effect that all the members that come after Q_GADGET are private now. That's because Q_GADGET is a macro that expands to...

                    #define Q_GADGET \
                    public: \
                        static const QMetaObject staticMetaObject; \
                        void qt_check_for_QGADGET_macro(); \
                        typedef void QtGadgetHelper; \
                    private: \
                        QT_WARNING_PUSH \
                        Q_OBJECT_NO_ATTRIBUTES_WARNING \
                        Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
                        QT_WARNING_POP \
                        QT_ANNOTATE_CLASS(qt_qgadget, "") \
                        /*end*/
                    

                    ... , see qobjectdefs.h.

                    So maybe better follow the usual convention to avoid surprises:

                    class MyStruct {
                        Q_GADGET 
                        Q_PROPERTY(int val MEMBER m_val)
                        Q_PROPERTY(QString name1 MEMBER m_name1)
                        Q_PROPERTY(QString name2 MEMBER m_name2)
                        Q_PROPERTY(QString name3 MEMBER m_name3)
                        Q_PROPERTY(QString name4 MEMBER m_name4)
                    public:
                        int m_val;
                        QString m_name1;
                        QString m_name2;
                        QString m_name3;
                        QString m_name4;
                    };
                    
                    P 2 Replies Last reply 13 Aug 2017, 07:15
                    6
                    • ? A Former User
                      13 Aug 2017, 00:32

                      One more thing, you did this...

                      struct MyStruct {
                          Q_GADGET 
                          int m_val;
                          QString m_name1;
                          QString m_name2;
                          QString m_name3;
                          QString m_name4;
                          Q_PROPERTY(int val MEMBER m_val)
                          Q_PROPERTY(QString name1 MEMBER m_name1)
                          Q_PROPERTY(QString name2 MEMBER m_name2)
                          Q_PROPERTY(QString name3 MEMBER m_name3)
                          Q_PROPERTY(QString name4 MEMBER m_name4)
                      };
                      

                      ... where you put Q_GADGET in the public section. This has the side effect that all the members that come after Q_GADGET are private now. That's because Q_GADGET is a macro that expands to...

                      #define Q_GADGET \
                      public: \
                          static const QMetaObject staticMetaObject; \
                          void qt_check_for_QGADGET_macro(); \
                          typedef void QtGadgetHelper; \
                      private: \
                          QT_WARNING_PUSH \
                          Q_OBJECT_NO_ATTRIBUTES_WARNING \
                          Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
                          QT_WARNING_POP \
                          QT_ANNOTATE_CLASS(qt_qgadget, "") \
                          /*end*/
                      

                      ... , see qobjectdefs.h.

                      So maybe better follow the usual convention to avoid surprises:

                      class MyStruct {
                          Q_GADGET 
                          Q_PROPERTY(int val MEMBER m_val)
                          Q_PROPERTY(QString name1 MEMBER m_name1)
                          Q_PROPERTY(QString name2 MEMBER m_name2)
                          Q_PROPERTY(QString name3 MEMBER m_name3)
                          Q_PROPERTY(QString name4 MEMBER m_name4)
                      public:
                          int m_val;
                          QString m_name1;
                          QString m_name2;
                          QString m_name3;
                          QString m_name4;
                      };
                      
                      P Offline
                      P Offline
                      pra7
                      wrote on 13 Aug 2017, 07:15 last edited by
                      #9

                      @Wieland Thanks !! for pointing that .

                      1 Reply Last reply
                      1
                      • ? A Former User
                        13 Aug 2017, 00:32

                        One more thing, you did this...

                        struct MyStruct {
                            Q_GADGET 
                            int m_val;
                            QString m_name1;
                            QString m_name2;
                            QString m_name3;
                            QString m_name4;
                            Q_PROPERTY(int val MEMBER m_val)
                            Q_PROPERTY(QString name1 MEMBER m_name1)
                            Q_PROPERTY(QString name2 MEMBER m_name2)
                            Q_PROPERTY(QString name3 MEMBER m_name3)
                            Q_PROPERTY(QString name4 MEMBER m_name4)
                        };
                        

                        ... where you put Q_GADGET in the public section. This has the side effect that all the members that come after Q_GADGET are private now. That's because Q_GADGET is a macro that expands to...

                        #define Q_GADGET \
                        public: \
                            static const QMetaObject staticMetaObject; \
                            void qt_check_for_QGADGET_macro(); \
                            typedef void QtGadgetHelper; \
                        private: \
                            QT_WARNING_PUSH \
                            Q_OBJECT_NO_ATTRIBUTES_WARNING \
                            Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
                            QT_WARNING_POP \
                            QT_ANNOTATE_CLASS(qt_qgadget, "") \
                            /*end*/
                        

                        ... , see qobjectdefs.h.

                        So maybe better follow the usual convention to avoid surprises:

                        class MyStruct {
                            Q_GADGET 
                            Q_PROPERTY(int val MEMBER m_val)
                            Q_PROPERTY(QString name1 MEMBER m_name1)
                            Q_PROPERTY(QString name2 MEMBER m_name2)
                            Q_PROPERTY(QString name3 MEMBER m_name3)
                            Q_PROPERTY(QString name4 MEMBER m_name4)
                        public:
                            int m_val;
                            QString m_name1;
                            QString m_name2;
                            QString m_name3;
                            QString m_name4;
                        };
                        
                        P Offline
                        P Offline
                        pra7
                        wrote on 14 Aug 2017, 19:29 last edited by
                        #10

                        @Wieland Is there any possibility that I can access structure inside a structure?

                        struct MyStruct {
                        Q_GADGET
                        int m_val;
                        QString m_name1;
                        QString m_name2;
                        QString m_name3;
                        QString m_name4;
                        MyNewStruct m_newStr; //** new Struct includes Q_GADGET macro and member definations. 
                        
                        Q_PROPERTY(int val MEMBER m_val)
                        Q_PROPERTY(QString name1 MEMBER m_name1)
                        Q_PROPERTY(QString name2 MEMBER m_name2)
                        Q_PROPERTY(QString name3 MEMBER m_name3)
                        Q_PROPERTY(QString name4 MEMBER m_name4)
                        
                        Q_PROPERTY(MyNewStruct newStr MEMBER m_newStr) //**Currently getting error 
                        };
                        
                        M 1 Reply Last reply 17 Oct 2017, 14:25
                        0
                        • ? Offline
                          ? Offline
                          A Former User
                          wrote on 15 Aug 2017, 07:59 last edited by
                          #11

                          @pra7 said in Best way to access a cpp structure in QML:

                          //**Currently getting error

                          What error?

                          P P 2 Replies Last reply 15 Aug 2017, 10:44
                          0
                          • ? A Former User
                            15 Aug 2017, 07:59

                            @pra7 said in Best way to access a cpp structure in QML:

                            //**Currently getting error

                            What error?

                            P Offline
                            P Offline
                            Praveen_2017
                            wrote on 15 Aug 2017, 10:44 last edited by
                            #12
                            This post is deleted!
                            1 Reply Last reply
                            0
                            • ? A Former User
                              15 Aug 2017, 07:59

                              @pra7 said in Best way to access a cpp structure in QML:

                              //**Currently getting error

                              What error?

                              P Offline
                              P Offline
                              pra7
                              wrote on 15 Aug 2017, 10:45 last edited by
                              #13

                              @Wieland

                              error: no match for 'operator!=' (operand types are 'myStruct1' and 'myStruct1') if (_t->mynewstr != *reinterpret_cast< myStruct1*>(_v)) {
                              

                              where Mystruct1 is myNewStruct and the error is in MOC ...

                              1 Reply Last reply
                              0
                              • ? Offline
                                ? Offline
                                A Former User
                                wrote on 15 Aug 2017, 10:49 last edited by
                                #14

                                The MOC generates some code for you to implement all the Gadget / Property stuff. Looks like the generated code uses the != operator for MyStruct. So you need to implement that:

                                public:
                                    bool operator==(MyStruct const &other) const;
                                    bool operator!=(MyStruct const &other) const;
                                
                                bool MyStruct::operator==(const MyStruct &other) const
                                {
                                    // compare members 
                                    return true;
                                }
                                
                                bool MyStruct::operator!=(MyStruct const &other) const
                                {
                                    return !(*this == other);
                                }
                                
                                P 1 Reply Last reply 15 Aug 2017, 11:09
                                3
                                • ? A Former User
                                  15 Aug 2017, 10:49

                                  The MOC generates some code for you to implement all the Gadget / Property stuff. Looks like the generated code uses the != operator for MyStruct. So you need to implement that:

                                  public:
                                      bool operator==(MyStruct const &other) const;
                                      bool operator!=(MyStruct const &other) const;
                                  
                                  bool MyStruct::operator==(const MyStruct &other) const
                                  {
                                      // compare members 
                                      return true;
                                  }
                                  
                                  bool MyStruct::operator!=(MyStruct const &other) const
                                  {
                                      return !(*this == other);
                                  }
                                  
                                  P Offline
                                  P Offline
                                  pra7
                                  wrote on 15 Aug 2017, 11:09 last edited by
                                  #15

                                  @Wieland That worked !!! Thanks, How to know that which all operators should be overloaded?

                                  ? 1 Reply Last reply 15 Aug 2017, 11:27
                                  1
                                  • P pra7
                                    15 Aug 2017, 11:09

                                    @Wieland That worked !!! Thanks, How to know that which all operators should be overloaded?

                                    ? Offline
                                    ? Offline
                                    A Former User
                                    wrote on 15 Aug 2017, 11:27 last edited by
                                    #16

                                    @pra7 said in Best way to access a cpp structure in QML:

                                    How to know that which all operators should be overloaded?

                                    You can't really know. But when the compiler complains about a missing operator, just implement it. In this case we didn't really need the == operator, but I'd say it's common practice to implement the != operator using the == operator.

                                    P 1 Reply Last reply 15 Aug 2017, 17:20
                                    3
                                    • ? A Former User
                                      15 Aug 2017, 11:27

                                      @pra7 said in Best way to access a cpp structure in QML:

                                      How to know that which all operators should be overloaded?

                                      You can't really know. But when the compiler complains about a missing operator, just implement it. In this case we didn't really need the == operator, but I'd say it's common practice to implement the != operator using the == operator.

                                      P Offline
                                      P Offline
                                      pra7
                                      wrote on 15 Aug 2017, 17:20 last edited by
                                      #17

                                      @Wieland Thanks for all your suggestions.

                                      1 Reply Last reply
                                      1
                                      • P pra7
                                        14 Aug 2017, 19:29

                                        @Wieland Is there any possibility that I can access structure inside a structure?

                                        struct MyStruct {
                                        Q_GADGET
                                        int m_val;
                                        QString m_name1;
                                        QString m_name2;
                                        QString m_name3;
                                        QString m_name4;
                                        MyNewStruct m_newStr; //** new Struct includes Q_GADGET macro and member definations. 
                                        
                                        Q_PROPERTY(int val MEMBER m_val)
                                        Q_PROPERTY(QString name1 MEMBER m_name1)
                                        Q_PROPERTY(QString name2 MEMBER m_name2)
                                        Q_PROPERTY(QString name3 MEMBER m_name3)
                                        Q_PROPERTY(QString name4 MEMBER m_name4)
                                        
                                        Q_PROPERTY(MyNewStruct newStr MEMBER m_newStr) //**Currently getting error 
                                        };
                                        
                                        M Offline
                                        M Offline
                                        Mammamia
                                        wrote on 17 Oct 2017, 14:25 last edited by
                                        #18

                                        @pra7, @Wieland how can I access a list of Structure inside another Structure.
                                        Eg: From the above example, I need to use

                                        QList<MyNewStructure> m_StructList;
                                        
                                        How is that possible? I have tried,
                                        QList<MyNewStructure> m_StructList;
                                        
                                        Q_PROPERTY(QList<MyNewStruct> newStr MEMBER m_newStr) but didnt help.
                                        
                                        1 Reply Last reply
                                        0
                                        • P pra7
                                          12 Aug 2017, 18:56

                                          @Wieland Thanks!!! for your suggestion after lot of reading and searching I got the answer ,Actually we can use structs or any object which is not derived from QObject by using Q_GADGET :

                                          struct MyStruct {
                                              Q_GADGET
                                              int m_val;
                                              QString m_name1;
                                              QString m_name2;
                                              QString m_name3;
                                              QString m_name4;
                                              Q_PROPERTY(int val MEMBER m_val)
                                              Q_PROPERTY(QString name1 MEMBER m_name1)
                                              Q_PROPERTY(QString name2 MEMBER m_name2)
                                              Q_PROPERTY(QString name3 MEMBER m_name3)
                                              Q_PROPERTY(QString name4 MEMBER m_name4)
                                          };
                                          

                                          Then in my class i just replaced QVariant as below :

                                          class MyClass:public QObject
                                          {
                                              Q_OBJECT
                                              Q_PROPERTY(MyStruct mystr READ getMyStruct
                                                          WRITE setMyStruct NOTIFY myStructChanged)
                                          
                                          public:
                                              explicit MyClass(QObject *parent = nullptr);
                                              MyStruct strObj;
                                          
                                               // Edit: changed get function
                                               MyStruct getMyStruct() const
                                               {
                                                   return strObj;
                                               }
                                          
                                          // Edit: Added set function
                                               void setMyStruct(myStruct val)
                                                  {
                                                      mystr = val;
                                                      emit myStructChanged();
                                                  }
                                          signals:
                                          void myStructChanged();
                                          
                                          }
                                          

                                          Now in QML file i can just use classObj.mystr.name1 to access the members and i can just use classObj.mystr.name1 = "abc" to set the values.

                                          S Offline
                                          S Offline
                                          seyed
                                          wrote on 13 Jun 2021, 18:41 last edited by
                                          #19

                                          @pra7 but it does not sufficient! I had to use Q_DECLARE_METATYPE() and qRegisterMetaType<>() to avoid unknown type error. Did I missed something?

                                          1 Reply Last reply
                                          0
                                          • R Rua3n referenced this topic on 15 Jul 2023, 12:49
                                          • R Rua3n referenced this topic on 15 Jul 2023, 15:02

                                          • Login

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