Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquickanimatedimage.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
6
7#include <QtGui/qguiapplication.h>
8#include <QtQml/qqmlinfo.h>
9#include <QtQml/qqmlfile.h>
10#include <QtQml/qqmlengine.h>
11#include <QtGui/qmovie.h>
12#if QT_CONFIG(qml_network)
13#include <QtNetwork/qnetworkrequest.h>
14#include <QtNetwork/qnetworkreply.h>
15#endif
16
18
20{
21 if (!movie)
22 return nullptr;
23
24 int current = movie->currentFrameNumber();
25 if (!frameMap.contains(current)) {
26 QUrl requestedUrl;
27 QQuickPixmap *pixmap = nullptr;
28 if (engine && !movie->fileName().isEmpty()) {
29 requestedUrl.setUrl(QString::fromUtf8("quickanimatedimage://%1#%2x%3#%4")
30 .arg(movie->fileName())
31 .arg(movie->scaledSize().width())
32 .arg(movie->scaledSize().height())
33 .arg(current));
34 }
35 if (!requestedUrl.isEmpty()) {
37 pixmap = new QQuickPixmap(engine, requestedUrl);
38 else
39 pixmap = new QQuickPixmap(requestedUrl, movie->currentImage());
40 } else {
41 pixmap = new QQuickPixmap;
42 pixmap->setImage(movie->currentImage());
43 }
44 frameMap.insert(current, pixmap);
45 }
46
47 return frameMap.value(current);
48}
49
51{
54}
55
131{
132 connect(this, &QQuickImageBase::cacheChanged, this, &QQuickAnimatedImage::onCacheChanged);
133 connect(this, &QQuickImageBase::currentFrameChanged, this, &QQuickAnimatedImage::frameChanged);
134 connect(this, &QQuickImageBase::currentFrameChanged, this, &QQuickAnimatedImage::currentFrameChanged);
135 connect(this, &QQuickImageBase::frameCountChanged, this, &QQuickAnimatedImage::frameCountChanged);
136}
137
139{
141#if QT_CONFIG(qml_network)
142 if (d->reply)
143 d->reply->deleteLater();
144#endif
145 delete d->movie;
146 d->clearCache();
147}
148
158{
159 Q_D(const QQuickAnimatedImage);
160 if (!d->movie)
161 return d->paused;
162 return d->movie->state()==QMovie::Paused;
163}
164
166{
168 if (pause == d->paused)
169 return;
170 if (!d->movie) {
171 d->paused = pause;
173 } else {
174 d->movie->setPaused(pause);
175 }
176}
177
197{
198 Q_D(const QQuickAnimatedImage);
199 if (!d->movie)
200 return d->playing;
201 return d->movie->state()!=QMovie::NotRunning;
202}
203
205{
207 if (play == d->playing)
208 return;
209 if (!d->movie) {
210 d->playing = play;
212 return;
213 }
214 if (play)
215 d->movie->start();
216 else
217 d->movie->stop();
218}
219
231{
232 Q_D(const QQuickAnimatedImage);
233 if (!d->movie)
234 return d->presetCurrentFrame;
235 return d->movie->currentFrameNumber();
236}
237
239{
241 if (!d->movie) {
242 d->presetCurrentFrame = frame;
243 return;
244 }
245 d->movie->jumpToFrame(frame);
246}
247
249{
250 Q_D(const QQuickAnimatedImage);
251 if (!d->movie)
252 return 0;
253 return d->movie->frameCount();
254}
255
266{
267 Q_D(const QQuickAnimatedImage);
268 return d->speed;
269}
270
272{
274 if (d->speed != speed) {
275 d->speed = speed;
276 if (d->movie)
277 d->movie->setSpeed(qRound(speed * 100.0));
278 emit speedChanged();
279 }
280}
281
283{
285 if (url == d->url)
286 return;
287
288#if QT_CONFIG(qml_network)
289 if (d->reply) {
290 d->reply->deleteLater();
291 d->reply = nullptr;
292 }
293#endif
294
295 d->setImage(QImage());
296 d->oldPlaying = isPlaying();
297 d->setMovie(nullptr);
298 d->url = url;
299 emit sourceChanged(d->url);
300
302 load();
303}
304
306{
308
309 if (d->url.isEmpty()) {
310 d->setProgress(0);
311
312 d->setImage(QImage());
313 if (sourceSize() != d->oldSourceSize) {
314 d->oldSourceSize = sourceSize();
316 }
317
318 d->setStatus(Null);
319 if (isPlaying() != d->oldPlaying)
321 } else {
322 const qreal targetDevicePixelRatio = (window() ? window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio());
323 d->devicePixelRatio = 1.0;
324
325 const auto context = qmlContext(this);
326 QUrl loadUrl = context ? context->resolvedUrl(d->url) : d->url;
327 const QUrl resolvedUrl = loadUrl;
328 resolve2xLocalFile(resolvedUrl, targetDevicePixelRatio, &loadUrl, &d->devicePixelRatio);
330
331 d->status = Null; // reset status, no emit
332
333 if (!lf.isEmpty()) {
334 d->setMovie(new QMovie(lf));
335 movieRequestFinished();
336 } else {
337#if QT_CONFIG(qml_network)
338 d->setStatus(Loading);
339 d->setProgress(0);
340 QNetworkRequest req(d->url);
342
343 d->reply = qmlEngine(this)->networkAccessManager()->get(req);
344 connect(d->reply, &QNetworkReply::finished, this, &QQuickAnimatedImage::movieRequestFinished);
345 connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(requestProgress(qint64,qint64)));
346#endif
347 }
348 }
349}
350
351void QQuickAnimatedImage::movieRequestFinished()
352{
354
355#if QT_CONFIG(qml_network)
356 if (d->reply)
357 d->setMovie(new QMovie(d->reply));
358#endif
359
360 if (!d->movie || !d->movie->isValid()) {
361 const QQmlContext *context = qmlContext(this);
362 qmlWarning(this) << "Error Reading Animated Image File "
363 << (context ? context->resolvedUrl(d->url) : d->url).toString();
364 d->setMovie(nullptr);
365
366 d->setImage(QImage());
367 if (sourceSize() != d->oldSourceSize) {
368 d->oldSourceSize = sourceSize();
370 }
371
372 d->setProgress(0);
373 d->setStatus(Error);
374
375 if (isPlaying() != d->oldPlaying)
377 return;
378 }
379
380 connect(d->movie, &QMovie::stateChanged, this, &QQuickAnimatedImage::playingStatusChanged);
381 connect(d->movie, &QMovie::frameChanged, this, &QQuickAnimatedImage::movieUpdate);
382 if (d->cache)
383 d->movie->setCacheMode(QMovie::CacheAll);
384 d->movie->setSpeed(qRound(d->speed * 100.0));
385
386 d->setProgress(1);
387
388 bool pausedAtStart = d->paused;
389 if (d->movie && d->playing)
390 d->movie->start();
391 if (d->movie && pausedAtStart)
392 d->movie->setPaused(true);
393 if (d->movie && (d->paused || !d->playing)) {
394 d->movie->jumpToFrame(d->presetCurrentFrame);
395 d->presetCurrentFrame = 0;
396 }
397
398 QQuickPixmap *pixmap = d->infoForCurrentFrame(qmlEngine(this));
399 if (pixmap) {
400 d->setPixmap(*pixmap);
401 if (sourceSize() != d->oldSourceSize) {
402 d->oldSourceSize = sourceSize();
404 }
405 }
406
407 d->setStatus(Ready);
408
409 if (isPlaying() != d->oldPlaying)
411}
412
413void QQuickAnimatedImage::movieUpdate()
414{
416
417 if (!d->cache)
418 d->clearCache();
419
420 if (d->movie) {
421 d->setPixmap(*d->infoForCurrentFrame(qmlEngine(this)));
422 emit QQuickImageBase::currentFrameChanged();
423 }
424}
425
426void QQuickAnimatedImage::playingStatusChanged()
427{
429
430 if ((d->movie->state() != QMovie::NotRunning) != d->playing) {
431 d->playing = (d->movie->state() != QMovie::NotRunning);
433 }
434 if ((d->movie->state() == QMovie::Paused) != d->paused) {
435 d->paused = (d->movie->state() == QMovie::Paused);
437 }
438}
439
440void QQuickAnimatedImage::onCacheChanged()
441{
443 if (!cache()) {
444 d->clearCache();
445 if (d->movie)
446 d->movie->setCacheMode(QMovie::CacheNone);
447 } else {
448 if (d->movie)
449 d->movie->setCacheMode(QMovie::CacheAll);
450 }
451}
452
454{
455 QQuickItem::componentComplete(); // NOT QQuickImage
456 load();
457}
458
460{
461 if (movie == m)
462 return;
463
465 const int oldFrameCount = q->frameCount();
466
467 if (movie) {
468 movie->disconnect();
470 }
471
472 movie = m;
473 clearCache();
474
475 if (movie)
477
478 if (oldFrameCount != q->frameCount())
479 emit q->frameCountChanged();
480}
481
483
484#include "moc_qquickanimatedimage_p.cpp"
\inmodule QtGui
Definition qimage.h:37
iterator insert(const Key &key, const T &value)
Definition qmap.h:687
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:356
bool contains(const Key &key) const
Definition qmap.h:340
void clear()
Definition qmap.h:288
\inmodule QtGui
Definition qmovie.h:28
QImage currentImage() const
Returns the current frame as a QImage.
Definition qmovie.cpp:751
int currentFrameNumber() const
Returns the sequence number of the current frame.
Definition qmovie.cpp:818
@ Paused
Definition qmovie.h:36
@ NotRunning
Definition qmovie.h:35
@ CacheAll
Definition qmovie.h:42
@ CacheNone
Definition qmovie.h:41
QSize scaledSize()
Definition qmovie.cpp:963
QString fileName() const
Returns the name of the file that QMovie reads image data from.
Definition qmovie.cpp:654
void stateChanged(QMovie::MovieState state)
This signal is emitted every time the state of the movie changes.
void frameChanged(int frameNumber)
void setScaledSize(const QSize &size)
Definition qmovie.cpp:976
void finished()
This signal is emitted when the reply has finished processing.
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
void setAttribute(Attribute code, const QVariant &value)
Sets the attribute associated with code code to be value value.
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3099
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
static QString urlToLocalFileOrQrc(const QString &)
If url is a local file returns a path suitable for passing to QFile.
Definition qqmlfile.cpp:643
QQuickPixmap * infoForCurrentFrame(QQmlEngine *engine)
QMap< int, QQuickPixmap * > frameMap
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
void setSource(const QUrl &) override
bool isPlaying() const
\qmlproperty bool QtQuick::AnimatedImage::playing This property holds whether the animated image is p...
void setCurrentFrame(int frame) override
QQuickAnimatedImage(QQuickItem *parent=nullptr)
\qmltype AnimatedImage \instantiates QQuickAnimatedImage \inqmlmodule QtQuick \inherits Image
bool isPaused() const
\qmlproperty bool QtQuick::AnimatedImage::paused This property holds whether the animated image is pa...
void sourceSizeChanged()
static void resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio)
void sourceChanged(const QUrl &)
The QQuickImageProviderOptions class provides options for QQuickImageProviderWithOptions image reques...
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:64
void componentComplete() override
\reimp Derived classes should call the base class method before adding their own actions to perform a...
bool isComponentComplete() const
Returns true if construction of the QML component is complete; otherwise returns false.
static bool isCached(const QUrl &url, const QRect &requestRegion, const QSize &requestSize, const int frame, const QQuickImageProviderOptions &options)
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
\inmodule QtCore
Definition qurl.h:94
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1888
void setUrl(const QString &url, ParsingMode mode=TolerantMode)
Parses url and sets this object to that value.
Definition qurl.cpp:1926
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
static void * context
#define qApp
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
const GLfloat * m
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
QQmlEngine * qmlEngine(const QObject *obj)
Definition qqml.cpp:76
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:71
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
static QUrl resolvedUrl(const QUrl &url, const QQmlRefPointer< QQmlContextData > &context)
SSL_CTX int(*) void arg)
#define emit
long long qint64
Definition qtypes.h:55
double qreal
Definition qtypes.h:92
QUrl url("example.com")
[constructor-url-reference]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
widget render & pixmap
aWidget window() -> setWindowTitle("New Window Title")
[2]
QFrame frame
[0]
char * toString(const MyType &t)
[31]
QJSEngine engine
[0]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent