C++ object assignment between two context property in QML through Q_Invokable
-
Hi,
I'm trying to implement a simple edit dialog in QML with (almost) pure C++ backend. The class to be edited has some displayable members and also others i.e. pointers, vectors, etc. Because of this and to keep (almost) all the logic on the C++ side, I want to have a temp instance while editing the properties in the QML window, so that I can either discard them or save them to my class instance represented there.
One way would be to use simple properties on the QML side and assign to them the first the original values on open and the new values upon save or do nothing on discard, but that way I would have to check everything on the QML side probably in javascript and part of the logic would be transfared to the QML side, and If I have many members I would also have that my QML property and two times the assigments.
My solution to avoid the above mentioned things is that I not just expose the two object to QML but also register their class as a QML type and then I can call a C++ clone function, as I was unable to call the overloaded assignment operator (use a single AInstance = BInstance in QML) while it would be convenient and cool.
I also have to bind these members to their TextField.text one-by-one.Below you can find my MCP example. Is there a better, more sophisticated way to implement this?
C++
A.hClass A; typedef struct { QString prefix; QString firstname; QString lastname; std::vector<A*> As; } StructVar; class A : public QObject { Q_OBJECT Q_PROPERTY( QString a1 READ geta1 WRITE seta1 NOTIFY a3Changed ) Q_PROPERTY( QString a2 READ geta2 WRITE seta2 NOTIFY a2Changed ) Q_PROPERTY( QString a3 READ geta3 WRITE seta3 NOTIFY a3Changed ) Q_PROPERTY( QString var1 READ getvar1 WRITE setvar1 NOTIFY var1Changed ) signals: void a1Changed(); void a2Changed(); void a3Changed(); void var1Changed(); public: A( QObject *parent = 0 ); ~A(); A( const A& a ); A& operator=( const A& a ); Q_INVOKABLE void copy( QObject* a ); ... setters, getters, other functions ... private: QSrtring a1; QSrtring a2; QSrtring a3; StructVar sv1; SomeOtherClass B*; } /* not copying here almost empty/trivial/not relevant A.cpp content */
main.cpp
#include <QApplication> #include <QQmlApplicationEngine> #include <QtQml> #include <QQmlContext> #include "a.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); A currentA; currentA.seta1( "Text a1" ); currentA.seta2( "Text a2" ); A editA = currentA; qmlRegisterType<A>("My", 1, 0, "A"); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty( "currentA", ¤tA ); engine.rootContext()->setContextProperty( "editA", &editA ); engine.load(QUrl(QStringLiteral("qrc:///main.qml"))); return app.exec(); }
QML
import QtQuick 2.2 import QtQuick.Controls 1.2 ApplicationWindow { id: appWindow visible: true height: 640 width: 1140 visibility: "Maximized" Rectangle { id: menuContainer x: 100 y: 100 width: 200 height: 200 Rectangle { id: saveButton x: 10 y: 10 width: 40 height: 40 color: "blue" MouseArea { anchors.fill: parent onClicked: { currentA.copy( editA ) } } } Rectangle { id: cancelButton x: 60 y: 10 width: 40 height: 40 color: "red" MouseArea { anchors.fill: parent onClicked: { // do nothing in the example } } } Item { id: textInputContainer width: 200 height: 100 anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.bottom anchors.bottomMargin: 20 Binding { target: editA property: "a1" value: a1Text.text } TextField { id: a1Text text: editA.name placeholderText: "type..." height: 50 width: 150 } } } }
Thanks for looking it through ; )