Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to create Q_PROPERTY 'alias' in C++.



  • In QML, it is simple to create an alias of a property:

    property int number: 1
    property alias numeral: number
    

    However, I cannot find a method of doing the same thing from C++ that matches the subtleties of the QML engine.

    The most obvious thing that comes to mind is:

    Q_PROPERTY(int number READ GetNumber WRITE SetNumber NOTIFY NumberChanged)
    Q_PROPERTY(int numeral READ GetNumber WRITE SetNumber NOTIFY NumberChanged)
    

    or perhaps:

    Q_PROPERTY(int number MEMBER _number)
    Q_PROPERTY(int numeral MEMBER _number)
    

    However the problem arises that a new binding or constant value assigned to the 'numeral' property will not break an older binding assigned to the 'number' property.

    An example:

    number: myNumber
    
    ...
    
    numeral: 3
    
    /* 'numeral' now becomes 3, until 'myNumber' changes,
        at which point the 'myNumber' binding takes over.
        This wouldn't happen with a qml property alias.*/
    

    Looking in the documentation, I cannot find a simple (or, for that matter, complicated) method of breaking property bindings from C++.

    Any ideas?


  • Qt Champions 2017

    @LScott said in How to create Q_PROPERTY 'alias' in C++.:

    However, I cannot find a method of doing the same thing from C++ that matches the subtleties of the QML engine.

    I don't believe there's any. As far as I understand the two properties are distinct, even if they use the same getter, setter and notifier. Why don't you use what QML provides already?

    Looking in the documentation, I cannot find a simple (or, for that matter, complicated) method of breaking property bindings from C++.

    There's no "property binding" as such here, what you have is two properties that share the same piece of data, which isn't exactly the same as having an alias. They just overwrite each other depending on who was last written.



  • There's no "property binding" as such here

    Right, no binding on the C++ side, but the QML/javascript generates a binding with the line:

    number: myNumber
    

    assuming that 'myNumber' is a notifiable property (or replaced with an expression), right?

    I suppose there is no way for the C++ to know about the binding, it's just getting the setter called as far as it's concerned? I was hoping there might be some way to break the javascript binding from C++ with QMetaProperty or something.

    Why don't you use what QML provides already?

    I certainly could, but it seems messy to keep different property definitions in different places, I'd rather avoid it.

    Thanks for the response :)


  • Qt Champions 2017

    @LScott said in How to create Q_PROPERTY 'alias' in C++.:

    I suppose there is no way for the C++ to know about the binding

    Not as far as I know.


  • Moderators

    @LScott
    you could simply emit the changed signal multiple times after each other.

    The QML engine should detect a "binding loop" and break the binding itself.
    Hacky, but it should work.



  • Finally came back to this problem (testers wouldn't stop bugging me about it).

    Found a potential solution!

    QQmlProperty::write(QObject*, const QString& name)

    It doesn't seem to be documented, but calling this function seems to break any existing QML bindings on the specified property. So I just create a separate WRITE function for my aliased property:

    Q_PROPERTY(int number READ GetNumber WRITE SetNumber NOTIFY NumberChanged)
    Q_PROPERTY(int numeral READ GetNumber WRITE OverwriteNumber NOTIFY NumberChanged)
    
    void OverwriteNumber(const int value)
    {
        QQmlProperty p(this, "number");
    
        p.write(value);
    }
    

    Seems to work for me.
    Basically gets around the problem of C++ being unaware of the binding by writing to the property through the QML context, I guess. It's probably much slower than calling the setter directly, so probably not ideal for properties that change frequently, but it will suffice for my purposes.


Log in to reply