Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Allocate memory for a Q_GADGET inside another Q_GADGET



  • Hello everyone. Let's say I have a void *pointer to a Q_GADGET, and inside this Q_GADGET I have a pointer to another Q_GADGET. All of them are registered in the meta-object system. Is it possible, using QMetaObjects and the original void* pointer to allocate memory to this other Q_GADGET? Example code follows:

    #ifndef EXAMPLE_H
    #define EXAMPLE_H
    #include <QObject>
    
    //Nested Q_GADGET
    struct P2D {
        Q_GADGET
        Q_PROPERTY(P2D p2d READ getP2D )
        Q_PROPERTY(float m_x READ getX WRITE setX)
        Q_PROPERTY(float m_y READ getY WRITE setY)
    
        P2D getP2D() {return *this;}
        float getX() {return this->m_x;}
        void setX(float x) {this->m_x = x;}
        float getY() {return this->m_y;}
        void setY(float y) {this->m_y = y;}
    
    
    public:
        float m_x;
        float m_y;
    }; Q_DECLARE_METATYPE(P2D)
    
    //Main Q_GADGET
    struct Player {
        Q_GADGET
    
    public:
        enum class CarType {
            NO_CAR = 0,
            SLOW_CAR,
            FAST_CAR,
            HYPER_CAR
        }; Q_ENUM(CarType)
    
        Q_PROPERTY(Player player READ getPlayer)
        Q_PROPERTY(int m_speed READ getSpeed WRITE setSpeed)
        Q_PROPERTY(CarType m_carType READ getCarType)
        Q_PROPERTY(P2D* p2d READ getP2D )
    
    
        Player getPlayer() { return *this;}
        int getSpeed() {return this->m_speed;}
        void setSpeed(int speed) {this->m_speed = speed;}
        CarType getCarType() { return m_carType;}
        P2D* getP2D() {return this->p2d;}
    
    
    public:
        CarType m_carType;
        int m_speed;
        P2D *p2d;
    
    }; Q_DECLARE_METATYPE(Player)
    
    #endif
    

    Main:

    #include <QCoreApplication>
    #include <iostream>
    #include <QMetaObject>
    #include "example.h"
    #include <QDebug>
    #include <QMetaProperty>
    #include <QPointer>
    
    
    void gadgetExplorer(void *ptr, const char* s)
    {
        //Receives Player and access its meta-object
        int typeId = QMetaType::type(s);
        const QMetaObject *mo = QMetaType::metaObjectForType(typeId);
    
        qInfo() << "Q_GADGET: " << mo->className();
        //QProperty 3 refers to Q_GADGET P2D
        QMetaProperty mp = mo->property(3);
        qInfo() << "Q_PROPERTY: " << mp.name();
        
        //With this given info, is it possible to allocate memory to p2d?
        
    }
    
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        qRegisterMetaType<Player>();
        qRegisterMetaType<P2D>();
    
        Player p1;
        p1.setSpeed(30);
    
        gadgetExplorer(&p1, "Player");
    
    
        return a.exec();
    }
    

    I think this is doable creating a method to allocate memory inside the Player Q_GADGET. However, is there other way to do it?

    Thanks for your time.



  • One more example:

    #include <QCoreApplication>
    #include <iostream>
    #include <QMetaObject>
    #include "example.h"
    #include <QDebug>
    #include <QMetaProperty>
    #include <QPointer>
    
    
    void gadgetExplorer(void *ptr, const char* s)
    {
        //Receives Player and access its meta-object
        int typeId = QMetaType::type(s);
        const QMetaObject *mo = QMetaType::metaObjectForType(typeId);    
        qInfo() << "Q_GADGET: " << mo->className();
        QMetaProperty mp;
        for(int i = 1; i < mo->propertyCount(); i++)
        {
            mp = mo->property(i);
            qInfo() << "Q_PROPERTY: " << mp.typeName() << "Value: " << mp.readOnGadget(ptr);
            if(int(mp.type()) == 1024)
                gadgetExplorer(ptr, mp.typeName());
        }
    
    }
    
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        qRegisterMetaType<Player>();
        qRegisterMetaType<P2D>();
        qRegisterMetaType<P2D*>();
    
        Player p1;
        p1.setSpeed(30);
        p1.p2d = new P2D();
        p1.p2d->setX(10.0);
        p1.p2d->setY(25.0);
        gadgetExplorer(&p1, "Player");
    
    
        return a.exec();
    }
    

    gadgetExplorer() works fine for the first Q_GADGET, but for the second one the read property doesn't work. Is it possible to access the second's Q_GADGET pointer?