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
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 const QObject *target = targetObject.valueBypassingBindings();
64 if (!target || propertyName.value().isEmpty()) {
66 propertyIndex = -1;
67 return;
68 }
69
70 //propertyType will be set to a valid type only if there is a Q_PROPERTY
71 //otherwise it will be set to QVariant::Invalid at the end of this function
72 propertyType = target->property(propertyName.value()).userType();
73 propertyIndex = target->metaObject()->indexOfProperty(propertyName.value());
74
77 if (propertyIndex == -1) {
78 //there is no Q_PROPERTY on the object
80 if (!target->dynamicPropertyNames().contains(propertyName))
81 qWarning("QPropertyAnimation: you're trying to animate a non-existing property %s of "
82 "your QObject",
83 propertyName.value().constData());
84 } else if (!target->metaObject()->property(propertyIndex).isWritable()) {
85 qWarning("QPropertyAnimation: you're trying to animate the non-writable property %s of "
86 "your QObject",
87 propertyName.value().constData());
88 }
89}
90
91void QPropertyAnimationPrivate::updateProperty(const QVariant &newValue)
92{
94 return;
95
96 if (!targetObject)
97 return;
98
99 if (newValue.userType() == propertyType) {
100 //no conversion is needed, we directly call the QMetaObject::metacall
101 //check QMetaProperty::write for an explanation of these
102 int status = -1;
103 int flags = 0;
104 void *argv[] = { const_cast<void *>(newValue.constData()), const_cast<QVariant *>(&newValue), &status, &flags };
106 } else {
107 targetObject->setProperty(propertyName.value().constData(), newValue);
108 }
109}
110
119
133
141
149{
150 return d_func()->targetObject;
151}
152
154{
155 return &d_func()->targetObject;
156}
157
159{
161 if (d->state != QAbstractAnimation::Stopped) {
162 qWarning("QPropertyAnimation::setTargetObject: you can't change the target of a running animation");
163 return;
164 }
165
166 d->targetObject.removeBindingUnlessInWrapper();
167 const QObject *oldTarget = d->targetObject.valueBypassingBindings();
168 if (oldTarget == target)
169 return;
170
171 if (oldTarget != nullptr)
172 QObject::disconnect(oldTarget, &QObject::destroyed, this, nullptr);
173 d->targetObject.setValueBypassingBindings(target);
174
175 if (target != nullptr) {
177 [d] { d->targetObjectDestroyed(); });
178 }
179 d->updateMetaProperty();
180 d->targetObject.notify();
181}
182
191{
192 Q_D(const QPropertyAnimation);
193 return d->propertyName;
194}
195
197{
199 if (d->state != QAbstractAnimation::Stopped) {
200 qWarning("QPropertyAnimation::setPropertyName: you can't change the property name of a running animation");
201 return;
202 }
203
204 d->propertyName.removeBindingUnlessInWrapper();
205
206 if (d->propertyName.valueBypassingBindings() == propertyName)
207 return;
208
209 d->propertyName.setValueBypassingBindings(propertyName);
210 d->updateMetaProperty();
211 d->propertyName.notify();
212}
213
215{
216 return &d_func()->propertyName;
217}
218
226
235{
237 d->updateProperty(value);
238}
239
248{
250
251 if (!d->targetObject && oldState == Stopped) {
252 qWarning("QPropertyAnimation::updateState (%s): Changing state of an animation without "
253 "target",
254 d->propertyName.value().constData());
255 return;
256 }
257
259
260 QPropertyAnimation *animToStop = nullptr;
261 {
262 Q_CONSTINIT static QBasicMutex mutex;
263 auto locker = qt_unique_lock(mutex);
264 using QPropertyAnimationPair = std::pair<QObject *, QByteArray>;
265 typedef QHash<QPropertyAnimationPair, QPropertyAnimation*> QPropertyAnimationHash;
266 Q_CONSTINIT static QPropertyAnimationHash hash;
267
268 // in case the targetObject gets deleted, the following happens:
269 // 1. targetObject's destroyed signal calls our targetObjectDestroyed.
270 // 2. targetObjectDestroyed calls stop()
271 // 3. QAbstractAnimation::stop() calls setState(Stopped)
272 // 4. setState(Stopped) calls updateState(newState, oldState)
273 // 5. we arrive here. d->targetObject is not yet set to nullptr, we can safely use it.
274 Q_ASSERT(d->targetObject);
275
276 QPropertyAnimationPair key(d->targetObject, d->propertyName);
277 if (newState == Running) {
278 d->updateMetaProperty();
279 animToStop = hash.value(key, nullptr);
280 hash.insert(key, this);
281 locker.unlock();
282 // update the default start value
283 if (oldState == Stopped) {
284 d->setDefaultStartEndValue(
285 d->targetObject->property(d->propertyName.value().constData()));
286 //let's check if we have a start value and an end value
287 const char *what = nullptr;
288 if (!startValue().isValid() && (d->direction == Backward || !d->defaultStartEndValue.isValid())) {
289 what = "start";
290 }
291 if (!endValue().isValid() && (d->direction == Forward || !d->defaultStartEndValue.isValid())) {
292 if (what)
293 what = "start and end";
294 else
295 what = "end";
296 }
297 if (Q_UNLIKELY(what)) {
298 qWarning("QPropertyAnimation::updateState (%s, %s, %ls): starting an animation "
299 "without %s value",
300 d->propertyName.value().constData(),
301 d->targetObject->metaObject()->className(),
302 qUtf16Printable(d->targetObject->objectName()), what);
303 }
304 }
305 } else if (hash.value(key) == this) {
306 hash.remove(key);
307 }
308 }
309
310 //we need to do that after the mutex was unlocked
311 if (animToStop) {
312 // try to stop the top level group
313 QAbstractAnimation *current = animToStop;
314 while (current->group() && current->state() != Stopped)
315 current = current->group();
316 current->stop();
317 }
318}
319
321
322#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 qbytearray.h:57
\inmodule QtCore
Definition qcoreevent.h:45
\inmodule QtCore
Definition qmutex.h:281
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
QVariant property(const char *name) const
Returns the value of the object's name property.
Definition qobject.cpp:4323
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:65
int userType() const
Definition qvariant.h:339
const void * constData() const
Definition qvariant.h:451
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)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:166
GLuint64 key
GLenum target
GLbitfield flags
struct _cl_event * event
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qUtf16Printable(string)
Definition qstring.h:1543
QMutex mutex
[2]
static int metacall(QObject *, Call, int, void **)