aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlbinding_p.h
blob: 4031a2655e6e959160cd8d3956cf407b5c2bf0a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#ifndef QQMLBINDING_P_H
#define QQMLBINDING_P_H

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#include "qqmlproperty.h"
#include "qqmlscriptstring.h"

#include <QtCore/QObject>
#include <QtCore/QMetaProperty>

#include <private/qqmlabstractbinding_p.h>
#include <private/qqmljavascriptexpression_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qqmltranslation_p.h>

QT_BEGIN_NAMESPACE

class QQmlContext;
class Q_QML_EXPORT QQmlBinding : public QQmlJavaScriptExpression,
                                         public QQmlAbstractBinding
{
    friend class QQmlAbstractBinding;
public:
    typedef QExplicitlySharedDataPointer<QQmlBinding> Ptr;

    static QQmlBinding *create(const QQmlPropertyData *, const QQmlScriptString &, QObject *, QQmlContext *);

    static QQmlBinding *create(
            const QQmlPropertyData *, const QString &, QObject *,
            const QQmlRefPointer<QQmlContextData> &, const QString &url = QString(),
            quint16 lineNumber = 0);

    static QQmlBinding *create(
            const QQmlPropertyData *property, QV4::Function *function, QObject *obj,
            const QQmlRefPointer<QQmlContextData> &ctxt, QV4::ExecutionContext *scope);

    static QQmlBinding *create(QMetaType propertyType, QV4::Function *function, QObject *obj,
                               const QQmlRefPointer<QQmlContextData> &ctxt,
                               QV4::ExecutionContext *scope);

    static QQmlBinding *createTranslationBinding(
            const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
            const QV4::CompiledData::Binding *binding, QObject *obj,
            const QQmlRefPointer<QQmlContextData> &ctxt);

    static QQmlBinding *
    createTranslationBinding(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
                             const QQmlRefPointer<QQmlContextData> &ctxt,
                             const QString &propertyName, const QQmlTranslation &translationData,
                             const QQmlSourceLocation &location, QObject *obj);

    Kind kind() const final { return QQmlAbstractBinding::QmlBinding; }

    ~QQmlBinding() override;

    bool mustCaptureBindableProperty() const final {return true;}
    void refresh() override;

    void setEnabled(bool, QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding) override;
    QString expression() const override;
    void update(QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding);

    typedef int Identifier;
    enum {
        Invalid = -1
    };

    QVariant evaluate();
    bool evaluate(void *result, QMetaType type)
    {
        return QQmlJavaScriptExpression::evaluate(&result, &type, 0);
    }

    void expressionChanged() override;

    QQmlSourceLocation sourceLocation() const override;
    void setSourceLocation(const QQmlSourceLocation &location);
    void setBoundFunction(QV4::BoundFunction *boundFunction) {
        m_boundFunction.set(boundFunction->engine(), *boundFunction);
    }
    bool hasBoundFunction() const { return m_boundFunction.valueRef(); }

    /**
     * This method returns a snapshot of the currently tracked dependencies of
     * this binding. The dependencies can change upon reevaluation. This method is
     * used in GammaRay to visualize binding hierarchies.
     *
     * Call this method from the UI thread.
     */
    QVector<QQmlProperty> dependencies() const;
    // This method is used internally to check whether a binding is constant and can be removed
    virtual bool hasDependencies() const;

protected:
    virtual void doUpdate(const DeleteWatcher &watcher,
                  QQmlPropertyData::WriteFlags flags, QV4::Scope &scope);

    virtual bool write(const QV4::Value &result, bool isUndefined, QQmlPropertyData::WriteFlags flags) = 0;
    virtual bool write(void *result, QMetaType type, bool isUndefined, QQmlPropertyData::WriteFlags flags) = 0;

    int getPropertyType() const;

    bool slowWrite(const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData,
                   const QV4::Value &result, bool isUndefined, QQmlPropertyData::WriteFlags flags);
    bool slowWrite(const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData,
                   const void *result, QMetaType resultType, bool isUndefined,
                   QQmlPropertyData::WriteFlags flags);

    QV4::ReturnedValue evaluate(bool *isUndefined);

private:
    static QQmlBinding *newBinding(const QQmlPropertyData *property);
    static QQmlBinding *newBinding(QMetaType propertyType);

    QQmlSourceLocation *m_sourceLocation = nullptr; // used for Qt.binding() created functions
    QV4::PersistentValue m_boundFunction; // used for Qt.binding() that are created from a bound function object
    void handleWriteError(const void *result, QMetaType resultType, QMetaType metaType);
};

QT_END_NAMESPACE

Q_DECLARE_METATYPE(QQmlBinding*)

#endif // QQMLBINDING_P_H