1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "QtQuick1/private/qdeclarativeanimatedimage_p.h"
43 #include "QtQuick1/private/qdeclarativeanimatedimage_p_p.h"
47 #include <QtDeclarative/qdeclarativeinfo.h>
48 #include <QtDeclarative/private/qdeclarativeengine_p.h>
51 #include <QNetworkRequest>
52 #include <QNetworkReply>
59 \qmlclass AnimatedImage QDeclarative1AnimatedImage
60 \inqmlmodule QtQuick 1
63 \ingroup basic-visual-elements
65 The AnimatedImage element extends the features of the \l Image element, providing
66 a way to play animations stored as images containing a series of frames,
67 such as those stored in GIF files.
69 Information about the current frame and totla length of the animation can be
70 obtained using the \l currentFrame and \l frameCount properties. You can
71 start, pause and stop the animation by changing the values of the \l playing
72 and \l paused properties.
74 The full list of supported formats can be determined with QMovie::supportedFormats().
76 \section1 Example Usage
79 \image animatedimageitem.gif
82 The following QML shows how to display an animated image and obtain information
83 about its state, such as the current frame and total number of frames.
84 The result is an animated image with a simple progress indicator underneath it.
86 \bold Note: Unlike images, animated images are not cached or shared internally.
89 \snippet doc/src/snippets/qtquick1/animatedimage.qml document
91 \sa BorderImage, Image
95 \qmlproperty url QtQuick1::AnimatedImage::source
97 This property holds the URL that refers to the source image.
99 AnimatedImage can handle any image format supported by Qt, loaded from any
100 URL scheme supported by Qt.
102 \sa QDeclarativeImageProvider
106 \qmlproperty bool QtQuick1::AnimatedImage::asynchronous
108 Specifies that images on the local filesystem should be loaded
109 asynchronously in a separate thread. The default value is
110 false, causing the user interface thread to block while the
111 image is loaded. Setting \a asynchronous to true is useful where
112 maintaining a responsive user interface is more desirable
113 than having images immediately visible.
115 Note that this property is only valid for images read from the
116 local filesystem. Images loaded via a network resource (e.g. HTTP)
117 are always loaded asynchonously.
121 \qmlproperty bool QtQuick1::AnimatedImage::mirror
124 This property holds whether the image should be horizontally inverted
125 (effectively displaying a mirrored image).
127 The default value is false.
130 QDeclarative1AnimatedImage::QDeclarative1AnimatedImage(QDeclarativeItem *parent)
131 : QDeclarative1Image(*(new QDeclarative1AnimatedImagePrivate), parent)
135 QDeclarative1AnimatedImage::~QDeclarative1AnimatedImage()
137 Q_D(QDeclarative1AnimatedImage);
142 \qmlproperty bool QtQuick1::AnimatedImage::paused
143 This property holds whether the animated image is paused.
145 By default, this property is false. Set it to true when you want to pause
148 bool QDeclarative1AnimatedImage::isPaused() const
150 Q_D(const QDeclarative1AnimatedImage);
153 return d->_movie->state()==QMovie::Paused;
156 void QDeclarative1AnimatedImage::setPaused(bool pause)
158 Q_D(QDeclarative1AnimatedImage);
159 if(pause == d->paused)
164 d->_movie->setPaused(pause);
167 \qmlproperty bool QtQuick1::AnimatedImage::playing
168 This property holds whether the animated image is playing.
170 By default, this property is true, meaning that the animation
171 will start playing immediately.
173 bool QDeclarative1AnimatedImage::isPlaying() const
175 Q_D(const QDeclarative1AnimatedImage);
178 return d->_movie->state()!=QMovie::NotRunning;
181 void QDeclarative1AnimatedImage::setPlaying(bool play)
183 Q_D(QDeclarative1AnimatedImage);
184 if(play == d->playing)
196 \qmlproperty int QtQuick1::AnimatedImage::currentFrame
197 \qmlproperty int QtQuick1::AnimatedImage::frameCount
199 currentFrame is the frame that is currently visible. By monitoring this property
200 for changes, you can animate other items at the same time as the image.
202 frameCount is the number of frames in the animation. For some animation formats,
203 frameCount is unknown and has a value of zero.
205 int QDeclarative1AnimatedImage::currentFrame() const
207 Q_D(const QDeclarative1AnimatedImage);
209 return d->preset_currentframe;
210 return d->_movie->currentFrameNumber();
213 void QDeclarative1AnimatedImage::setCurrentFrame(int frame)
215 Q_D(QDeclarative1AnimatedImage);
217 d->preset_currentframe = frame;
220 d->_movie->jumpToFrame(frame);
223 int QDeclarative1AnimatedImage::frameCount() const
225 Q_D(const QDeclarative1AnimatedImage);
228 return d->_movie->frameCount();
231 void QDeclarative1AnimatedImage::setSource(const QUrl &url)
233 Q_D(QDeclarative1AnimatedImage);
241 d->reply->deleteLater();
246 emit sourceChanged(d->url);
248 if (isComponentComplete())
252 void QDeclarative1AnimatedImage::load()
254 Q_D(QDeclarative1AnimatedImage);
256 QDeclarative1ImageBase::Status oldStatus = d->status;
257 qreal oldProgress = d->progress;
259 if (d->url.isEmpty()) {
261 d->setPixmap(QPixmap());
264 if (d->status != oldStatus)
265 emit statusChanged(d->status);
266 if (d->progress != oldProgress)
267 emit progressChanged(d->progress);
269 #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
270 QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url);
272 //### should be unified with movieRequestFinished
273 d->_movie = new QMovie(lf);
274 if (!d->_movie->isValid()){
275 qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString();
279 if (d->status != oldStatus)
280 emit statusChanged(d->status);
283 connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
284 this, SLOT(playingStatusChanged()));
285 connect(d->_movie, SIGNAL(frameChanged(int)),
286 this, SLOT(movieUpdate()));
287 d->_movie->setCacheMode(QMovie::CacheAll);
291 d->_movie->jumpToFrame(0);
293 d->_movie->setPaused(true);
294 d->setPixmap(d->_movie->currentPixmap());
297 if (d->status != oldStatus)
298 emit statusChanged(d->status);
299 if (d->progress != oldProgress)
300 emit progressChanged(d->progress);
306 emit statusChanged(d->status);
307 emit progressChanged(d->progress);
308 QNetworkRequest req(d->url);
309 req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
310 d->reply = qmlEngine(this)->networkAccessManager()->get(req);
311 QObject::connect(d->reply, SIGNAL(finished()),
312 this, SLOT(movieRequestFinished()));
313 QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
314 this, SLOT(requestProgress(qint64,qint64)));
318 #define ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION 16
320 void QDeclarative1AnimatedImage::movieRequestFinished()
322 Q_D(QDeclarative1AnimatedImage);
325 if (d->redirectCount < ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION) {
326 QVariant redirect = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
327 if (redirect.isValid()) {
328 QUrl url = d->reply->url().resolved(redirect.toUrl());
329 d->reply->deleteLater();
337 d->_movie = new QMovie(d->reply);
338 if (!d->_movie->isValid()){
339 #ifndef QT_NO_DEBUG_STREAM
340 qmlInfo(this) << "Error Reading Animated Image File " << d->url;
345 emit statusChanged(d->status);
348 connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
349 this, SLOT(playingStatusChanged()));
350 connect(d->_movie, SIGNAL(frameChanged(int)),
351 this, SLOT(movieUpdate()));
352 d->_movie->setCacheMode(QMovie::CacheAll);
355 if (d->paused || !d->playing) {
356 d->_movie->jumpToFrame(d->preset_currentframe);
357 d->preset_currentframe = 0;
360 d->_movie->setPaused(true);
361 d->setPixmap(d->_movie->currentPixmap());
363 emit statusChanged(d->status);
366 void QDeclarative1AnimatedImage::movieUpdate()
368 Q_D(QDeclarative1AnimatedImage);
369 d->setPixmap(d->_movie->currentPixmap());
373 void QDeclarative1AnimatedImage::playingStatusChanged()
375 Q_D(QDeclarative1AnimatedImage);
376 if((d->_movie->state() != QMovie::NotRunning) != d->playing){
377 d->playing = (d->_movie->state() != QMovie::NotRunning);
378 emit playingChanged();
380 if((d->_movie->state() == QMovie::Paused) != d->paused){
381 d->playing = (d->_movie->state() == QMovie::Paused);
382 emit pausedChanged();
386 void QDeclarative1AnimatedImage::componentComplete()
388 Q_D(QDeclarative1AnimatedImage);
389 QDeclarativeItem::componentComplete(); // NOT QDeclarative1Image
390 if (d->url.isValid())
393 setCurrentFrame(d->preset_currentframe);
394 d->preset_currentframe = 0;
402 #endif // QT_NO_MOVIE