0
votes

my Qt/QML program uses classes declared in C++ to structure information in QML and pass it as a bundle to C++ functions.

The structs are derived from QObject as required by QML. Example:

class ResultStorageOptionsStruct : public QObject {
    Q_OBJECT

public:
    explicit ResultStorageOptionsStruct(QObject * parent = nullptr) : QObject(parent) {}
    ~ResultStorageOptionsStruct() = default;
    ResultStorageOptionsStruct(const ResultStorageOptionsStruct& blob) {
    }

    bool folderValid;
    QString folderURL;

    Q_PROPERTY(bool folderValid MEMBER folderValid)
    Q_PROPERTY(QString folderURL MEMBER folderURL)


};

Q_DECLARE_METATYPE(ResultStorageOptionsStruct);

Using this method, passing information from QML to C++ works without a problem, but handling of that information on the C++ side is very bothersome due to the fact that you cannot copy/assign the class(derived of QObject).

I would like to copy/serialize/deserialize my classes for easy handling once they are on the c++ side. I do not need the features QObject gives me once we are on the c++ side as those classes are just containers for the information.

Is there some kind of trick or data structure to make this happen?

1
You can use Q_GADGET for structsAmfasis
That would work, but has the downside that the struct can not be instantiate in QML itself (as far as I know). This would make bindings to UI elements impossible, which is a feature I would be loathe to miss.ghst
I guess you don't want to make a "creator" function (like Qt.point(...)). Maybe a cast operator is an option? This does duplicate the structs but sounds like you might like itAmfasis

1 Answers

0
votes

You can serialize and deserialize to a QIODevice, but this would be for file storage. To me, it sounds more like you want a QObject wrapper around a plain C++ object.

I would create a C++ class with the data that you need. Then create a QObject derived class with a (weak) reference to the C++ class that you wrap the original class in when passing it to QML.

class MyData
{
public:
    int x;
};

class MyDataWrapped : QObject
{
    Q_OBJECT
public:
    MyDataWrapped(MyData *obj) : md(obj) {}

    void x() const { return md->x; }

    Q_PROPERTY(...)

private:
    MyData *md; // You might want to make this a weak pointer
};

What is potentially tricky is if the data is changed from QML or C++, while the wrapper lives. How can QML tell that a property is changed if you change it from C++, and the other way around. Here, QObject and signals and slots come in handy. However, if the data is read-only while shared, I guess you should be fine.