Casting a custom class to QVariant



  • I'm trying to provide a way to convert a custom (QObject derived) class to a QVariant using a custom method. The main purpose of this would be outputting data about the class into a QJsonDocument.

    I tried defining a cast operator as such:

    operator QVariant() const
    {
        return QVariant(this->statusMap()); // statusMap() method returns a QVariantMap with relevant data
    }
    

    But I'm getting an error of the form:

    error: ‘QVariant::QVariant(void*)’ is private within this context
        QVariant status = (QVariant)m_server->getExtension(extensionName);
                                                                        ^
    

    I have also declared the class as a QMetaType using Q_DECLARE_METATYPE but the result is the same.

    Is there even a way to do this? I cannot find a method such as QObject::toVariant or similar that I could override anywhere in the docs, so if there is such a thing I don't see it.

    Thanks.


  • Moderators

    @Onyx said in Casting a custom class to QVariant:

    QVariant(this->statusMap())

    Use QVariant::fromValue<>() instead.



  • @sierdzio Ah, that's a static, makes sense. One part I still don't understand is that I get use of deleted function... for constructors now. Poking around a bit, is this because I declared the class using Q_DECLARE_METATYPE but don't have my own copy constructors (what I found online seems to suggest copy constructor for QObject is private?).

    Also, I should note that this class inherits from another class, and they are both inheriting from QObject, I assume this might be causing problems as well? So basically currently it's:

    class Class1 : public QObject {
        Q_OBJECT
    ...
    }
    Q_DECLARE_METATYPE(Class1)
    
    class Class2 : public Class1 {
        Q_OBJECT
    ...
    }
    Q_DECLARE_METATYPE(Class2)
    

    Should I omit the Q_OBJECT and/or Q_DECLARE_METATYPE macros from Class2 or do I need them in both places? Sorry for all the extra questions, but I can't seem to find specific examples involving inheritance anywhere...


  • Moderators

    • Every QObject should have the Q_OBJECT macro in the header file. No need to change that
    • Multiple inheritance from 2 QObject classes is not allowed in Qt
    • Copying QObjects is not allowed in Qt and does not make sense. The copy constructor is private for a reason! You can copy the pointer (memory address), but not the object. If you really want to "copy" a QObject, you need to create a new one and make sure it is properly parented
    • I totally fail to see what you're trying to achieve ;-) Why you try to return QVariantMap in original post but start talking about QObjects in the last comment? How are the objects related to the variant map?


  • @sierdzio said in Casting a custom class to QVariant:

    Every QObject should have the Q_OBJECT macro in the header file. No need to change that

    Makes sense, I was pretty sure it was the case but...

    @sierdzio said in Casting a custom class to QVariant:

    Multiple inheritance from 2 QObject classes is not allowed in Qt

    I don't have multiple inheritance though. Class1 inherits QObject, Class2 inherits Class1. Unless my understanding of terminology is wrong, that shouldn't be a problem (and was not up to this point).

    @sierdzio said in Casting a custom class to QVariant:

    Copying QObjects is not allowed in Qt and does not make sense. The copy constructor is private for a reason! You can copy the pointer (memory address), but not the object. If you really want to "copy" a QObject, you need to create a new one and make sure it is properly parented

    Again, makes sense. I think it was just me googling and finding different threads online that led me to a wrong conclusion on what I need to do, probably doesn't have anything to do with my specific issue.

    @sierdzio said in Casting a custom class to QVariant:

    I totally fail to see what you're trying to achieve ;-) Why you try to return QVariantMap in original post but start talking about QObjects in the last comment? How are the objects related to the variant map?

    Yeah, I explained that poorly... Taking the same hierarchy from before, I'm trying to provide a way to cast Class2 to QVariant. Currently, it provides a method called statusMap that returns a QVariantMap with the info I need.

    So, basically, I want this:

    QVariant data = (QVariant)Class2;
    

    Unless I misunderstood, this should allow me to do something like:

    QJsonDocument data = QJsonDocument::fromVariant(Class2);
    

    Is this wrong?

    The reason I asked about Q_DECLARE_METATYPE stuff is that, from my understanding of the docs, if I want that to work my class needs to be registered in Qt's metatype system. But trying to do that results in compile errors, so I'm trying to figure out what I'm doing wrong.

    Maybe my whole approach is wrong, or maybe it's not even doable... On reflection, I should've probably led with that.

    Thanks for all the clarifications so far either way :)


  • Moderators

    @Onyx said in Casting a custom class to QVariant:

    I don't have multiple inheritance though. Class1 inherits QObject, Class2 inherits Class1. Unless my understanding of terminology is wrong, that shouldn't be a problem (and was not up to this point).

    Yes that is OK.

    Taking the same hierarchy from before, I'm trying to provide a way to cast Class2 to QVariant. Currently, it provides a method called statusMap that returns a QVariantMap with the info I need.
    So, basically, I want this:
    QVariant data = (QVariant)Class2;
    Unless I misunderstood, this should allow me to do something like:
    QJsonDocument data = QJsonDocument::fromVariant(Class2);

    If you want to serialize to JSON, I think going through a variant map is only needlessly adding complexity here. Consider serializing to JSON directly in your class and returning a QJsonObject or QJsonArray. Example: https://github.com/sierdzio/stimeline/blob/master/src/scalendar.h#L38

    As for making an unified serialization framework, see how QDataStream has overloads added to many Qt classes - this is probably the best way to do it (in your case, the overloads will be for QJson* classes, of course).

    The reason I asked about Q_DECLARE_METATYPE stuff is that, from my understanding of the docs, if I want that to work my class needs to be registered in Qt's metatype system

    Pointers to QObjects are declared to metatype system automatically.



  • @sierdzio said in Casting a custom class to QVariant:

    If you want to serialize to JSON, I think going through a variant map is only needlessly adding complexity here. Consider serializing to JSON directly in your class and returning a QJsonObject or QJsonArray. Example: https://github.com/sierdzio/stimeline/blob/master/src/scalendar.h#L38

    That might indeed be the simplest solution. I'll have to check if I even need any serialization past going directly to JSON (it's not a fresh project, I'm refactoring an existing one), but it sounds like a good idea in any case.

    @sierdzio said in Casting a custom class to QVariant:

    As for making an unified serialization framework, see how QDataStream has overloads added to many Qt classes

    Ah, that's a place I didn't think to look into. I hoped it would just be a case of adding a toVariant method to my classes or similar initially, but since I couldn't find anything like that I went the casting route. Will take a peek in there.

    @sierdzio said in Casting a custom class to QVariant:

    Pointers to QObjects are declared to metatype system automatically.

    Oh, that's nice. Good to know.

    Thanks for all the pointers, I'll mark this as solved since it seems I took the wrong route anyway.


Log in to reply
 

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