1// Copyright (C) 2016 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
4#include "qqmlvaluetype_p.h"
5
6#include <QtCore/qmutex.h>
7#include <private/qqmlglobal_p.h>
8#include <QtCore/qdebug.h>
9#include <private/qqmlengine_p.h>
10#include <private/qmetaobjectbuilder_p.h>
11
12QT_BEGIN_NAMESPACE
13
14QQmlValueType::~QQmlValueType()
15{
16 ::free(ptr: m_dynamicMetaObject);
17}
18
19QQmlGadgetPtrWrapper *QQmlGadgetPtrWrapper::instance(QQmlEngine *engine, QMetaType type)
20{
21 return engine ? QQmlEnginePrivate::get(e: engine)->valueTypeInstance(type) : nullptr;
22}
23
24QQmlGadgetPtrWrapper::QQmlGadgetPtrWrapper(QQmlValueType *valueType, QObject *parent)
25 : QObject(parent), m_gadgetPtr(valueType->create())
26{
27 QObjectPrivate *d = QObjectPrivate::get(o: this);
28 Q_ASSERT(!d->metaObject);
29 d->metaObject = valueType;
30}
31
32QQmlGadgetPtrWrapper::~QQmlGadgetPtrWrapper()
33{
34 QObjectPrivate *d = QObjectPrivate::get(o: this);
35 static_cast<const QQmlValueType *>(d->metaObject)->destroy(gadgetPtr: m_gadgetPtr);
36 d->metaObject = nullptr;
37}
38
39void QQmlGadgetPtrWrapper::read(QObject *obj, int idx)
40{
41 Q_ASSERT(m_gadgetPtr);
42 void *a[] = { m_gadgetPtr, nullptr };
43 QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
44}
45
46void QQmlGadgetPtrWrapper::write(
47 QObject *obj, int idx, QQmlPropertyData::WriteFlags flags, int internalIndex) const
48{
49 Q_ASSERT(m_gadgetPtr);
50 int status = -1;
51 void *a[] = { m_gadgetPtr, nullptr, &status, &flags, &internalIndex };
52 QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
53}
54
55QVariant QQmlGadgetPtrWrapper::value() const
56{
57 Q_ASSERT(m_gadgetPtr);
58 return QVariant(metaType(), m_gadgetPtr);
59}
60
61void QQmlGadgetPtrWrapper::setValue(const QVariant &value)
62{
63 Q_ASSERT(m_gadgetPtr);
64 Q_ASSERT(metaType() == value.metaType());
65 const QQmlValueType *type = valueType();
66 type->destruct(gadgetPtr: m_gadgetPtr);
67 type->construct(gadgetPtr: m_gadgetPtr, copy: value.constData());
68}
69
70int QQmlGadgetPtrWrapper::metaCall(QMetaObject::Call type, int id, void **argv)
71{
72 Q_ASSERT(m_gadgetPtr);
73 const QMetaObject *metaObject = valueType()->staticMetaObject();
74 QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, metaObject: &metaObject, index: &id);
75 metaObject->d.static_metacall(static_cast<QObject *>(m_gadgetPtr), type, id, argv);
76 return id;
77}
78
79const QQmlValueType *QQmlGadgetPtrWrapper::valueType() const
80{
81 const QObjectPrivate *d = QObjectPrivate::get(o: this);
82 return static_cast<const QQmlValueType *>(d->metaObject);
83}
84
85QMetaObject *QQmlValueType::toDynamicMetaObject(QObject *)
86{
87 if (!m_dynamicMetaObject) {
88 QMetaObjectBuilder builder(m_staticMetaObject);
89
90 // Do not set PropertyAccessInStaticMetaCall here. QQmlGadgetPtrWrapper likes to
91 // to intercept the metacalls since it needs to use its gadgetPtr.
92 // For QQmlValueType::metaObject() we use the base type that has the flag.
93
94 m_dynamicMetaObject = builder.toMetaObject();
95 }
96 return m_dynamicMetaObject;
97}
98
99void QQmlValueType::objectDestroyed(QObject *)
100{
101}
102
103int QQmlValueType::metaCall(QObject *object, QMetaObject::Call type, int _id, void **argv)
104{
105 return static_cast<QQmlGadgetPtrWrapper *>(object)->metaCall(type, id: _id, argv);
106}
107
108QString QQmlPointFValueType::toString() const
109{
110 return QString::asprintf(format: "QPointF(%g, %g)", v.x(), v.y());
111}
112
113qreal QQmlPointFValueType::x() const
114{
115 return v.x();
116}
117
118qreal QQmlPointFValueType::y() const
119{
120 return v.y();
121}
122
123void QQmlPointFValueType::setX(qreal x)
124{
125 v.setX(x);
126}
127
128void QQmlPointFValueType::setY(qreal y)
129{
130 v.setY(y);
131}
132
133
134QString QQmlPointValueType::toString() const
135{
136 return QString::asprintf(format: "QPoint(%d, %d)", v.x(), v.y());
137}
138
139int QQmlPointValueType::x() const
140{
141 return v.x();
142}
143
144int QQmlPointValueType::y() const
145{
146 return v.y();
147}
148
149void QQmlPointValueType::setX(int x)
150{
151 v.setX(x);
152}
153
154void QQmlPointValueType::setY(int y)
155{
156 v.setY(y);
157}
158
159
160QString QQmlSizeFValueType::toString() const
161{
162 return QString::asprintf(format: "QSizeF(%g, %g)", v.width(), v.height());
163}
164
165qreal QQmlSizeFValueType::width() const
166{
167 return v.width();
168}
169
170qreal QQmlSizeFValueType::height() const
171{
172 return v.height();
173}
174
175void QQmlSizeFValueType::setWidth(qreal w)
176{
177 v.setWidth(w);
178}
179
180void QQmlSizeFValueType::setHeight(qreal h)
181{
182 v.setHeight(h);
183}
184
185
186QString QQmlSizeValueType::toString() const
187{
188 return QString::asprintf(format: "QSize(%d, %d)", v.width(), v.height());
189}
190
191int QQmlSizeValueType::width() const
192{
193 return v.width();
194}
195
196int QQmlSizeValueType::height() const
197{
198 return v.height();
199}
200
201void QQmlSizeValueType::setWidth(int w)
202{
203 v.setWidth(w);
204}
205
206void QQmlSizeValueType::setHeight(int h)
207{
208 v.setHeight(h);
209}
210
211QString QQmlRectFValueType::toString() const
212{
213 return QString::asprintf(format: "QRectF(%g, %g, %g, %g)", v.x(), v.y(), v.width(), v.height());
214}
215
216qreal QQmlRectFValueType::x() const
217{
218 return v.x();
219}
220
221qreal QQmlRectFValueType::y() const
222{
223 return v.y();
224}
225
226void QQmlRectFValueType::setX(qreal x)
227{
228 v.moveLeft(pos: x);
229}
230
231void QQmlRectFValueType::setY(qreal y)
232{
233 v.moveTop(pos: y);
234}
235
236qreal QQmlRectFValueType::width() const
237{
238 return v.width();
239}
240
241qreal QQmlRectFValueType::height() const
242{
243 return v.height();
244}
245
246void QQmlRectFValueType::setWidth(qreal w)
247{
248 v.setWidth(w);
249}
250
251void QQmlRectFValueType::setHeight(qreal h)
252{
253 v.setHeight(h);
254}
255
256qreal QQmlRectFValueType::left() const
257{
258 return v.left();
259}
260
261qreal QQmlRectFValueType::right() const
262{
263 return v.right();
264}
265
266qreal QQmlRectFValueType::top() const
267{
268 return v.top();
269}
270
271qreal QQmlRectFValueType::bottom() const
272{
273 return v.bottom();
274}
275
276
277QString QQmlRectValueType::toString() const
278{
279 return QString::asprintf(format: "QRect(%d, %d, %d, %d)", v.x(), v.y(), v.width(), v.height());
280}
281
282int QQmlRectValueType::x() const
283{
284 return v.x();
285}
286
287int QQmlRectValueType::y() const
288{
289 return v.y();
290}
291
292void QQmlRectValueType::setX(int x)
293{
294 v.moveLeft(pos: x);
295}
296
297void QQmlRectValueType::setY(int y)
298{
299 v.moveTop(pos: y);
300}
301
302int QQmlRectValueType::width() const
303{
304 return v.width();
305}
306
307int QQmlRectValueType::height() const
308{
309 return v.height();
310}
311
312void QQmlRectValueType::setWidth(int w)
313{
314 v.setWidth(w);
315}
316
317void QQmlRectValueType::setHeight(int h)
318{
319 v.setHeight(h);
320}
321
322int QQmlRectValueType::left() const
323{
324 return v.left();
325}
326
327int QQmlRectValueType::right() const
328{
329 return v.right();
330}
331
332int QQmlRectValueType::top() const
333{
334 return v.top();
335}
336
337int QQmlRectValueType::bottom() const
338{
339 return v.bottom();
340}
341
342#if QT_CONFIG(easingcurve)
343QQmlEasingEnums::Type QQmlEasingValueType::type() const
344{
345 return (QQmlEasingEnums::Type)v.type();
346}
347
348qreal QQmlEasingValueType::amplitude() const
349{
350 return v.amplitude();
351}
352
353qreal QQmlEasingValueType::overshoot() const
354{
355 return v.overshoot();
356}
357
358qreal QQmlEasingValueType::period() const
359{
360 return v.period();
361}
362
363void QQmlEasingValueType::setType(QQmlEasingEnums::Type type)
364{
365 v.setType((QEasingCurve::Type)type);
366}
367
368void QQmlEasingValueType::setAmplitude(qreal amplitude)
369{
370 v.setAmplitude(amplitude);
371}
372
373void QQmlEasingValueType::setOvershoot(qreal overshoot)
374{
375 v.setOvershoot(overshoot);
376}
377
378void QQmlEasingValueType::setPeriod(qreal period)
379{
380 v.setPeriod(period);
381}
382
383void QQmlEasingValueType::setBezierCurve(const QVariantList &customCurveVariant)
384{
385 if (customCurveVariant.isEmpty())
386 return;
387
388 if ((customCurveVariant.size() % 6) != 0)
389 return;
390
391 auto convert = [](const QVariant &v, qreal &r) {
392 bool ok;
393 r = v.toReal(ok: &ok);
394 return ok;
395 };
396
397 QEasingCurve newEasingCurve(QEasingCurve::BezierSpline);
398 for (int i = 0, ei = customCurveVariant.size(); i < ei; i += 6) {
399 qreal c1x, c1y, c2x, c2y, c3x, c3y;
400 if (!convert(customCurveVariant.at(i ), c1x)) return;
401 if (!convert(customCurveVariant.at(i: i + 1), c1y)) return;
402 if (!convert(customCurveVariant.at(i: i + 2), c2x)) return;
403 if (!convert(customCurveVariant.at(i: i + 3), c2y)) return;
404 if (!convert(customCurveVariant.at(i: i + 4), c3x)) return;
405 if (!convert(customCurveVariant.at(i: i + 5), c3y)) return;
406
407 const QPointF c1(c1x, c1y);
408 const QPointF c2(c2x, c2y);
409 const QPointF c3(c3x, c3y);
410
411 newEasingCurve.addCubicBezierSegment(c1, c2, endPoint: c3);
412 }
413
414 v = newEasingCurve;
415}
416
417QVariantList QQmlEasingValueType::bezierCurve() const
418{
419 QVariantList rv;
420 const QVector<QPointF> points = v.toCubicSpline();
421 rv.reserve(size: points.size() * 2);
422 for (const auto &point : points)
423 rv << QVariant(point.x()) << QVariant(point.y());
424 return rv;
425}
426#endif // easingcurve
427
428
429QT_END_NAMESPACE
430
431#include "moc_qqmlvaluetype_p.cpp"
432

source code of qtdeclarative/src/qml/qml/qqmlvaluetype.cpp