Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qpropertyanimation.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
51#include "qpropertyanimation.h"
52#include "qanimationgroup.h"
54
55#include <QtCore/QMutex>
56#include <QtCore/QHash>
57#include <QtCore/private/qlocking_p.h>
58
60
62{
63 if (!targetObject || propertyName.value().isEmpty()) {
65 propertyIndex = -1;
66 return;
67 }
68
69 //propertyType will be set to a valid type only if there is a Q_PROPERTY
70 //otherwise it will be set to QVariant::Invalid at the end of this function
71 propertyType = targetObject->property(propertyName.value()).userType();
72 propertyIndex = targetObject->metaObject()->indexOfProperty(propertyName.value());
73
76 if (propertyIndex == -1) {
77 //there is no Q_PROPERTY on the object
79 if (!targetObject->dynamicPropertyNames().contains(propertyName))
80 qWarning("QPropertyAnimation: you're trying to animate a non-existing property %s of "
81 "your QObject",
82 propertyName.value().constData());
83 } else if (!targetObject->metaObject()->property(propertyIndex).isWritable()) {
84 qWarning("QPropertyAnimation: you're trying to animate the non-writable property %s of "
85 "your QObject",
86 propertyName.value().constData());
87 }
88}
89
90void QPropertyAnimationPrivate::updateProperty(const QVariant &newValue)
91{
93 return;
94
95 if (!targetObject)
96 return;
97
98 if (newValue.userType() == propertyType) {
99 //no conversion is needed, we directly call the QMetaObject::metacall
100 //check QMetaProperty::write for an explanation of these
101 int status = -1;
102 int flags = 0;
103 void *argv[] = { const_cast<void *>(newValue.constData()), const_cast<QVariant *>(&newValue), &status, &flags };
105 } else {
106 targetObject->setProperty(propertyName.value().constData(), newValue);
107 }
108}
109
116{
117}
118
128{
131}
132
137{
138 stop();
139}
140
148{
149 return d_func()->targetObject;
150}
151
153{
154 return &d_func()->targetObject;
155}
156
158{
160 if (d->state != QAbstractAnimation::Stopped) {
161 qWarning("QPropertyAnimation::setTargetObject: you can't change the target of a running animation");
162 return;
163 }
164
165 d->targetObject.removeBindingUnlessInWrapper();
166 if (d->targetObject == target)
167 return;
168
169 if (d->targetObject != nullptr)
170 QObject::disconnect(d->targetObject, &QObject::destroyed, this, nullptr);
171 d->targetObject.setValueBypassingBindings(target);
172
173 if (d->targetObject != nullptr) {
174 QObject::connect(d->targetObject, &QObject::destroyed, this,
175 [d] { d->targetObjectDestroyed(); });
176 }
177 d->updateMetaProperty();
178 d->targetObject.notify();
179}
180
189{
190 Q_D(const QPropertyAnimation);
191 return d->propertyName;
192}
193
195{
197 if (d->state != QAbstractAnimation::Stopped) {
198 qWarning("QPropertyAnimation::setPropertyName: you can't change the property name of a running animation");
199 return;
200 }
201
202 d->propertyName.removeBindingUnlessInWrapper();
203
204 if (d->propertyName == propertyName)
205 return;
206
207 d->propertyName.setValueBypassingBindings(propertyName);
208 d->updateMetaProperty();
209 d->propertyName.notify();
210}
211
213{
214 return &d_func()->propertyName;
215}
216
221{
223}
224
233{
235 d->updateProperty(value);
236}
237
246{
248
249 if (!d->targetObject && oldState == Stopped) {
250 qWarning("QPropertyAnimation::updateState (%s): Changing state of an animation without "
251 "target",
252 d->propertyName.value().constData());
253 return;
254 }
255
257
258 QPropertyAnimation *animToStop = nullptr;
259 {
260 Q_CONSTINIT static QBasicMutex mutex;
261 auto locker = qt_unique_lock(mutex);
262 typedef QPair<QObject *, QByteArray> QPropertyAnimationPair;
263 typedef QHash<QPropertyAnimationPair, QPropertyAnimation*> QPropertyAnimationHash;
264 Q_CONSTINIT static QPropertyAnimationHash hash;
265
266 // in case the targetObject gets deleted, the following happens:
267 // 1. targetObject's destroyed signal calls our targetObjectDestroyed.
268 // 2. targetObjectDestroyed calls stop()
269 // 3. QAbstractAnimation::stop() calls setState(Stopped)
270 // 4. setState(Stopped) calls updateState(newState, oldState)
271 // 5. we arrive here. d->targetObject is not yet set to nullptr, we can safely use it.
272 Q_ASSERT(d->targetObject);
273
274 QPropertyAnimationPair key(d->targetObject, d->propertyName);
275 if (newState == Running) {
276 d->updateMetaProperty();
277 animToStop = hash.value(key, nullptr);
278 hash.insert(key, this);
279 locker.unlock();
280 // update the default start value
281 if (oldState == Stopped) {
282 d->setDefaultStartEndValue(
283 d->targetObject->property(d->propertyName.value().constData()));
284 //let's check if we have a start value and an end value
285 const char *what = nullptr;
286 if (!startValue().isValid() && (d->direction == Backward || !d->defaultStartEndValue.isValid())) {
287 what = "start";
288 }
289 if (!endValue().isValid() && (d->direction == Forward || !d->defaultStartEndValue.isValid())) {
290 if (what)
291 what = "start and end";
292 else
293 what = "end";
294 }
295 if (Q_UNLIKELY(what)) {
296 qWarning("QPropertyAnimation::updateState (%s, %s, %ls): starting an animation "
297 "without %s value",
298 d->propertyName.value().constData(),
299 d->targetObject->metaObject()->className(),
300 qUtf16Printable(d->targetObject->objectName()), what);
301 }
302 }
303 } else if (hash.value(key) == this) {
304 hash.remove(key);
305 }
306 }
307
308 //we need to do that after the mutex was unlocked
309 if (animToStop) {
310 // try to stop the top level group
311 QAbstractAnimation *current = animToStop;
312 while (current->group() && current->state() != Stopped)
313 current = current->group();
314 current->stop();
315 }
316}
317
319
320#include "moc_qpropertyanimation.cpp"
State state
state of the animation.
State
This enum describes the state of the animation.
void stop()
Stops the animation.
QAnimationGroup * group() const
If this animation is part of a QAnimationGroup, this function returns a pointer to the group; otherwi...
\inmodule QtCore
Definition qproperty.h:809
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
Definition qcoreevent.h:45
\inmodule QtCore
Definition qhash.h:818
\inmodule QtCore
Definition qmutex.h:285
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3099
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
void setTargetObject(QObject *target)
void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) override
\reimp
bool event(QEvent *event) override
\reimp
void setPropertyName(const QByteArray &propertyName)
~QPropertyAnimation()
Destroys the QPropertyAnimation instance.
void updateCurrentValue(const QVariant &value) override
This virtual function is called by QVariantAnimation whenever the current value changes.
QByteArray propertyName
the target property name for this animation
QPropertyAnimation(QObject *parent=nullptr)
Construct a QPropertyAnimation object.
QBindable< QObject * > bindableTargetObject()
QObject * targetObject
the target QObject for this animation.
QBindable< QByteArray > bindablePropertyName()
\inmodule QtCore
void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) override
\reimp
QVariant startValue
the optional start value of the animation
QVariant endValue
the end value of the animation
bool event(QEvent *event) override
\reimp
\inmodule QtCore
Definition qvariant.h:64
int userType() const
Definition qvariant.h:336
const void * constData() const
Definition qvariant.h:446
QHash< int, QWidget * > hash
[35multi]
else opt state
[0]
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
#define Q_UNLIKELY(x)
std::pair< T1, T2 > QPair
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:162
GLuint64 key
GLenum target
GLbitfield flags
struct _cl_event * event
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qUtf16Printable(string)
Definition qstring.h:1403
QMutex mutex
[2]
static int metacall(QObject *, Call, int, void **)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent