Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquickbehavior.cpp
Go to the documentation of this file.
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 "qquickbehavior_p.h"
5
6#include "qquickanimation_p.h"
7#include <qqmlcontext.h>
8#include <qqmlinfo.h>
9#include <private/qqmlproperty_p.h>
10#include <private/qqmlengine_p.h>
11#include <private/qabstractanimationjob_p.h>
12#include <private/qquicktransition_p.h>
13
14#include <private/qquickanimatorjob_p.h>
15
16#include <private/qobject_p.h>
17#include <QtCore/qpointer.h>
18
20
40{
42 QUntypedPropertyData *m_sourcePropertyData;
43 const QtPrivate::QBindableInterface *m_sourceInterface;
44 QVariant m_storage;
45public:
46 void static getter(const QUntypedPropertyData *d, void *value)
47 {
48 auto This = static_cast<const UntypedProxyProperty *>(d);
49 // multiplexing: If the flag is set, we want to receive the metatype instead
51 *reinterpret_cast<QMetaType *>(quintptr(value) &
52 ~QtPrivate::QBindableInterface::MetaTypeAccessorFlag)
53 = This->type();
54 return;
55 }
56 This->type().construct(value, This->m_storage.constData());
57 This->m_bindingData.registerWithCurrentlyEvaluatingBinding();
58 }
59
60 void static setter(QUntypedPropertyData *d, const void *value)
61 {
62 auto This = static_cast<UntypedProxyProperty *>(d);
63 This->type().construct(This->m_storage.data(), value);
64 This->m_bindingData.notifyObservers(reinterpret_cast<QUntypedPropertyData *>(This->m_storage.data()));
65 }
66
68 {
69 auto This = static_cast<const UntypedProxyProperty *>(d);
70 return QUntypedPropertyBinding(This->m_bindingData.binding());
71 }
72
74 const QUntypedPropertyBinding &binding)
75 {
76 auto This = static_cast<UntypedProxyProperty *>(d);
77 const QMetaType type = This->type();
78 if (binding.valueMetaType() != type)
79 return {};
80
81 // We want to notify in any case here because the target property should be set
82 // even if our proxy binding results in the default value.
83 QPropertyBindingPrivate::get(binding)->scheduleNotify();
84 return This->m_bindingData.setBinding(binding,
85 reinterpret_cast<QUntypedPropertyData *>(
86 This->m_storage.data()));
87 }
88
91 {
92 auto This = static_cast<const UntypedProxyProperty *>(d);
93 return This->m_sourceInterface->makeBinding(This->m_sourcePropertyData, location);
94 }
95
96 static void setObserver(const QUntypedPropertyData *d, QPropertyObserver *observer)
97 {
98 auto This = static_cast<const UntypedProxyProperty *>(d);
99 This->m_sourceInterface->setObserver(This->m_sourcePropertyData, observer);
100 }
101
102
103
105
107 QMetaType type() const { return m_storage.metaType(); }
108 QVariant value() const {return m_storage;}
109};
110
120
126
131
151
153 m_sourcePropertyData(QUntypedBindablePrivate::getPropertyData(bindable)),
154 m_sourceInterface(QUntypedBindablePrivate::getInterface(bindable)),
155 m_storage(QVariant(bindable.metaType()))
156{
157 behavior->setSource(m_bindingData);
158}
159
194
196{
197 Q_D(QQuickBehavior);
198 delete d->animationInstance;
199}
200
209{
210 Q_D(QQuickBehavior);
211 return d->animation;
212}
213
215{
216 Q_D(QQuickBehavior);
217 if (d->animation) {
218 qmlWarning(this) << tr("Cannot change the animation assigned to a Behavior.");
219 return;
220 }
221
222 d->animation = animation;
223 if (d->animation) {
224 d->animation->setDefaultTarget(d->property);
225 d->animation->setDisableUserControl();
226 }
227}
228
229
231{
232 auto This = static_cast<QQuickBehaviorPrivate *>(observer);
233 This->q_func()->write(This->propertyProxy->value());
234}
235
241
252{
253 Q_D(const QQuickBehavior);
254 return d->enabled;
255}
256
258{
259 Q_D(QQuickBehavior);
260 if (d->enabled == enabled)
261 return;
262 d->enabled = enabled;
264}
265
275{
276 Q_D(const QQuickBehavior);
277 return d->targetValue;
278}
279
349{
350 Q_D(const QQuickBehavior);
351 return d->property;
352}
353
355{
356 Q_D(QQuickBehavior);
357 d->finalized = true;
358}
359
361{
362 Q_D(QQuickBehavior);
363 const bool targetValueHasChanged = d->targetValue != value;
364 if (targetValueHasChanged) {
365 d->targetValue = value;
366 emit targetValueChanged(); // emitting the signal here should allow
367 } // d->enabled to change if scripted by the user.
368 bool bypass = !d->enabled || !d->finalized || QQmlEnginePrivate::designerMode();
369 if (!bypass)
370 qmlExecuteDeferred(this);
371 if (QQmlData::wasDeleted(d->animation) || bypass) {
372 if (d->animationInstance)
373 d->animationInstance->stop();
375 return;
376 }
377
378 bool behaviorActive = d->animation->isRunning();
379 if (behaviorActive && !targetValueHasChanged)
380 return;
381
382 if (d->animationInstance
383 && (d->animationInstance->duration() != -1
384 || d->animationInstance->isRenderThreadProxy())
385 && !d->animationInstance->isStopped()) {
386 d->blockRunningChanged = true;
387 d->animationInstance->stop();
388 }
389 // Render thread animations use "stop" to synchronize the property back
390 // to the item, so we need to read the value after.
391 const QVariant &currentValue = d->property.read();
392
393 // Don't unnecessarily wake up the animation system if no real animation
394 // is needed (value has not changed). If the Behavior was already
395 // running, let it continue as normal to ensure correct behavior and state.
396 if (!behaviorActive && d->targetValue == currentValue) {
398 return;
399 }
400
402 QQuickStateAction action;
403 action.property = d->property;
404 action.fromValue = currentValue;
405 action.toValue = value;
406 actions << action;
407
408 QList<QQmlProperty> after;
409 auto *newInstance = d->animation->transition(actions, after, QQuickAbstractAnimation::Forward);
410 Q_ASSERT(!newInstance || newInstance != d->animationInstance);
411 delete d->animationInstance;
412 d->animationInstance = newInstance;
413
414 if (d->animationInstance) {
415 if (d->animation->threadingModel() == QQuickAbstractAnimation::RenderThread)
416 d->animationInstance = new QQuickAnimatorProxyJob(d->animationInstance, d->animation);
417
418 d->animationInstance->addAnimationChangeListener(d, QAbstractAnimationJob::StateChange);
419 d->animationInstance->start();
420 d->blockRunningChanged = false;
421 }
422
423 if (!after.contains(d->property))
425}
426
428{
429 Q_D(QQuickBehavior);
430 if (!d->propertyProxy)
431 d->propertyProxy = std::make_unique<UntypedProxyProperty>(target, d);
432 *untypedBindable = d->propertyProxy->getBindable();
433 return true;
434}
435
437{
438 Q_D(QQuickBehavior);
439 d->property = property;
440 if (d->animation)
441 d->animation->setDefaultTarget(property);
442
443 if (QMetaProperty metaProp = property.property(); metaProp.isBindable()) {
444 QUntypedBindable untypedBindable = metaProp.bindable(property.object());
445 d->propertyProxy = std::make_unique<UntypedProxyProperty>(untypedBindable, d);
446 if (untypedBindable.hasBinding()) {
447 // should not happen as bindings should get initialized only after interceptors
448 UntypedProxyProperty::bindingSetter(d->propertyProxy.get(), untypedBindable.takeBinding());
449 }
450 }
451
453}
454
456
457#include "moc_qquickbehavior_p.cpp"
\inmodule QtCore
\inmodule QtCore
Definition qmetatype.h:341
void * construct(void *where, const void *copy=nullptr) const
\inmodule QtCore
Definition qobject.h:103
static QPropertyBindingPrivate * get(const QUntypedPropertyBinding &binding)
static bool wasDeleted(const QObject *)
Definition qqmldata_p.h:312
static bool designerMode()
static bool write(QObject *, const QQmlPropertyData &, const QVariant &, const QQmlRefPointer< QQmlContextData > &, QQmlPropertyData::WriteFlags flags={})
The QQmlProperty class abstracts accessing properties on objects created from QML.
QMetaProperty property() const
Returns the \l{QMetaProperty} {Qt property} associated with this QML property.
void setDefaultTarget(const QQmlProperty &)
QAbstractAnimationJob * animationInstance
void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) override
QPointer< QQuickAbstractAnimation > animation
static void onProxyChanged(QPropertyObserver *, QUntypedPropertyData *)
std::unique_ptr< UntypedProxyProperty > propertyProxy
void setEnabled(bool enabled)
void setTarget(const QQmlProperty &) override
Set the target property for the value interceptor.
void write(const QVariant &value) override
This method will be called when a new value is assigned to the property being intercepted.
QQmlProperty targetProperty
void targetValueChanged()
bool bindable(QUntypedBindable *untypedBindable, QUntypedBindable target) override
void componentFinalized() override
The customization point provided by this interface.
QQuickBehavior(QObject *parent=nullptr)
\qmltype Behavior \instantiates QQuickBehavior \inqmlmodule QtQuick
void targetPropertyChanged()
void setAnimation(QQuickAbstractAnimation *)
void enabledChanged()
QQuickAbstractAnimation * animation
\qmlproperty Animation QtQuick::Behavior::animation \qmldefault
QQmlProperty property
\inmodule QtCore
Definition qproperty.h:679
QMetaType valueMetaType() const
Returns the meta-type of the binding.
\inmodule QtCore
Definition qvariant.h:65
QMetaType metaType() const
The UntypedProxyProperty class is a property used in Behavior to handle bindable properties.
static QUntypedPropertyBinding bindingSetter(QUntypedPropertyData *d, const QUntypedPropertyBinding &binding)
QUntypedBindable getBindable()
static QUntypedPropertyBinding makeBinding(const QUntypedPropertyData *d, const QPropertyBindingSourceLocation &location)
static void setter(QUntypedPropertyData *d, const void *value)
static void setObserver(const QUntypedPropertyData *d, QPropertyObserver *observer)
static QUntypedPropertyBinding bindingGetter(const QUntypedPropertyData *d)
QVariant value() const
static void getter(const QUntypedPropertyData *d, void *value)
UntypedProxyProperty(QUntypedBindable bindable, QQuickBehaviorPrivate *behavior)
QMetaType type() const
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
\macro QT_NO_KEYWORDS >
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static QGtk3Storage * m_storage
GLint location
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum type
GLenum target
void qmlExecuteDeferred(QObject *object)
Definition qqml.cpp:49
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
static constexpr QtPrivate::QBindableInterface untypedProxyPropertyBindableInterafce
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define tr(X)
#define Q_EMIT
#define emit
size_t quintptr
Definition qtypes.h:167
const char property[13]
Definition qwizard.cpp:101
QPropertyAnimation animation
[0]
static constexpr quintptr MetaTypeAccessorFlag
Definition qproperty.h:545
UntypedProxyPropertyBindable(UntypedProxyProperty *property)