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 "qsganimatedimage_p.h"
43 #include "qsganimatedimage_p_p.h"
47 #include <QtDeclarative/qdeclarativeinfo.h>
48 #include <QtGui/qmovie.h>
49 #include <QtNetwork/qnetworkrequest.h>
50 #include <QtNetwork/qnetworkreply.h>
52 #include <private/qdeclarativeengine_p.h>
56 QSGAnimatedImage::QSGAnimatedImage(QSGItem *parent)
57 : QSGImage(*(new QSGAnimatedImagePrivate), parent)
61 QSGAnimatedImage::~QSGAnimatedImage()
63 Q_D(QSGAnimatedImage);
67 bool QSGAnimatedImage::isPaused() const
69 Q_D(const QSGAnimatedImage);
72 return d->_movie->state()==QMovie::Paused;
75 void QSGAnimatedImage::setPaused(bool pause)
77 Q_D(QSGAnimatedImage);
78 if(pause == d->paused)
83 d->_movie->setPaused(pause);
86 bool QSGAnimatedImage::isPlaying() const
88 Q_D(const QSGAnimatedImage);
91 return d->_movie->state()!=QMovie::NotRunning;
94 void QSGAnimatedImage::setPlaying(bool play)
96 Q_D(QSGAnimatedImage);
97 if(play == d->playing)
108 int QSGAnimatedImage::currentFrame() const
110 Q_D(const QSGAnimatedImage);
112 return d->preset_currentframe;
113 return d->_movie->currentFrameNumber();
116 void QSGAnimatedImage::setCurrentFrame(int frame)
118 Q_D(QSGAnimatedImage);
120 d->preset_currentframe = frame;
123 d->_movie->jumpToFrame(frame);
126 int QSGAnimatedImage::frameCount() const
128 Q_D(const QSGAnimatedImage);
131 return d->_movie->frameCount();
134 void QSGAnimatedImage::setSource(const QUrl &url)
136 Q_D(QSGAnimatedImage);
144 d->reply->deleteLater();
149 emit sourceChanged(d->url);
151 if (isComponentComplete())
155 void QSGAnimatedImage::load()
157 Q_D(QSGAnimatedImage);
159 QSGImageBase::Status oldStatus = d->status;
160 qreal oldProgress = d->progress;
162 if (d->url.isEmpty()) {
164 d->setPixmap(QPixmap());
167 if (d->status != oldStatus)
168 emit statusChanged(d->status);
169 if (d->progress != oldProgress)
170 emit progressChanged(d->progress);
172 #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
173 QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url);
175 //### should be unified with movieRequestFinished
176 d->_movie = new QMovie(lf);
177 if (!d->_movie->isValid()){
178 qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString();
182 if (d->status != oldStatus)
183 emit statusChanged(d->status);
186 connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
187 this, SLOT(playingStatusChanged()));
188 connect(d->_movie, SIGNAL(frameChanged(int)),
189 this, SLOT(movieUpdate()));
190 d->_movie->setCacheMode(QMovie::CacheAll);
194 d->_movie->jumpToFrame(0);
196 d->_movie->setPaused(true);
197 d->setPixmap(d->_movie->currentPixmap());
200 if (d->status != oldStatus)
201 emit statusChanged(d->status);
202 if (d->progress != oldProgress)
203 emit progressChanged(d->progress);
209 emit statusChanged(d->status);
210 emit progressChanged(d->progress);
211 QNetworkRequest req(d->url);
212 req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
213 d->reply = qmlEngine(this)->networkAccessManager()->get(req);
214 QObject::connect(d->reply, SIGNAL(finished()),
215 this, SLOT(movieRequestFinished()));
216 QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
217 this, SLOT(requestProgress(qint64,qint64)));
221 #define ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION 16
223 void QSGAnimatedImage::movieRequestFinished()
225 Q_D(QSGAnimatedImage);
228 if (d->redirectCount < ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION) {
229 QVariant redirect = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
230 if (redirect.isValid()) {
231 QUrl url = d->reply->url().resolved(redirect.toUrl());
232 d->reply->deleteLater();
240 d->_movie = new QMovie(d->reply);
241 if (!d->_movie->isValid()){
242 #ifndef QT_NO_DEBUG_STREAM
243 qmlInfo(this) << "Error Reading Animated Image File " << d->url;
248 emit statusChanged(d->status);
251 connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
252 this, SLOT(playingStatusChanged()));
253 connect(d->_movie, SIGNAL(frameChanged(int)),
254 this, SLOT(movieUpdate()));
255 d->_movie->setCacheMode(QMovie::CacheAll);
258 if (d->paused || !d->playing) {
259 d->_movie->jumpToFrame(d->preset_currentframe);
260 d->preset_currentframe = 0;
263 d->_movie->setPaused(true);
264 d->setPixmap(d->_movie->currentPixmap());
266 emit statusChanged(d->status);
269 void QSGAnimatedImage::movieUpdate()
271 Q_D(QSGAnimatedImage);
272 d->setPixmap(d->_movie->currentPixmap());
276 void QSGAnimatedImage::playingStatusChanged()
278 Q_D(QSGAnimatedImage);
279 if((d->_movie->state() != QMovie::NotRunning) != d->playing){
280 d->playing = (d->_movie->state() != QMovie::NotRunning);
281 emit playingChanged();
283 if((d->_movie->state() == QMovie::Paused) != d->paused){
284 d->playing = (d->_movie->state() == QMovie::Paused);
285 emit pausedChanged();
289 void QSGAnimatedImage::componentComplete()
291 Q_D(QSGAnimatedImage);
292 QSGItem::componentComplete(); // NOT QSGImage
293 if (d->url.isValid())
296 setCurrentFrame(d->preset_currentframe);
297 d->preset_currentframe = 0;
303 #endif // QT_NO_MOVIE