8#include <QtGui/qguiapplication.h>
9#include <QtQml/qqmlinfo.h>
10#include <QtQml/qqmlfile.h>
11#include <QtQml/qqmlengine.h>
12#include <QtGui/qmovie.h>
13#if QT_CONFIG(qml_network)
14#include <QtNetwork/qnetworkrequest.h>
15#include <QtNetwork/qnetworkreply.h>
20QQuickPixmap* QQuickAnimatedImagePrivate::infoForCurrentFrame(QQmlEngine *engine)
25 int current = movie->currentFrameNumber();
26 if (!frameMap.contains(current)) {
28 QQuickPixmap *pixmap =
nullptr;
29 if (engine && !movie->fileName().isEmpty()) {
30 requestedUrl.setUrl(QString::fromUtf8(
"quickanimatedimage://%1#%2x%3#%4")
31 .arg(movie->fileName())
32 .arg(movie->scaledSize().width())
33 .arg(movie->scaledSize().height())
36 if (!requestedUrl.isEmpty()) {
37 if (QQuickPixmap::isCached(requestedUrl, QRect(), QSize(), 0, QQuickImageProviderOptions()))
38 pixmap =
new QQuickPixmap(engine, requestedUrl);
40 pixmap =
new QQuickPixmap(requestedUrl, movie->currentImage());
42 pixmap =
new QQuickPixmap;
43 pixmap->setImage(movie->currentImage());
45 frameMap.insert(current, pixmap);
48 return frameMap.value(current);
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
101
102
103
104
105
106
107
108
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130QQuickAnimatedImage::QQuickAnimatedImage(QQuickItem *parent)
131 : QQuickImage(*(
new QQuickAnimatedImagePrivate), parent)
133 connect(
this, &QQuickImageBase::cacheChanged,
this, &QQuickAnimatedImage::onCacheChanged);
134 connect(
this, &QQuickImageBase::currentFrameChanged,
this, &QQuickAnimatedImage::frameChanged);
135 connect(
this, &QQuickImageBase::currentFrameChanged,
this, &QQuickAnimatedImage::currentFrameChanged);
136 connect(
this, &QQuickImageBase::frameCountChanged,
this, &QQuickAnimatedImage::frameCountChanged);
139QQuickAnimatedImage::~QQuickAnimatedImage()
141 Q_D(QQuickAnimatedImage);
142#if QT_CONFIG(qml_network)
144 d->reply->deleteLater();
151
152
153
154
155
156
158bool QQuickAnimatedImage::isPaused()
const
160 Q_D(
const QQuickAnimatedImage);
163 return d->movie->state()==QMovie::Paused;
166void QQuickAnimatedImage::setPaused(
bool pause)
168 Q_D(QQuickAnimatedImage);
169 if (pause == d->paused)
173 emit pausedChanged();
175 d->movie->setPaused(pause);
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
197bool QQuickAnimatedImage::isPlaying()
const
199 Q_D(
const QQuickAnimatedImage);
202 return d->movie->state()!=QMovie::NotRunning;
205void QQuickAnimatedImage::setPlaying(
bool play)
207 Q_D(QQuickAnimatedImage);
208 if (play == d->playing)
212 emit playingChanged();
222
223
224
225
226
227
228
229
230
231int QQuickAnimatedImage::currentFrame()
const
233 Q_D(
const QQuickAnimatedImage);
235 return d->presetCurrentFrame;
236 return d->movie->currentFrameNumber();
239void QQuickAnimatedImage::setCurrentFrame(
int frame)
241 Q_D(QQuickAnimatedImage);
243 d->presetCurrentFrame = frame;
246 d->movie->jumpToFrame(frame);
249int QQuickAnimatedImage::frameCount()
const
251 Q_D(
const QQuickAnimatedImage);
254 return d->movie->frameCount();
258
259
260
261
262
263
264
265
266qreal QQuickAnimatedImage::speed()
const
268 Q_D(
const QQuickAnimatedImage);
272void QQuickAnimatedImage::setSpeed(qreal speed)
274 Q_D(QQuickAnimatedImage);
275 if (d->speed != speed) {
278 d->movie->setSpeed(qRound(speed * 100.0));
283void QQuickAnimatedImage::setSource(
const QUrl &url)
285 Q_D(QQuickAnimatedImage);
289#if QT_CONFIG(qml_network)
291 d->reply->deleteLater();
296 d->setImage(QImage());
297 d->oldPlaying = isPlaying();
298 d->setMovie(
nullptr);
300 emit sourceChanged(d->url);
302 if (isComponentComplete())
306void QQuickAnimatedImage::load()
308 Q_D(QQuickAnimatedImage);
310 if (d->url.isEmpty()) {
313 d->setImage(QImage());
314 if (sourceSize() != d->oldSourceSize) {
315 d->oldSourceSize = sourceSize();
316 emit sourceSizeChanged();
320 if (isPlaying() != d->oldPlaying)
321 emit playingChanged();
323 const qreal targetDevicePixelRatio = d->effectiveDevicePixelRatio();
324 d->devicePixelRatio = 1.0;
326 const auto context = qmlContext(
this);
327 QUrl loadUrl = context ? context->resolvedUrl(d->url) : d->url;
328 const QUrl resolvedUrl = loadUrl;
329 resolve2xLocalFile(resolvedUrl, targetDevicePixelRatio, &loadUrl, &d->devicePixelRatio);
330 QString lf = QQmlFile::urlToLocalFileOrQrc(loadUrl);
335 d->setMovie(
new QMovie(lf));
336 movieRequestFinished();
338#if QT_CONFIG(qml_network)
342 d->setStatus(Loading);
344 QNetworkRequest req(d->url);
345 req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute,
true);
347 d->reply = qmlEngine(
this)->networkAccessManager()->get(req);
348 connect(d->reply, &QNetworkReply::finished,
this, &QQuickAnimatedImage::movieRequestFinished);
349 connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(requestProgress(qint64,qint64)));
355void QQuickAnimatedImage::movieRequestFinished()
357 Q_D(QQuickAnimatedImage);
359#if QT_CONFIG(qml_network)
361 auto movie =
new QMovie(d->reply);
365 d->reply->disconnect(
this);
366 d->reply->setParent(movie);
373 if (!d->movie || !d->movie->isValid()) {
374 const QQmlContext *context = qmlContext(
this);
375 qmlWarning(
this) <<
"Error Reading Animated Image File "
376 << (context ? context->resolvedUrl(d->url) : d->url).toString();
377 d->setMovie(
nullptr);
379 d->setImage(QImage());
380 if (sourceSize() != d->oldSourceSize) {
381 d->oldSourceSize = sourceSize();
382 emit sourceSizeChanged();
388 if (isPlaying() != d->oldPlaying)
389 emit playingChanged();
393 connect(d->movie, &QMovie::stateChanged,
this, &QQuickAnimatedImage::playingStatusChanged);
394 connect(d->movie, &QMovie::frameChanged,
this, &QQuickAnimatedImage::movieUpdate);
396 d->movie->setCacheMode(QMovie::CacheAll);
397 d->movie->setSpeed(qRound(d->speed * 100.0));
401 bool pausedAtStart = d->paused;
402 if (d->movie && d->playing)
404 if (d->movie && pausedAtStart)
405 d->movie->setPaused(
true);
406 if (d->movie && (d->paused || !d->playing)) {
407 d->movie->jumpToFrame(d->presetCurrentFrame);
408 d->presetCurrentFrame = 0;
411 QQuickPixmap *pixmap = d->infoForCurrentFrame(qmlEngine(
this));
413 d->setPixmap(*pixmap);
414 if (sourceSize() != d->oldSourceSize) {
415 d->oldSourceSize = sourceSize();
416 emit sourceSizeChanged();
422 if (isPlaying() != d->oldPlaying)
423 emit playingChanged();
426void QQuickAnimatedImage::movieUpdate()
428 Q_D(QQuickAnimatedImage);
434 d->setPixmap(*d->infoForCurrentFrame(qmlEngine(
this)));
435 emit QQuickImageBase::currentFrameChanged();
439void QQuickAnimatedImage::playingStatusChanged()
441 Q_D(QQuickAnimatedImage);
443 if ((d->movie->state() != QMovie::NotRunning) != d->playing) {
444 d->playing = (d->movie->state() != QMovie::NotRunning);
445 emit playingChanged();
447 if ((d->movie->state() == QMovie::Paused) != d->paused) {
448 d->paused = (d->movie->state() == QMovie::Paused);
449 emit pausedChanged();
453void QQuickAnimatedImage::onCacheChanged()
455 Q_D(QQuickAnimatedImage);
459 d->movie->setCacheMode(QMovie::CacheNone);
462 d->movie->setCacheMode(QMovie::CacheAll);
466void QQuickAnimatedImage::componentComplete()
468 QQuickItem::componentComplete();
477 Q_Q(QQuickAnimatedImage);
478 const int oldFrameCount = q->frameCount();
482 movie->deleteLater();
489 movie->setScaledSize(sourcesize);
491 if (oldFrameCount != q->frameCount())
492 emit q->frameCountChanged();
497#include "moc_qquickanimatedimage_p.cpp"
void setMovie(QMovie *movie)