Qt 6.x
The Qt SDK
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
19
39{
41 QUntypedPropertyData *m_sourcePropertyData;
42 const QtPrivate::QBindableInterface *m_sourceInterface;
43 QVariant m_storage;
44public:
45 void static getter(const QUntypedPropertyData *d, void *value)
46 {
47 auto This = static_cast<const UntypedProxyProperty *>(d);
48 // multiplexing: If the flag is set, we want to receive the metatype instead
50 *reinterpret_cast<QMetaType *>(quintptr(value) &
51 ~QtPrivate::QBindableInterface::MetaTypeAccessorFlag)
52 = This->type();
53 return;
54 }
55 This->type().construct(value, This->m_storage.constData());
56 This->m_bindingData.registerWithCurrentlyEvaluatingBinding();
57 }
58
59 void static setter(QUntypedPropertyData *d, const void *value)
60 {
61 auto This = static_cast<UntypedProxyProperty *>(d);
62 This->type().construct(This->m_storage.data(), value);
63 This->m_bindingData.notifyObservers(reinterpret_cast<QUntypedPropertyData *>(This->m_storage.data()));
64 }
65
67 {
68 auto This = static_cast<const UntypedProxyProperty *>(d);
69 return QUntypedPropertyBinding(This->m_bindingData.binding());
70 }
71
73 const QUntypedPropertyBinding &binding)
74 {
75 auto This = static_cast<UntypedProxyProperty *>(d);
76 const QMetaType type = This->type();
77 if (binding.valueMetaType() != type)
78 return {};
79
80 // We want to notify in any case here because the target property should be set
81 // even if our proxy binding results in the default value.
83 return This->m_bindingData.setBinding(binding,
84 reinterpret_cast<QUntypedPropertyData *>(
85 This->m_storage.data()));
86 }
87
90 {
91 auto This = static_cast<const UntypedProxyProperty *>(d);
92 return This->m_sourceInterface->makeBinding(This->m_sourcePropertyData, location);
93 }
94
95 static void setObserver(const QUntypedPropertyData *d, QPropertyObserver *observer)
96 {
97 auto This = static_cast<const UntypedProxyProperty *>(d);
98 This->m_sourceInterface->setObserver(This->m_sourcePropertyData, observer);
99 }
100
101
102
104
106 QMetaType type() const { return m_storage.metaType(); }
107 QVariant value() const {return m_storage;}
108};
109
117 /*metatype*/nullptr
118};
119
123 {}
124};
125
127{
128 return UntypedProxyPropertyBindable {const_cast<UntypedProxyProperty *>(this)};
129}
130
132{
133 Q_DECLARE_PUBLIC(QQuickBehavior)
134public:
139
144 std::unique_ptr<UntypedProxyProperty> propertyProxy;
145 bool enabled = true;
146 bool finalized = false;
148
149};
150
152 m_sourcePropertyData(QUntypedBindablePrivate::getPropertyData(bindable)),
153 m_sourceInterface(QUntypedBindablePrivate::getInterface(bindable)),
154 m_storage(QVariant(bindable.metaType()))
155{
156 behavior->setSource(m_bindingData);
157}
158
191{
192}
193
195{
196 Q_D(QQuickBehavior);
197 delete d->animationInstance;
198}
199
208{
209 Q_D(QQuickBehavior);
210 return d->animation;
211}
212
214{
215 Q_D(QQuickBehavior);
216 if (d->animation) {
217 qmlWarning(this) << tr("Cannot change the animation assigned to a Behavior.");
218 return;
219 }
220
221 d->animation = animation;
222 if (d->animation) {
223 d->animation->setDefaultTarget(d->property);
224 d->animation->setDisableUserControl();
225 }
226}
227
228
230{
231 auto This = static_cast<QQuickBehaviorPrivate *>(observer);
232 This->q_func()->write(This->propertyProxy->value());
233}
234
236{
238 animation->notifyRunningChanged(newState == QAbstractAnimationJob::Running);
239}
240
251{
252 Q_D(const QQuickBehavior);
253 return d->enabled;
254}
255
257{
258 Q_D(QQuickBehavior);
259 if (d->enabled == enabled)
260 return;
261 d->enabled = enabled;
263}
264
274{
275 Q_D(const QQuickBehavior);
276 return d->targetValue;
277}
278
348{
349 Q_D(const QQuickBehavior);
350 return d->property;
351}
352
354{
355 Q_D(QQuickBehavior);
356 d->finalized = true;
357}
358
360{
361 Q_D(QQuickBehavior);
362 const bool targetValueHasChanged = d->targetValue != value;
363 if (targetValueHasChanged) {
364 d->targetValue = value;
365 emit targetValueChanged(); // emitting the signal here should allow
366 } // d->enabled to change if scripted by the user.
367 bool bypass = !d->enabled || !d->finalized || QQmlEnginePrivate::designerMode();
368 if (!bypass)
369 qmlExecuteDeferred(this);
370 if (QQmlData::wasDeleted(d->animation) || bypass) {
371 if (d->animationInstance)
372 d->animationInstance->stop();
374 return;
375 }
376
377 bool behaviorActive = d->animation->isRunning();
378 if (behaviorActive && !targetValueHasChanged)
379 return;
380
381 if (d->animationInstance
382 && (d->animationInstance->duration() != -1
383 || d->animationInstance->isRenderThreadProxy())
384 && !d->animationInstance->isStopped()) {
385 d->blockRunningChanged = true;
386 d->animationInstance->stop();
387 }
388 // Render thread animations use "stop" to synchronize the property back
389 // to the item, so we need to read the value after.
390 const QVariant &currentValue = d->property.read();
391
392 // Don't unnecessarily wake up the animation system if no real animation
393 // is needed (value has not changed). If the Behavior was already
394 // running, let it continue as normal to ensure correct behavior and state.
395 if (!behaviorActive && d->targetValue == currentValue) {
397 return;
398 }
399
401 QQuickStateAction action;
402 action.property = d->property;
403 action.fromValue = currentValue;
404 action.toValue = value;
405 actions << action;
406
408 auto *newInstance = d->animation->transition(actions, after, QQuickAbstractAnimation::Forward);
409 Q_ASSERT(newInstance != d->animationInstance);
410 delete d->animationInstance;
411 d->animationInstance = newInstance;
412
413 if (d->animationInstance) {
414 if (d->animation->threadingModel() == QQuickAbstractAnimation::RenderThread)
415 d->animationInstance = new QQuickAnimatorProxyJob(d->animationInstance, d->animation);
416
417 d->animationInstance->addAnimationChangeListener(d, QAbstractAnimationJob::StateChange);
418 d->animationInstance->start();
419 d->blockRunningChanged = false;
420 }
421
422 if (!after.contains(d->property))
424}
425
427{
428 Q_D(QQuickBehavior);
429 if (!d->propertyProxy)
430 d->propertyProxy = std::make_unique<UntypedProxyProperty>(target, d);
431 *untypedBindable = d->propertyProxy->getBindable();
432 return true;
433}
434
436{
437 Q_D(QQuickBehavior);
438 d->property = property;
439 if (d->animation)
440 d->animation->setDefaultTarget(property);
441
442 if (QMetaProperty metaProp = property.property(); metaProp.isBindable()) {
443 QUntypedBindable untypedBindable = metaProp.bindable(property.object());
444 d->propertyProxy = std::make_unique<UntypedProxyProperty>(untypedBindable, d);
445 if (untypedBindable.hasBinding()) {
446 // should not happen as bindings should get initialized only after interceptors
447 UntypedProxyProperty::bindingSetter(d->propertyProxy.get(), untypedBindable.takeBinding());
448 }
449 }
450
452}
453
455
456#include "moc_qquickbehavior_p.cpp"
\inmodule QtCore
\inmodule QtCore
Definition qmetatype.h:320
void * construct(void *where, const void *copy=nullptr) const
\inmodule QtCore
Definition qobject.h:90
\inmodule QtCore
Definition qpointer.h:18
static QPropertyBindingPrivate * get(const QUntypedPropertyBinding &binding)
void setSource(const Property &property)
Definition qproperty.h:267
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.
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.
FINALQQmlProperty targetProperty
void write(const QVariant &value) override
This method will be called when a new value is assigned to the property being intercepted.
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:677
bool hasBinding() const
Returns true if the underlying property has a binding.
Definition qproperty.h:785
QUntypedPropertyBinding takeBinding()
Removes the currently set binding from the property and returns it.
Definition qproperty.h:706
QMetaType valueMetaType() const
Returns the meta-type of the binding.
\inmodule QtCore
Definition qvariant.h:64
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_NAMESPACE
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:48
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:72
const char property[13]
Definition qwizard.cpp:101
QPropertyAnimation animation
[0]
bool contains(const AT &t) const noexcept
Definition qlist.h:44
static constexpr quintptr MetaTypeAccessorFlag
Definition qproperty.h:543
UntypedProxyPropertyBindable(UntypedProxyProperty *property)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent