2

There is a question about how to bind from a singleton object property to a QML property. But what about if we like to bind a QML property to a singleton object.

Here is the singleton class definition,

class Singleton : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName)
public:
    explicit Singleton(QObject *parent = nullptr);
    QString name() const;
    void setName(const QString &name);
private:
    QString m_name;
};

And on QML

property string qmlName: textField.text
TextField {
    id: textField
}

I would like to bind textField.text to Singleton object name property. It is possible to bind it with a workaround like,

onQmlNameChanged: {
    Singleton.name = qmlName;
}

But that won't be an Property Binding actually, because it is an assignment.

So is there a more nature binding way to a singleton object property?

Community
  • 1
  • 1
cavitsinadogru
  • 940
  • 2
  • 10
  • 17
  • 1
    There is actually no need for qmlName property. Just `onEditingFinished: { Singleton.name = qmlName }` of `TextField` can do the job. – rightaway717 Mar 02 '16 at 19:32
  • Yes there is no need for qmlName, also we can write code on the textField's text changed signal but this will not be a property binding aswell. – cavitsinadogru Mar 03 '16 at 16:25
  • As for textChanged signal you might not want to use it except for "live search", otherwise why send signals for every letter changed if you need the whole word. As for property binding, @ddriver explained it pretty much, so in this case it is just about you liking the word "binding". If it does the same under the hood, then what is the difference? – rightaway717 Mar 04 '16 at 04:59
  • Yes I was thinking also that sending signal for every letter changed is redundant. Yes I like the word "binding" because it has some unique features. But it does not same with assigning to property on a signal way. – cavitsinadogru Mar 04 '16 at 06:31

2 Answers2

4

You could try to assign the binding like this:

Component.onCompleted: Singleton.name = Qt.binding(function() { return qmlName })

It works for normal QML-Objects, not sure it works with a singleton class, though. Anyhow, you can read more about this approach in the section "Creating Property Bindings from JavaScript".

BaCaRoZzo
  • 7,502
  • 6
  • 51
  • 82
Felix
  • 6,885
  • 1
  • 29
  • 54
0

That is essentially what a property binding does, at least I assume it is what it does - it connects the changed() signals of the related variables to reevaluating the bound expression which references them.

So this in practice is a binding:

onQmlNameChanged: {
    Singleton.name = qmlName;
}

You will only have a problem if you only execute the assignment once, but if it is attached to a signal it will keep updating as expected form a binding.

That would be identical to a Singleton.name : qmlName, unfortunately, the QML syntax does not allow to do it in this form. So for all intents and purposes, you do have a binding, even if it uses a different syntax to achieve it.

In fact this shouldn't be much different from what QML does under the carpet for you. For example the binding:

someProp : anotherProp + yetAnotherProp

is implement as something like this:

function unnamed(this) { return this.anotherProp + this.yetAnotherProp }
anotherPropChanged.connect(function(this) { this.someProp = unnamed(this) })
yetAnotherPropChanged.connect(function(this) { this.someProp = unnamed(this) })

Obviously, that is quite cumbersome to do manually especially as the expression becomes more complex and references more objects, so QML is doing it for you.

dtech
  • 47,916
  • 17
  • 112
  • 190
  • I am not sure this is what property binding does. I don't think so because, qmlName have to be changed, so line Singleton.name = qmlName to be executed. But on the other hand, when we bind a property, binded property is also initialized with the property that binded. So to mimic a property bind, we also have to workaround this also. And second, this makes a permanent relation between the qmlName and Singleton.name, but on the property binding, this relation is fragile, I mean if we assign anything to binded property, property binding will be broken. – cavitsinadogru Mar 03 '16 at 09:02
  • Well yes, this way it won't be scheduled for automatic evaluation on component completion, you would have to do it manually. And yes, you would also have to disconnect manually, which is only possible if instead of `onSignal: expr` you use `signal.connect(namedFoo)` so later you can call `signal.disconnect(namedFoo)`. Doing the binding manually implies managing it manually as well. If the solution suggested by Felix works you should go with it as it does all that stuff automatically for you. – dtech Mar 03 '16 at 11:56
  • yes seems like @Felix solution is more accurate. Thank you for joining to thread. – cavitsinadogru Mar 03 '16 at 12:06