1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 BasysKom GmbH.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include <QtQuick/private/qquickvaluetypes_p.h>
6#include <QtQuick/private/qquickapplication_p.h>
7#include <QtQuick/private/qquickstate_p.h>
8#include <QtQuick/private/qquickpropertychanges_p.h>
9#include <QtQuick/private/qquickitemsmodule_p.h>
10#if QT_CONFIG(accessibility)
11# include <QtQuick/private/qquickaccessiblefactory_p.h>
12#endif
13#include <QtGui/QGuiApplication>
14#include <QtGui/qdesktopservices.h>
15#include <QtGui/qfontdatabase.h>
16#include <QtGui/qstylehints.h>
17
18#include <QtQml/private/qqmlbinding_p.h>
19#include <QtQml/private/qqmldebugserviceinterfaces_p.h>
20#include <QtQml/private/qqmldebugstatesdelegate_p.h>
21#include <QtQml/private/qqmlglobal_p.h>
22#include <QtQml/private/qv4engine_p.h>
23#include <QtQml/private/qv4object_p.h>
24#include <QtQml/private/qqmlanybinding_p.h>
25
26#include <QtCore/qiterable.h>
27
28#ifdef Q_CC_MSVC
29// MSVC2010 warns about 'unused variable t', even if it's used in t->~T()
30# pragma warning( disable : 4189 )
31#endif
32
33QT_BEGIN_NAMESPACE
34
35#if QT_CONFIG(qml_debug)
36
37class QQmlQtQuick2DebugStatesDelegate : public QQmlDebugStatesDelegate
38{
39public:
40 QQmlQtQuick2DebugStatesDelegate();
41 ~QQmlQtQuick2DebugStatesDelegate();
42 void buildStatesList(bool cleanList, const QList<QPointer<QObject> > &instances) override;
43 void updateBinding(QQmlContext *context,
44 const QQmlProperty &property,
45 const QVariant &expression, bool isLiteralValue,
46 const QString &fileName, int line, int column,
47 bool *isBaseState) override;
48 bool setBindingForInvalidProperty(QObject *object,
49 const QString &propertyName,
50 const QVariant &expression,
51 bool isLiteralValue) override;
52 void resetBindingForInvalidProperty(QObject *object,
53 const QString &propertyName) override;
54
55private:
56 void buildStatesList(QObject *obj);
57
58 QList<QPointer<QQuickState> > m_allStates;
59};
60
61QQmlQtQuick2DebugStatesDelegate::QQmlQtQuick2DebugStatesDelegate()
62{
63}
64
65QQmlQtQuick2DebugStatesDelegate::~QQmlQtQuick2DebugStatesDelegate()
66{
67}
68
69void QQmlQtQuick2DebugStatesDelegate::buildStatesList(bool cleanList,
70 const QList<QPointer<QObject> > &instances)
71{
72 if (cleanList)
73 m_allStates.clear();
74
75 //only root context has all instances
76 for (int ii = 0; ii < instances.size(); ++ii) {
77 buildStatesList(obj: instances.at(i: ii));
78 }
79}
80
81void QQmlQtQuick2DebugStatesDelegate::buildStatesList(QObject *obj)
82{
83 if (QQuickState *state = qobject_cast<QQuickState *>(object: obj)) {
84 m_allStates.append(t: state);
85 }
86
87 QObjectList children = obj->children();
88 for (int ii = 0; ii < children.size(); ++ii) {
89 buildStatesList(obj: children.at(i: ii));
90 }
91}
92
93void QQmlQtQuick2DebugStatesDelegate::updateBinding(QQmlContext *context,
94 const QQmlProperty &property,
95 const QVariant &expression, bool isLiteralValue,
96 const QString &fileName, int line, int column,
97 bool *inBaseState)
98{
99 Q_UNUSED(column);
100 typedef QPointer<QQuickState> QuickStatePointer;
101 QObject *object = property.object();
102 QString propertyName = property.name();
103 for (const QuickStatePointer& statePointer : std::as_const(t&: m_allStates)) {
104 if (QQuickState *state = statePointer.data()) {
105 // here we assume that the revert list on itself defines the base state
106 if (state->isStateActive() && state->containsPropertyInRevertList(target: object, name: propertyName)) {
107 *inBaseState = false;
108
109 QQmlAnyBinding newBinding;
110 if (!isLiteralValue) {
111 newBinding = QQmlAnyBinding::createFromCodeString(prop: property,
112 code: expression.toString(), obj: object,
113 ctxt: QQmlContextData::get(context), url: fileName,
114 lineNumber: line);
115 }
116 state->changeBindingInRevertList(target: object, name: propertyName, binding: newBinding);
117
118 if (isLiteralValue)
119 state->changeValueInRevertList(target: object, name: propertyName, revertValue: expression);
120 }
121 }
122 }
123}
124
125bool QQmlQtQuick2DebugStatesDelegate::setBindingForInvalidProperty(QObject *object,
126 const QString &propertyName,
127 const QVariant &expression,
128 bool isLiteralValue)
129{
130 if (QQuickPropertyChanges *propertyChanges = qobject_cast<QQuickPropertyChanges *>(object)) {
131 if (isLiteralValue)
132 propertyChanges->changeValue(name: propertyName, value: expression);
133 else
134 propertyChanges->changeExpression(name: propertyName, expression: expression.toString());
135 return true;
136 } else {
137 return false;
138 }
139}
140
141void QQmlQtQuick2DebugStatesDelegate::resetBindingForInvalidProperty(QObject *object, const QString &propertyName)
142{
143 if (QQuickPropertyChanges *propertyChanges = qobject_cast<QQuickPropertyChanges *>(object)) {
144 propertyChanges->removeProperty(name: propertyName);
145 }
146}
147
148static QQmlDebugStatesDelegate *statesDelegateFactory()
149{
150 return new QQmlQtQuick2DebugStatesDelegate;
151}
152
153#endif // QT_CONFIG(qml_debug)
154
155class QQuickColorProvider : public QQmlColorProvider
156{
157public:
158 QVariant colorFromString(const QString &s, bool *ok) override
159 {
160 QColor c = QColor::fromString(name: s);
161 if (c.isValid()) {
162 if (ok) *ok = true;
163 return QVariant(c);
164 }
165
166 if (ok) *ok = false;
167 return QVariant();
168 }
169
170 unsigned rgbaFromString(const QString &s, bool *ok) override
171 {
172 QColor c = QColor::fromString(name: s);
173 if (c.isValid()) {
174 if (ok) *ok = true;
175 return c.rgba();
176 }
177
178 if (ok) *ok = false;
179 return 0;
180 }
181
182 QString stringFromRgba(unsigned rgba)
183 {
184 QColor c(QColor::fromRgba(rgba));
185 if (c.isValid()) {
186 return QVariant(c).toString();
187 }
188
189 return QString();
190 }
191
192 QVariant fromRgbF(double r, double g, double b, double a) override
193 {
194 return QVariant(QColor::fromRgbF(r, g, b, a));
195 }
196
197 QVariant fromHslF(double h, double s, double l, double a) override
198 {
199 return QVariant(QColor::fromHslF(h, s, l, a));
200 }
201
202 QVariant fromHsvF(double h, double s, double v, double a) override
203 {
204 return QVariant(QColor::fromHsvF(h, s, v, a));
205 }
206
207 QVariant lighter(const QVariant &var, qreal factor) override
208 {
209 QColor color = var.value<QColor>();
210 color = color.lighter(f: int(qRound(d: factor*100.)));
211 return QVariant::fromValue(value: color);
212 }
213
214 QVariant darker(const QVariant &var, qreal factor) override
215 {
216 QColor color = var.value<QColor>();
217 color = color.darker(f: int(qRound(d: factor*100.)));
218 return QVariant::fromValue(value: color);
219 }
220
221 QVariant alpha(const QVariant &var, qreal value) override
222 {
223 QColor color = var.value<QColor>();
224 color.setAlphaF(value);
225 return QVariant::fromValue(value: color);
226 }
227
228 QVariant tint(const QVariant &baseVar, const QVariant &tintVar) override
229 {
230 QColor tintColor = tintVar.value<QColor>().toRgb();
231
232 int tintAlpha = tintColor.alpha();
233 if (tintAlpha == 0xFF) {
234 return tintVar;
235 } else if (tintAlpha == 0x00) {
236 return baseVar;
237 }
238
239 // tint the base color and return the final color
240 QColor baseColor = baseVar.value<QColor>().toRgb();
241 qreal a = tintColor.alphaF();
242 qreal inv_a = 1.0 - a;
243
244 qreal r = tintColor.redF() * a + baseColor.redF() * inv_a;
245 qreal g = tintColor.greenF() * a + baseColor.greenF() * inv_a;
246 qreal b = tintColor.blueF() * a + baseColor.blueF() * inv_a;
247
248 return QVariant::fromValue(value: QColor::fromRgbF(r, g, b, a: a + inv_a * baseColor.alphaF()));
249 }
250};
251
252class QQuickGuiProvider : public QQmlGuiProvider
253{
254public:
255 QQuickApplication *application(QObject *parent) override
256 {
257 return new QQuickApplication(parent);
258 }
259
260#if QT_CONFIG(im)
261 QInputMethod *inputMethod() override
262 {
263 QInputMethod *im = qGuiApp->inputMethod();
264 QQmlEngine::setObjectOwnership(im, QQmlEngine::CppOwnership);
265 return im;
266 }
267#endif
268
269 QStyleHints *styleHints() override
270 {
271 QStyleHints *sh = qGuiApp->styleHints();
272 QQmlEngine::setObjectOwnership(sh, QQmlEngine::CppOwnership);
273 return sh;
274 }
275
276 QStringList fontFamilies() override
277 {
278 return QFontDatabase::families();
279 }
280
281 bool openUrlExternally(const QUrl &url) override
282 {
283#ifndef QT_NO_DESKTOPSERVICES
284 return QDesktopServices::openUrl(url);
285#else
286 Q_UNUSED(url);
287 return false;
288#endif
289 }
290
291 QString pluginName() const override
292 {
293 return QGuiApplication::platformName();
294 }
295};
296
297static QQuickColorProvider *getColorProvider()
298{
299 static QQuickColorProvider colorProvider;
300 return &colorProvider;
301}
302
303static QQuickGuiProvider *getGuiProvider()
304{
305 static QQuickGuiProvider guiProvider;
306 return &guiProvider;
307}
308
309void QQuick_initializeModule()
310{
311 // This is used by QQuickPath, and on macOS it fails to automatically register.
312 qRegisterMetaType<QVector<QVector<QPointF>>>();
313
314 QQml_setColorProvider(getColorProvider());
315 QQml_setGuiProvider(getGuiProvider());
316
317 QQuickItemsModule::defineModule();
318
319#if QT_CONFIG(accessibility)
320 QAccessible::installFactory(&qQuickAccessibleFactory);
321#endif
322
323#if QT_CONFIG(qml_debug)
324 QQmlEngineDebugService::setStatesDelegateFactory(statesDelegateFactory);
325#endif
326}
327
328Q_CONSTRUCTOR_FUNCTION(QQuick_initializeModule)
329
330QT_END_NAMESPACE
331

source code of qtdeclarative/src/quick/util/qquickglobal.cpp