1 /****************************************************************************
3 ** Copyright (C) 2011 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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "private/qdeclarativeanimatedimage_p.h"
43 #include "private/qdeclarativeanimatedimage_p_p.h"
47 #include <qdeclarativeinfo.h>
48 #include <private/qdeclarativeengine_p.h>
51 #include <QNetworkRequest>
52 #include <QNetworkReply>
57 \qmlclass AnimatedImage QDeclarativeAnimatedImage
60 \ingroup basic-visual-elements
62 The AnimatedImage element extends the features of the \l Image element, providing
63 a way to play animations stored as images containing a series of frames,
64 such as those stored in GIF files.
66 Information about the current frame and totla length of the animation can be
67 obtained using the \l currentFrame and \l frameCount properties. You can
68 start, pause and stop the animation by changing the values of the \l playing
69 and \l paused properties.
71 The full list of supported formats can be determined with QMovie::supportedFormats().
73 \section1 Example Usage
76 \image animatedimageitem.gif
79 The following QML shows how to display an animated image and obtain information
80 about its state, such as the current frame and total number of frames.
81 The result is an animated image with a simple progress indicator underneath it.
84 \snippet doc/src/snippets/declarative/animatedimage.qml document
86 \sa BorderImage, Image
90 \qmlproperty bool AnimatedImage::cache
93 Specifies whether the image should be cached. The default value is
94 true. Setting \a cache to false is useful when dealing with large images,
95 to make sure that they aren't cached at the expense of small 'ui element' images.
99 \qmlproperty bool AnimatedImage::mirror
102 This property holds whether the image should be horizontally inverted
103 (effectively displaying a mirrored image).
105 The default value is false.
108 QDeclarativeAnimatedImage::QDeclarativeAnimatedImage(QDeclarativeItem *parent)
109 : QDeclarativeImage(*(new QDeclarativeAnimatedImagePrivate), parent)
113 QDeclarativeAnimatedImage::~QDeclarativeAnimatedImage()
115 Q_D(QDeclarativeAnimatedImage);
120 \qmlproperty bool AnimatedImage::paused
121 This property holds whether the animated image is paused.
123 By default, this property is false. Set it to true when you want to pause
126 bool QDeclarativeAnimatedImage::isPaused() const
128 Q_D(const QDeclarativeAnimatedImage);
131 return d->_movie->state()==QMovie::Paused;
134 void QDeclarativeAnimatedImage::setPaused(bool pause)
136 Q_D(QDeclarativeAnimatedImage);
137 if(pause == d->paused)
142 d->_movie->setPaused(pause);
145 \qmlproperty bool AnimatedImage::playing
146 This property holds whether the animated image is playing.
148 By default, this property is true, meaning that the animation
149 will start playing immediately.
151 bool QDeclarativeAnimatedImage::isPlaying() const
153 Q_D(const QDeclarativeAnimatedImage);
156 return d->_movie->state()!=QMovie::NotRunning;
159 void QDeclarativeAnimatedImage::setPlaying(bool play)
161 Q_D(QDeclarativeAnimatedImage);
162 if(play == d->playing)
174 \qmlproperty int AnimatedImage::currentFrame
175 \qmlproperty int AnimatedImage::frameCount
177 currentFrame is the frame that is currently visible. By monitoring this property
178 for changes, you can animate other items at the same time as the image.
180 frameCount is the number of frames in the animation. For some animation formats,
181 frameCount is unknown and has a value of zero.
183 int QDeclarativeAnimatedImage::currentFrame() const
185 Q_D(const QDeclarativeAnimatedImage);
187 return d->preset_currentframe;
188 return d->_movie->currentFrameNumber();
191 void QDeclarativeAnimatedImage::setCurrentFrame(int frame)
193 Q_D(QDeclarativeAnimatedImage);
195 d->preset_currentframe = frame;
198 d->_movie->jumpToFrame(frame);
201 int QDeclarativeAnimatedImage::frameCount() const
203 Q_D(const QDeclarativeAnimatedImage);
206 return d->_movie->frameCount();
209 void QDeclarativeAnimatedImage::setSource(const QUrl &url)
211 Q_D(QDeclarativeAnimatedImage);
219 d->reply->deleteLater();
224 emit sourceChanged(d->url);
226 if (isComponentComplete())
230 void QDeclarativeAnimatedImage::load()
232 Q_D(QDeclarativeAnimatedImage);
234 QDeclarativeImageBase::Status oldStatus = d->status;
235 qreal oldProgress = d->progress;
237 if (d->url.isEmpty()) {
239 d->setPixmap(QPixmap());
242 if (d->status != oldStatus)
243 emit statusChanged(d->status);
244 if (d->progress != oldProgress)
245 emit progressChanged(d->progress);
247 #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
248 QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url);
250 //### should be unified with movieRequestFinished
251 d->_movie = new QMovie(lf);
252 if (!d->_movie->isValid()){
253 qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString();
257 if (d->status != oldStatus)
258 emit statusChanged(d->status);
261 connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
262 this, SLOT(playingStatusChanged()));
263 connect(d->_movie, SIGNAL(frameChanged(int)),
264 this, SLOT(movieUpdate()));
265 d->_movie->setCacheMode(QMovie::CacheAll);
269 d->_movie->jumpToFrame(0);
271 d->_movie->setPaused(true);
272 d->setPixmap(d->_movie->currentPixmap());
275 if (d->status != oldStatus)
276 emit statusChanged(d->status);
277 if (d->progress != oldProgress)
278 emit progressChanged(d->progress);
284 emit statusChanged(d->status);
285 emit progressChanged(d->progress);
286 QNetworkRequest req(d->url);
287 req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
288 d->reply = qmlEngine(this)->networkAccessManager()->get(req);
289 QObject::connect(d->reply, SIGNAL(finished()),
290 this, SLOT(movieRequestFinished()));
291 QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
292 this, SLOT(requestProgress(qint64,qint64)));
296 #define ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION 16
298 void QDeclarativeAnimatedImage::movieRequestFinished()
300 Q_D(QDeclarativeAnimatedImage);
303 if (d->redirectCount < ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION) {
304 QVariant redirect = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
305 if (redirect.isValid()) {
306 QUrl url = d->reply->url().resolved(redirect.toUrl());
307 d->reply->deleteLater();
315 d->_movie = new QMovie(d->reply);
316 if (!d->_movie->isValid()){
317 #ifndef QT_NO_DEBUG_STREAM
318 qmlInfo(this) << "Error Reading Animated Image File " << d->url;
323 emit statusChanged(d->status);
326 connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
327 this, SLOT(playingStatusChanged()));
328 connect(d->_movie, SIGNAL(frameChanged(int)),
329 this, SLOT(movieUpdate()));
330 d->_movie->setCacheMode(QMovie::CacheAll);
333 if (d->paused || !d->playing) {
334 d->_movie->jumpToFrame(d->preset_currentframe);
335 d->preset_currentframe = 0;
338 d->_movie->setPaused(true);
339 d->setPixmap(d->_movie->currentPixmap());
341 emit statusChanged(d->status);
344 void QDeclarativeAnimatedImage::movieUpdate()
346 Q_D(QDeclarativeAnimatedImage);
347 d->setPixmap(d->_movie->currentPixmap());
351 void QDeclarativeAnimatedImage::playingStatusChanged()
353 Q_D(QDeclarativeAnimatedImage);
354 if((d->_movie->state() != QMovie::NotRunning) != d->playing){
355 d->playing = (d->_movie->state() != QMovie::NotRunning);
356 emit playingChanged();
358 if((d->_movie->state() == QMovie::Paused) != d->paused){
359 d->playing = (d->_movie->state() == QMovie::Paused);
360 emit pausedChanged();
364 void QDeclarativeAnimatedImage::componentComplete()
366 Q_D(QDeclarativeAnimatedImage);
367 QDeclarativeItem::componentComplete(); // NOT QDeclarativeImage
368 if (d->url.isValid())
371 setCurrentFrame(d->preset_currentframe);
372 d->preset_currentframe = 0;
378 #endif // QT_NO_MOVIE