src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
       
     8 **
       
     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
       
    14 ** this package.
       
    15 **
       
    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.
       
    23 **
       
    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.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "private/qdeclarativeanimatedimage_p.h"
       
    43 #include "private/qdeclarativeanimatedimage_p_p.h"
       
    44 
       
    45 #ifndef QT_NO_MOVIE
       
    46 
       
    47 #include <qdeclarativeinfo.h>
       
    48 #include <private/qdeclarativeengine_p.h>
       
    49 
       
    50 #include <QMovie>
       
    51 #include <QNetworkRequest>
       
    52 #include <QNetworkReply>
       
    53 
       
    54 QT_BEGIN_NAMESPACE
       
    55 
       
    56 /*!
       
    57     \class QDeclarativeAnimatedImage
       
    58     \internal
       
    59 */
       
    60 
       
    61 /*!
       
    62     \qmlclass AnimatedImage QDeclarativeAnimatedImage
       
    63     \inherits Image
       
    64     \since 4.7
       
    65 
       
    66     This item provides for playing animations stored as images containing a series of frames,
       
    67     such as GIF files. The full list of supported formats can be determined with
       
    68     QMovie::supportedFormats().
       
    69 
       
    70     \table
       
    71     \row
       
    72     \o \image animatedimageitem.gif
       
    73     \o
       
    74     \qml
       
    75 Item {
       
    76     width: anim.width; height: anim.height+8
       
    77     AnimatedImage { id: anim; source: "pics/games-anim.gif" }
       
    78     Rectangle { color: "red"; width: 4; height: 8; y: anim.height
       
    79         x: (anim.width-width)*anim.currentFrame/(anim.frameCount-1)
       
    80     }
       
    81 }
       
    82     \endqml
       
    83     \endtable
       
    84 */
       
    85 
       
    86 QDeclarativeAnimatedImage::QDeclarativeAnimatedImage(QDeclarativeItem *parent)
       
    87     : QDeclarativeImage(*(new QDeclarativeAnimatedImagePrivate), parent)
       
    88 {
       
    89 }
       
    90 
       
    91 QDeclarativeAnimatedImage::~QDeclarativeAnimatedImage()
       
    92 {
       
    93     Q_D(QDeclarativeAnimatedImage);
       
    94     delete d->_movie;
       
    95 }
       
    96 
       
    97 /*!
       
    98   \qmlproperty bool AnimatedImage::paused
       
    99   This property holds whether the animated image is paused or not
       
   100 
       
   101   Defaults to false, and can be set to true when you want to pause.
       
   102 */
       
   103 bool QDeclarativeAnimatedImage::isPaused() const
       
   104 {
       
   105     Q_D(const QDeclarativeAnimatedImage);
       
   106     if(!d->_movie)
       
   107         return false;
       
   108     return d->_movie->state()==QMovie::Paused;
       
   109 }
       
   110 
       
   111 void QDeclarativeAnimatedImage::setPaused(bool pause)
       
   112 {
       
   113     Q_D(QDeclarativeAnimatedImage);
       
   114     if(pause == d->paused)
       
   115         return;
       
   116     d->paused = pause;
       
   117     if(!d->_movie)
       
   118         return;
       
   119     d->_movie->setPaused(pause);
       
   120 }
       
   121 /*!
       
   122   \qmlproperty bool AnimatedImage::playing
       
   123   This property holds whether the animated image is playing or not
       
   124 
       
   125   Defaults to true, so as to start playing immediately.
       
   126 */
       
   127 bool QDeclarativeAnimatedImage::isPlaying() const
       
   128 {
       
   129     Q_D(const QDeclarativeAnimatedImage);
       
   130     if (!d->_movie)
       
   131         return false;
       
   132     return d->_movie->state()!=QMovie::NotRunning;
       
   133 }
       
   134 
       
   135 void QDeclarativeAnimatedImage::setPlaying(bool play)
       
   136 {
       
   137     Q_D(QDeclarativeAnimatedImage);
       
   138     if(play == d->playing)
       
   139         return;
       
   140     d->playing = play;
       
   141     if (!d->_movie)
       
   142         return;
       
   143     if (play)
       
   144         d->_movie->start();
       
   145     else
       
   146         d->_movie->stop();
       
   147 }
       
   148 
       
   149 /*!
       
   150   \qmlproperty int AnimatedImage::currentFrame
       
   151   \qmlproperty int AnimatedImage::frameCount
       
   152 
       
   153   currentFrame is the frame that is currently visible. Watching when this changes can
       
   154   allow other things to animate at the same time as the image. frameCount is the number
       
   155   of frames in the animation. For some animation formats, frameCount is unknown and set to zero.
       
   156 */
       
   157 int QDeclarativeAnimatedImage::currentFrame() const
       
   158 {
       
   159     Q_D(const QDeclarativeAnimatedImage);
       
   160     if (!d->_movie)
       
   161         return d->preset_currentframe;
       
   162     return d->_movie->currentFrameNumber();
       
   163 }
       
   164 
       
   165 void QDeclarativeAnimatedImage::setCurrentFrame(int frame)
       
   166 {
       
   167     Q_D(QDeclarativeAnimatedImage);
       
   168     if (!d->_movie) {
       
   169         d->preset_currentframe = frame;
       
   170         return;
       
   171     }
       
   172     d->_movie->jumpToFrame(frame);
       
   173 }
       
   174 
       
   175 int QDeclarativeAnimatedImage::frameCount() const
       
   176 {
       
   177     Q_D(const QDeclarativeAnimatedImage);
       
   178     if (!d->_movie)
       
   179         return 0;
       
   180     return d->_movie->frameCount();
       
   181 }
       
   182 
       
   183 void QDeclarativeAnimatedImage::setSource(const QUrl &url)
       
   184 {
       
   185     Q_D(QDeclarativeAnimatedImage);
       
   186     if (url == d->url)
       
   187         return;
       
   188 
       
   189     delete d->_movie;
       
   190     d->_movie = 0;
       
   191 
       
   192     if (d->reply) {
       
   193         d->reply->deleteLater();
       
   194         d->reply = 0;
       
   195     }
       
   196 
       
   197     d->url = url;
       
   198 
       
   199     if (url.isEmpty()) {
       
   200         delete d->_movie;
       
   201         d->status = Null;
       
   202     } else {
       
   203 #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
       
   204         QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
       
   205         if (!lf.isEmpty()) {
       
   206             //### should be unified with movieRequestFinished
       
   207             d->_movie = new QMovie(lf);
       
   208             if (!d->_movie->isValid()){
       
   209                 qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString();
       
   210                 delete d->_movie;
       
   211                 d->_movie = 0;
       
   212                 return;
       
   213             }
       
   214             connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
       
   215                     this, SLOT(playingStatusChanged()));
       
   216             connect(d->_movie, SIGNAL(frameChanged(int)),
       
   217                     this, SLOT(movieUpdate()));
       
   218             d->_movie->setCacheMode(QMovie::CacheAll);
       
   219             if(d->playing)
       
   220                 d->_movie->start();
       
   221             else
       
   222                 d->_movie->jumpToFrame(0);
       
   223             if(d->paused)
       
   224                 d->_movie->setPaused(true);
       
   225             d->setPixmap(d->_movie->currentPixmap());
       
   226             d->status = Ready;
       
   227             d->progress = 1.0;
       
   228             emit statusChanged(d->status);
       
   229             emit sourceChanged(d->url);
       
   230             emit progressChanged(d->progress);
       
   231             return;
       
   232         }
       
   233 #endif
       
   234         d->status = Loading;
       
   235         QNetworkRequest req(d->url);
       
   236         req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
       
   237         d->reply = qmlEngine(this)->networkAccessManager()->get(req);
       
   238         QObject::connect(d->reply, SIGNAL(finished()),
       
   239                          this, SLOT(movieRequestFinished()));
       
   240     }
       
   241 
       
   242     emit statusChanged(d->status);
       
   243 }
       
   244 
       
   245 #define ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION 16
       
   246 
       
   247 void QDeclarativeAnimatedImage::movieRequestFinished()
       
   248 {
       
   249     Q_D(QDeclarativeAnimatedImage);
       
   250 
       
   251     d->redirectCount++;
       
   252     if (d->redirectCount < ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION) {
       
   253         QVariant redirect = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
       
   254         if (redirect.isValid()) {
       
   255             QUrl url = d->reply->url().resolved(redirect.toUrl());
       
   256             d->reply->deleteLater();
       
   257             d->reply = 0;
       
   258             setSource(url);
       
   259             return;
       
   260         }
       
   261     }
       
   262     d->redirectCount=0;
       
   263 
       
   264     d->_movie = new QMovie(d->reply);
       
   265     if (!d->_movie->isValid()){
       
   266         qmlInfo(this) << "Error Reading Animated Image File " << d->url;
       
   267         delete d->_movie;
       
   268         d->_movie = 0;
       
   269         return;
       
   270     }
       
   271     connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
       
   272             this, SLOT(playingStatusChanged()));
       
   273     connect(d->_movie, SIGNAL(frameChanged(int)),
       
   274             this, SLOT(movieUpdate()));
       
   275     d->_movie->setCacheMode(QMovie::CacheAll);
       
   276     if(d->playing)
       
   277         d->_movie->start();
       
   278     if (d->paused || !d->playing) {
       
   279         d->_movie->jumpToFrame(d->preset_currentframe);
       
   280         d->preset_currentframe = 0;
       
   281     }
       
   282     if(d->paused)
       
   283         d->_movie->setPaused(true);
       
   284     d->setPixmap(d->_movie->currentPixmap());
       
   285 }
       
   286 
       
   287 void QDeclarativeAnimatedImage::movieUpdate()
       
   288 {
       
   289     Q_D(QDeclarativeAnimatedImage);
       
   290     d->setPixmap(d->_movie->currentPixmap());
       
   291     emit frameChanged();
       
   292 }
       
   293 
       
   294 void QDeclarativeAnimatedImage::playingStatusChanged()
       
   295 {
       
   296     Q_D(QDeclarativeAnimatedImage);
       
   297     if((d->_movie->state() != QMovie::NotRunning) != d->playing){
       
   298         d->playing = (d->_movie->state() != QMovie::NotRunning);
       
   299         emit playingChanged();
       
   300     }
       
   301     if((d->_movie->state() == QMovie::Paused) != d->paused){
       
   302         d->playing = (d->_movie->state() == QMovie::Paused);
       
   303         emit pausedChanged();
       
   304     }
       
   305 }
       
   306 
       
   307 void QDeclarativeAnimatedImage::componentComplete()
       
   308 {
       
   309     Q_D(QDeclarativeAnimatedImage);
       
   310     QDeclarativeItem::componentComplete(); // NOT QDeclarativeImage
       
   311     if (!d->reply) {
       
   312         setCurrentFrame(d->preset_currentframe);
       
   313         d->preset_currentframe = 0;
       
   314     }
       
   315 }
       
   316 
       
   317 QT_END_NAMESPACE
       
   318 
       
   319 #endif // QT_NO_MOVIE