Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Auto Binding 2 ways with Cpp Dynamic Property
QtWS25 Last Chance

Auto Binding 2 ways with Cpp Dynamic Property

Scheduled Pinned Locked Moved Unsolved General and Desktop
7 Posts 2 Posters 2.7k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • DongD Offline
    DongD Offline
    Dong
    wrote on last edited by Dong
    #1

    Hi everyone !

    I know how Qt binding work, but it not work for Dynamic Property.
    Then I'm trying to implement 2 ways binding support Dynamic Property use simple function.

    The ideal is use eventFilter on DynamicPropertyChangedEvent to get notify when DynamicProperty changed then update destination property. (This is done as the code below)

    Q_INVOKABLE void binding(QObject* qmlObj, QString qmlProp, QObject* cppObj, QString cppProp);
    

    My class DynamicObject work as Context Object for an qml component

    class DynamicObject : public QObject
    {
        Q_OBJECT
    private:
        QMap<QString, QVariant> bindingList;
        QMap<QString, QStringList> cppToQml;
    
    protected:
        bool eventFilter(QObject *obj, QEvent *event);
    
    public:
        Q_INVOKABLE void binding(QObject* qmlObj, QString qmlProp, QObject* cppObj, QString cppProp);
        Q_INVOKABLE QObject* thisContextObject();
    }
    
    void DynamicObject::autoBinding(QObject* qmlObj, QString qmlProp, QObject* cppObj, QString cppProp)
    {
        //Set value from source (cpp) to qml
        qmlObj->setProperty(qPrintable(qmlProp), cppObj->property(qPrintable(cppProp)));
        // ==> Setup auto binding from source (cpp) to destination (qml)
        //Generate Unique Key for this binding
        QString uniqueKey = QString("%1%2%3%4").arg((size_t)qmlObj).arg(qmlProp).arg(size_t(cppObj)).arg(cppProp);
        qDebug() << "Binding Key: " + uniqueKey;
        if (!bindingList.contains(uniqueKey))
        {
            //Add Binding Info into Binding List
            BindingInfo* bInfo = new BindingInfo(qmlObj, qmlProp, cppObj, cppProp);
            QVariant val = QVariant::fromValue(bInfo);
            bindingList.insert(uniqueKey, val);
            //Add Binding Map for Cpp Property to Qml Property
            QStringList qmlPropList;
            if (cppToQml.contains(cppProp))
            {
                qmlPropList = cppToQml.value(cppProp);
            }
            qmlPropList.append(uniqueKey);
            cppToQml[cppProp] = qmlPropList;
        }
    
        // ==> Setup auto binding from destination (qml) to source (cpp)
        QVariant qmlVal = qmlObj->property(qPrintable(qmlProp));
        qDebug() << qmlVal;
        if (qmlProp == "text") {
            //Try to connect qml signal textChanged with a lot in this object
            QObject::connect(qmlObj, SIGNAL(textChanged()), this, onTextChanged);
            //Try to forward qml object's events use event filter
            qmlObj->installEventFilter(this);
        }
    }
    
    bool DynamicObject::eventFilter(QObject *obj, QEvent *event)
    {
        qDebug() << "Event Captured: " << event->type() << " on Object (" << obj << ")";
        if (event->type() == QEvent::KeyPress)
        {
            QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
            qDebug("Key pressed: %d", keyEvent->key());
        }
        if (event->type() == QEvent::KeyRelease)
        {
            QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
            qDebug("Key released: %d", keyEvent->key());
        }
        if (event->type() == QEvent::DynamicPropertyChange) {
            QDynamicPropertyChangeEvent *propEvent = static_cast<QDynamicPropertyChangeEvent *>(event);
            QString propName = propEvent->propertyName();
            qDebug() << (size_t)obj << ":" << propName;
        }
    }
    

    But it more difficult when I try to get notity when Qml Property changed

    I'm tried eventFilter, but for each controls, I have to handle correct event (To much switch case)

    Then I try to connect <property>Changed SIGNAL with corresponded slot (ex: textChanged => onTextChanged).
    I got the pointer to qml Object & property name which I need to "listen" on, But I don't know how to cast QObject to Qml Type (for example: QObject to TextField)

    Any one have any ideal or solution for this?! Please help !!!

    1 Reply Last reply
    0
    • DongD Offline
      DongD Offline
      Dong
      wrote on last edited by
      #2

      I'm really need help !!!

      Any Qt core Development team, Qt Professional or Qt Moderator here can point out a direction for me?
      Or any suggestion please !!!

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,

        Why do you need a big switch case ?

        Since these are all dynamic properties, what do you need to cast the QObjects ?

        If you are in such need for help, then you should maybe consider getting a commercial license which include support or hire someone to help you on this.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        DongD 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          Why do you need a big switch case ?

          Since these are all dynamic properties, what do you need to cast the QObjects ?

          If you are in such need for help, then you should maybe consider getting a commercial license which include support or hire someone to help you on this.

          DongD Offline
          DongD Offline
          Dong
          wrote on last edited by Dong
          #4

          Dear @SGaist

          "Why do you need a big switch case ?"

          • As you can see in the DynamicObject::eventFilter. It already check if DynamicPropertyChanged Event fired or not.
            I can get KeyPress, KeyRelease, but can't get DynamicPropertyChange. So, if I handle KeyRelease for TextField or SelectionChanged for ComboBox... etc... it will be a lot of case to switch (or if ... then)

          "What do you need to cast the QObjects"

          In Qml file, I'm setup autoBinding like this

          Component.onCompleted: {
                  viewModel = thisContextObject();
                  autoBinding(advSearch, "model", viewModel, "FilterList")
                  autoBinding(txtName, "model", viewModel, "CompanyName")
              }
          

          So I'm try to connect textChange signal of TextField (or other Property of other Qml Object) to related slot (in cpp autoBinding function). That why I need to cast QObject to TextField or something else.

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            There's something I'm not sure I'm following properly. Can you explain a use case for dynamic properties in QML ?

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            DongD 1 Reply Last reply
            0
            • SGaistS SGaist

              There's something I'm not sure I'm following properly. Can you explain a use case for dynamic properties in QML ?

              DongD Offline
              DongD Offline
              Dong
              wrote on last edited by
              #6

              @SGaist
              Sorry for late responded. (I don't know why I can't get notification when mine topic got answer or comment.

              Let take an sample Code for the use case

              //cpp
              QQmlContext* ctx = engine.rootContext();
                  ctx->setContextObject(mainViewModel);
              
              //QML
              TextField{
                 id : txtName
              }
              
              Component.onCompleted: {
                 viewModel = thisContextObject();
                 autoBinding(txtName, "text", viewModel, "SelectedItem.Name");
              }
              
              

              As you can see in the Code above.
              I setup an auto Binding between txtName.text <=> "SelectedItem.Name" ("SelectedItem" & "Name" are Dynamic Property in mainViewModel)
              in Qt way (With normal Property declared by Q_PROPERTY), I have to setup a binding for each way like this

              TextField{
                 id : txtName
                 text : SelectedItem.Name
              }
              
              Binding {
                 target: SelectedItem
                 property: "Name"
                 value: txtName.text
              }
              

              What I want is "How to implement Qml to Cpp binding like what Binding Element does.
              if I can have a look at Binding element source code, may be I can figure it out.

              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                You can look at the code without any problem. Just download the sources, either through the maintenance tool or clone it with git.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved