Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlcppbinding.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4
6
7#include <QtQml/qqmlengine.h>
8#include <QtQml/qqmlcontext.h>
9#include <QtCore/qmetaobject.h>
10
11#include <private/qqmltypedata_p.h>
12#include <private/qqmlpropertybinding_p.h>
13#include <private/qqmlbinding_p.h>
14#include <private/qv4qmlcontext_p.h>
15#include <private/qqmlproperty_p.h>
16#include <private/qqmlbinding_p.h>
17
19
20template<typename CreateBinding>
21inline decltype(auto) createBindingInScope(QObject *thisObject, CreateBinding create)
22{
23 QQmlEngine *qmlengine = qmlEngine(thisObject);
24 Q_ASSERT(qmlengine);
25 QV4::ExecutionEngine *v4 = qmlengine->handle();
26 Q_ASSERT(v4);
27
28 QQmlData *ddata = QQmlData::get(thisObject);
29 Q_ASSERT(ddata && ddata->context);
30 QQmlRefPointer<QQmlContextData> ctxtdata = QQmlRefPointer<QQmlContextData>(ddata->context);
31
32 QV4::Scope scope(v4);
33 QV4::ExecutionContext *executionCtx = v4->scriptContext();
34 QV4::Scoped<QV4::QmlContext> qmlContext(
35 scope, QV4::QmlContext::create(executionCtx, ctxtdata, thisObject));
36
37 return create(ctxtdata, qmlContext);
38}
39
40QUntypedPropertyBinding
41QQmlCppBinding::createBindingForBindable(const QV4::ExecutableCompilationUnit *unit,
42 QObject *thisObject, qsizetype functionIndex,
43 QObject *bindingTarget, int metaPropertyIndex,
44 int valueTypePropertyIndex, const QString &propertyName)
45{
46 Q_UNUSED(propertyName);
47
48 QV4::Function *v4Function = unit->runtimeFunctions.value(functionIndex, nullptr);
49 if (!v4Function) {
50 // TODO: align with existing logging of such
51 qCritical() << "invalid JavaScript function index (internal error)";
52 return QUntypedPropertyBinding();
53 }
54 if (metaPropertyIndex < 0) {
55 // TODO: align with existing logging of such
56 qCritical() << "invalid meta property index (internal error)";
57 return QUntypedPropertyBinding();
58 }
59
60 const QMetaObject *mo = bindingTarget->metaObject();
61 Q_ASSERT(mo);
62 QMetaProperty property = mo->property(metaPropertyIndex);
63 Q_ASSERT(valueTypePropertyIndex == -1 || QString::fromUtf8(property.name()) == propertyName);
64
65 return createBindingInScope(
66 thisObject,
67 [&](const QQmlRefPointer<QQmlContextData> &ctxt, QV4::ExecutionContext *scope) {
68 auto index = QQmlPropertyIndex(property.propertyIndex(), valueTypePropertyIndex);
69 return QQmlPropertyBinding::create(property.metaType(), v4Function, thisObject,
70 ctxt, scope, bindingTarget, index);
71 });
72}
73
74void QQmlCppBinding::createBindingForNonBindable(const QV4::ExecutableCompilationUnit *unit,
75 QObject *thisObject, qsizetype functionIndex,
76 QObject *bindingTarget, int metaPropertyIndex,
77 int valueTypePropertyIndex,
78 const QString &propertyName)
79{
80 Q_UNUSED(propertyName);
81
82 QV4::Function *v4Function = unit->runtimeFunctions.value(functionIndex, nullptr);
83 if (!v4Function) {
84 // TODO: align with existing logging of such
85 qCritical() << "invalid JavaScript function index (internal error)";
86 return;
87 }
88 if (metaPropertyIndex < 0) {
89 // TODO: align with existing logging of such
90 qCritical() << "invalid meta property index (internal error)";
91 return;
92 }
93
94 const QMetaObject *mo = bindingTarget->metaObject();
95 Q_ASSERT(mo);
96 QMetaProperty property = mo->property(metaPropertyIndex);
97 Q_ASSERT(valueTypePropertyIndex != -1 || QString::fromUtf8(property.name()) == propertyName);
98
99 createBindingInScope(
100 thisObject,
101 [&](const QQmlRefPointer<QQmlContextData> &ctxt, QV4::ExecutionContext *scope) -> void {
102 QQmlBinding *binding = QQmlBinding::create(property.metaType(), v4Function,
103 thisObject, ctxt, scope);
104 // almost as in qv4objectwrapper.cpp:535
105 Q_ASSERT(!property.isAlias()); // we convert aliases to (almost) real properties
106 binding->setTarget(bindingTarget, property.propertyIndex(), false,
107 valueTypePropertyIndex);
108 QQmlPropertyPrivate::setBinding(binding);
109 });
110}
111
112QUntypedPropertyBinding QQmlCppBinding::createTranslationBindingForBindable(
113 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, QObject *bindingTarget,
114 int metaPropertyIndex, const QQmlTranslation &translationData, const QString &propertyName)
115{
116 Q_UNUSED(propertyName);
117
118 if (metaPropertyIndex < 0) {
119 // TODO: align with existing logging of such
120 qCritical() << "invalid meta property index (internal error)";
121 return QUntypedPropertyBinding();
122 }
123
124 const QMetaObject *mo = bindingTarget->metaObject();
125 Q_ASSERT(mo);
126 QMetaProperty property = mo->property(metaPropertyIndex);
127 Q_ASSERT(QString::fromUtf8(property.name()) == propertyName);
128
129 return QQmlTranslationPropertyBinding::create(property.metaType(), unit, translationData);
130}
131
132void QQmlCppBinding::createTranslationBindingForNonBindable(
133 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
134 const QQmlSourceLocation &location, const QQmlTranslation &translationData,
135 QObject *thisObject, QObject *bindingTarget, int metaPropertyIndex,
136 const QString &propertyName, int valueTypePropertyIndex)
137{
138 Q_UNUSED(propertyName);
139
140 if (metaPropertyIndex < 0) {
141 // TODO: align with existing logging of such
142 qCritical() << "invalid meta property index (internal error)";
143 return;
144 }
145
146 const QMetaObject *mo = bindingTarget->metaObject();
147 Q_ASSERT(mo);
148 QMetaProperty property = mo->property(metaPropertyIndex);
149 Q_ASSERT(QString::fromUtf8(property.name()) == propertyName);
150
151 createBindingInScope(
152 thisObject,
153 [&](const QQmlRefPointer<QQmlContextData> &ctxt, QV4::ExecutionContext *) -> void {
154 QQmlBinding *binding = QQmlBinding::createTranslationBinding(
155 unit, ctxt, propertyName, translationData, location, thisObject);
156 // almost as in qv4objectwrapper.cpp:535
157 Q_ASSERT(!property.isAlias()); // we convert aliases to (almost) real properties
158 binding->setTarget(bindingTarget, property.propertyIndex(), false,
159 valueTypePropertyIndex);
160 QQmlPropertyPrivate::setBinding(binding);
161 });
162}
163
164QT_END_NAMESPACE
Combined button and popup list for selecting options.