[SOLVED] Qt Meta-Obect System: QObject::setProperty() with QVariant user defined types - fails



  • Hello all,

    Here is my case: I have a class, MyClass, that has references to other objects (composition). I want to dynamically initialize an instance of this class using @QObject::setProperty(const char * fieldName, QVariant &value;)@
    The properties are pointers to objects that inherit QObjects. I have those pointers stored in a QObject* array (let's call it objVals) and I also have the field names in an array fieldNames.
    To do this, I create a QVariant (let's call it value) for each QObject* in the array, then call setProperty() with fieldNames[i] and value.
    For example

    @MyClass mc;
    for (int i = 0; i < numObjFields; ++i) {
    QVariant value;
    value.setValue(objVals[i]);
    mc.setProperty(fieldNames[i],value);
    }@

    if the properties' real type is not QObject*, but a derived class, setProperty fails.
    Now if I cast objVals[i] to it's true type, it succeeds (assuming I know the type at compile time of course)

    @MyClass mc;
    for (int i = 0; i < numObjFields; ++i) {
    QVariant value;
    value.setValue((trueType*)objVals[i]);
    mc.setProperty(fieldNames[i],value);
    }@

    I have declared all the types with Q_DECLARE_METATYPE, Q_OBJECT and the properties with Q_PROPERTY with the proper getters and setters.

    Why is this problem happennig? Is there a way to overcome it? Your help will be very much appreciated.

    Thanks!



  • Do do you register the meta type with the call qRegisterMetaType("your custom meta type")?



  • Yes I tried with qRegisterMetaType, it didn't work either.



  • What's the (apparent) type of objVals?

    [quote]I have declared all the types with Q_DECLARE_METATYPE[/quote]

    Which types are you talking about exactly?

    [quote author="steno" date="1311784107"]Do do you register the meta type with the call qRegisterMetaType("your custom meta type")?[/quote]

    Not needed.



  • [quote author="steno" date="1311784107"]Do do you register the meta type with the call qRegisterMetaType("your custom meta type")?[/quote]

    Not needed.[/quote]

    Doh, true. Only needed for queued signals/slots and the property system.



  • For the sake of trying to pinpoint what happens: if you try to set a property by directly entering its name instead of retreiving it from your array, and then calling setProperty on the QObject* pointer, does that work?

    I mean: what happens if you use:
    @
    myQObjectPtr->setProperty('ThePropertyOfTheSubclass', QVariant("a value"));
    @



  • bq. peppe wrote:
    What’s the (apparent) type of objVals?

    The type of objVals is QObject** (array of QObject pointers).

    bq. peppe wrote:
    Which types are you talking about exactly?

    I have created my own classes, that inherit QObject. I'm registering the pointers to those classes.
    For example
    @class Class1 : public QObject {
    Q_OBJECT

    public:
    Class1() {
    }

    virtual ~Class1() {
    }
    

    };

    Q_DECLARE_METATYPE(Class1*)@

    Then I have another class Class2 containing a reference to Class1
    @class MyClass : public QObject {
    Q_OBJECT
    Q_PROPERTY (Class1* cl READ getCl WRITE setCl)
    Class1* cl;

    public:
    MyClass() {
    cl = NULL;
    }

    Class1* getCl() const {
        return cl;
    }
    void setCl(Class1 *obj) {
        cl = obj;
    }
    

    };@

    bq. Andre wrote:
    I mean: what happens if you use:
    @myQObjectPtr->setProperty('ThePropertyOfTheSubclass', QVariant("a value"));@

    It doesn't work either

    Here is a sample code that you can compile and run to troubleshoot the problem (Qt console application)

    main.cpp:
    @#include <QtCore/QCoreApplication>

    #include <iostream>
    #include "MyClasses.h"

    using namespace std;

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    MyClass mc;
    QObject* c = new Class1;
    
    QVariant value;
    value.setValue(c);
    
    if (mc.setProperty("cl",value) == false)
        cout<<"setProperty failed"<<endl;
    
    return a.exec&#40;&#41;;
    

    }
    @

    header file (MyClasses.h)
    @#ifndef MYCLASSES_H
    #define MYCLASSES_H

    #include <QObject>
    #include <QVariant>
    #include <QMetaObject>

    class Class1: public QObject {
    Q_OBJECT
    public:
    virtual ~Class1() {}
    };

    Q_DECLARE_METATYPE(Class1*)

    class MyClass: public QObject {
    Q_OBJECT
    Q_PROPERTY (Class1* cl READ getCl WRITE setCl)
    Class1* cl;

    public:
    MyClass() {
    cl = NULL;
    }

    Class1* getCl() const {
        return cl;
    }
    void setCl(Class1 *obj) {
        cl = obj;
    }
    
    virtual ~MyClass() {}
    

    };

    #endif // MYCLASSES_H
    @



  • No, that code is wrong -- the type of the QVariant is QObject*, which does not match the type of the property (Class1*). Therefore the setProperty will fail. Create your QVariant from a Class1* value and it will work.

    Yes, it's a kind of limitation of the whole QMetaType stuff...



  • Ok that's what I assumed, but I hoped there was something else.

    Thank you all for your help!



  • Oh, one last thing: why can't the QVariant of type QObject* be converted to a Class1* (using QVariant::convert(Type t))?

    Thanks



  • [quote author="genC" date="1311851619"]Oh, one last thing: why can't the QVariant of type QObject* be converted to a Class1* (using QVariant::convert(Type t))?[/quote]Because QVariant::type() returns 2 different type ids for Class1* and QObject*, and you can see in the source code of QVariant::canConvert(Type) that if the two type ids are different the functions returns false except for a few hard-coded conversions between Qt builtin types or between numeric types.

    But if it's really a composition and not an aggregation, you could just add the QObjects as children, and give them names (QObject::setObjectName) to find them later with yourContainerObject->findChild<Class1*>("yourObjectName");.



  • I see.
    Well in fact, I'm using both composition and aggregation, so QObjects as children might not really work for me...

    Thank you


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.