| 1 | /****************************************************************************
|
|---|
| 2 | ** $Id: qmovie.cpp 2 2005-11-16 15:49:26Z dmik $
|
|---|
| 3 | **
|
|---|
| 4 | ** Implementation of movie classes
|
|---|
| 5 | **
|
|---|
| 6 | ** Created : 970617
|
|---|
| 7 | **
|
|---|
| 8 | ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
|
|---|
| 9 | **
|
|---|
| 10 | ** This file is part of the kernel module of the Qt GUI Toolkit.
|
|---|
| 11 | **
|
|---|
| 12 | ** This file may be distributed under the terms of the Q Public License
|
|---|
| 13 | ** as defined by Trolltech AS of Norway and appearing in the file
|
|---|
| 14 | ** LICENSE.QPL included in the packaging of this file.
|
|---|
| 15 | **
|
|---|
| 16 | ** This file may be distributed and/or modified under the terms of the
|
|---|
| 17 | ** GNU General Public License version 2 as published by the Free Software
|
|---|
| 18 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
|---|
| 19 | ** packaging of this file.
|
|---|
| 20 | **
|
|---|
| 21 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
|---|
| 22 | ** licenses may use this file in accordance with the Qt Commercial License
|
|---|
| 23 | ** Agreement provided with the Software.
|
|---|
| 24 | **
|
|---|
| 25 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|---|
| 26 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|---|
| 27 | **
|
|---|
| 28 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
|---|
| 29 | ** information about Qt Commercial License Agreements.
|
|---|
| 30 | ** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
|---|
| 31 | ** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
|---|
| 32 | **
|
|---|
| 33 | ** Contact info@trolltech.com if any conditions of this licensing are
|
|---|
| 34 | ** not clear to you.
|
|---|
| 35 | **
|
|---|
| 36 | **********************************************************************/
|
|---|
| 37 |
|
|---|
| 38 | // #define QT_SAVE_MOVIE_HACK
|
|---|
| 39 |
|
|---|
| 40 | #include "qtimer.h"
|
|---|
| 41 | #include "qpainter.h"
|
|---|
| 42 | #include "qptrlist.h"
|
|---|
| 43 | #include "qbitmap.h"
|
|---|
| 44 | #include "qmovie.h"
|
|---|
| 45 | #include "qfile.h"
|
|---|
| 46 | #include "qbuffer.h"
|
|---|
| 47 | #include "qobject.h"
|
|---|
| 48 | #include "qpixmapcache.h"
|
|---|
| 49 |
|
|---|
| 50 | #ifndef QT_NO_MOVIE
|
|---|
| 51 |
|
|---|
| 52 | #ifdef Q_WS_QWS
|
|---|
| 53 | #include "qgfx_qws.h"
|
|---|
| 54 | #endif
|
|---|
| 55 |
|
|---|
| 56 | #include "qasyncio.h"
|
|---|
| 57 | #include "qasyncimageio.h"
|
|---|
| 58 |
|
|---|
| 59 | #include <stdlib.h>
|
|---|
| 60 |
|
|---|
| 61 | /*!
|
|---|
| 62 | \class QMovie qmovie.h
|
|---|
| 63 | \brief The QMovie class provides incremental loading of animations or images, signalling as it progresses.
|
|---|
| 64 |
|
|---|
| 65 | \ingroup images
|
|---|
| 66 | \ingroup graphics
|
|---|
| 67 | \ingroup multimedia
|
|---|
| 68 | \mainclass
|
|---|
| 69 |
|
|---|
| 70 | The simplest way to display a QMovie is to use a QLabel and
|
|---|
| 71 | QLabel::setMovie().
|
|---|
| 72 |
|
|---|
| 73 | A QMovie provides a QPixmap as the framePixmap(); connections can
|
|---|
| 74 | be made via connectResize() and connectUpdate() to receive
|
|---|
| 75 | notification of size and pixmap changes. All decoding is driven
|
|---|
| 76 | by the normal event-processing mechanisms.
|
|---|
| 77 |
|
|---|
| 78 | The movie begins playing as soon as the QMovie is created
|
|---|
| 79 | (actually, once control returns to the event loop). When the last
|
|---|
| 80 | frame in the movie has been played, it may loop back to the start
|
|---|
| 81 | if such looping is defined in the input source.
|
|---|
| 82 |
|
|---|
| 83 | QMovie objects are explicitly shared. This means that a QMovie
|
|---|
| 84 | copied from another QMovie will be displaying the same frame at
|
|---|
| 85 | all times. If one shared movie pauses, all pause. To make \e
|
|---|
| 86 | independent movies, they must be constructed separately.
|
|---|
| 87 |
|
|---|
| 88 | The set of data formats supported by QMovie is determined by the
|
|---|
| 89 | decoder factories that have been installed; the format of the
|
|---|
| 90 | input is determined as the input is decoded.
|
|---|
| 91 |
|
|---|
| 92 | The supported formats are MNG (if Qt is configured with MNG
|
|---|
| 93 | support enabled) and GIF (if Qt is configured with GIF support
|
|---|
| 94 | enabled, see qgif.h).
|
|---|
| 95 |
|
|---|
| 96 | If Qt is configured to support GIF reading, we are required to
|
|---|
| 97 | state that "The Graphics Interchange Format(c) is the Copyright
|
|---|
| 98 | property of CompuServe Incorporated. GIF(sm) is a Service Mark
|
|---|
| 99 | property of CompuServe Incorporated.
|
|---|
| 100 |
|
|---|
| 101 | \warning If you are in a country that recognizes software patents
|
|---|
| 102 | and in which Unisys holds a patent on LZW compression and/or
|
|---|
| 103 | decompression and you want to use GIF, Unisys may require you to
|
|---|
| 104 | license that technology. Such countries include Canada, Japan,
|
|---|
| 105 | the USA, France, Germany, Italy and the UK.
|
|---|
| 106 |
|
|---|
| 107 | GIF support may be removed completely in a future version of Qt.
|
|---|
| 108 | We recommend using the MNG or PNG format.
|
|---|
| 109 |
|
|---|
| 110 | \img qmovie.png QMovie
|
|---|
| 111 |
|
|---|
| 112 | \sa QLabel::setMovie()
|
|---|
| 113 | */
|
|---|
| 114 |
|
|---|
| 115 | /*!
|
|---|
| 116 | \enum QMovie::Status
|
|---|
| 117 |
|
|---|
| 118 | \value SourceEmpty
|
|---|
| 119 | \value UnrecognizedFormat
|
|---|
| 120 | \value Paused
|
|---|
| 121 | \value EndOfFrame
|
|---|
| 122 | \value EndOfLoop
|
|---|
| 123 | \value EndOfMovie
|
|---|
| 124 | \value SpeedChanged
|
|---|
| 125 | */
|
|---|
| 126 |
|
|---|
| 127 | class QMoviePrivate : public QObject, public QShared,
|
|---|
| 128 | private QDataSink, private QImageConsumer
|
|---|
| 129 | {
|
|---|
| 130 | Q_OBJECT
|
|---|
| 131 |
|
|---|
| 132 | public: // for QMovie
|
|---|
| 133 |
|
|---|
| 134 | // Creates a null Private
|
|---|
| 135 | QMoviePrivate();
|
|---|
| 136 |
|
|---|
| 137 | // NOTE: The ownership of the QDataSource is transferred to the Private
|
|---|
| 138 | QMoviePrivate(QDataSource* src, QMovie* movie, int bufsize);
|
|---|
| 139 |
|
|---|
| 140 | virtual ~QMoviePrivate();
|
|---|
| 141 |
|
|---|
| 142 | bool isNull() const;
|
|---|
| 143 |
|
|---|
| 144 | // Initialize, possibly to the null state
|
|---|
| 145 | void init(bool fully);
|
|---|
| 146 | void flushBuffer();
|
|---|
| 147 | void updatePixmapFromImage();
|
|---|
| 148 | void updatePixmapFromImage(const QPoint& off, const QRect& area);
|
|---|
| 149 | void showChanges();
|
|---|
| 150 |
|
|---|
| 151 | // This as QImageConsumer
|
|---|
| 152 | void changed(const QRect& rect);
|
|---|
| 153 | void end();
|
|---|
| 154 | void preFrameDone(); //util func
|
|---|
| 155 | void frameDone();
|
|---|
| 156 | void frameDone(const QPoint&, const QRect& rect);
|
|---|
| 157 | void restartTimer();
|
|---|
| 158 | void setLooping(int l);
|
|---|
| 159 | void setFramePeriod(int milliseconds);
|
|---|
| 160 | void setSize(int w, int h);
|
|---|
| 161 |
|
|---|
| 162 | // This as QDataSink
|
|---|
| 163 | int readyToReceive();
|
|---|
| 164 | void receive(const uchar* b, int bytecount);
|
|---|
| 165 | void eof();
|
|---|
| 166 | void pause();
|
|---|
| 167 |
|
|---|
| 168 | signals:
|
|---|
| 169 | void sizeChanged(const QSize&);
|
|---|
| 170 | void areaChanged(const QRect&);
|
|---|
| 171 | void dataStatus(int);
|
|---|
| 172 |
|
|---|
| 173 | public slots:
|
|---|
| 174 | void refresh();
|
|---|
| 175 |
|
|---|
| 176 | public:
|
|---|
| 177 | QMovie *that;
|
|---|
| 178 | QWidget * display_widget;
|
|---|
| 179 |
|
|---|
| 180 | QImageDecoder *decoder;
|
|---|
| 181 |
|
|---|
| 182 | // Cyclic buffer
|
|---|
| 183 | int buf_size;
|
|---|
| 184 | uchar *buffer;
|
|---|
| 185 | int buf_r, buf_w, buf_usage;
|
|---|
| 186 |
|
|---|
| 187 | int framenumber;
|
|---|
| 188 | int frameperiod;
|
|---|
| 189 | int speed;
|
|---|
| 190 | QTimer *frametimer;
|
|---|
| 191 | int lasttimerinterval;
|
|---|
| 192 | int loop;
|
|---|
| 193 | bool movie_ended;
|
|---|
| 194 | bool dirty_cache;
|
|---|
| 195 | bool waitingForFrameTick;
|
|---|
| 196 | int stepping;
|
|---|
| 197 | QRect changed_area;
|
|---|
| 198 | QRect valid_area;
|
|---|
| 199 | QDataPump *pump;
|
|---|
| 200 | QDataSource *source;
|
|---|
| 201 | QPixmap mypixmap;
|
|---|
| 202 | QBitmap mymask;
|
|---|
| 203 | QColor bg;
|
|---|
| 204 |
|
|---|
| 205 | int error;
|
|---|
| 206 | bool empty;
|
|---|
| 207 |
|
|---|
| 208 | #ifdef QT_SAVE_MOVIE_HACK
|
|---|
| 209 | bool save_image;
|
|---|
| 210 | int image_number;
|
|---|
| 211 | #endif
|
|---|
| 212 | };
|
|---|
| 213 |
|
|---|
| 214 |
|
|---|
| 215 | QMoviePrivate::QMoviePrivate()
|
|---|
| 216 | {
|
|---|
| 217 | dirty_cache = FALSE;
|
|---|
| 218 | buffer = 0;
|
|---|
| 219 | pump = 0;
|
|---|
| 220 | source = 0;
|
|---|
| 221 | decoder = 0;
|
|---|
| 222 | display_widget=0;
|
|---|
| 223 | buf_size = 0;
|
|---|
| 224 | init(FALSE);
|
|---|
| 225 | }
|
|---|
| 226 |
|
|---|
| 227 | // NOTE: The ownership of the QDataSource is transferred to the Private
|
|---|
| 228 | QMoviePrivate::QMoviePrivate(QDataSource* src, QMovie* movie, int bufsize) :
|
|---|
| 229 | that(movie),
|
|---|
| 230 | buf_size(bufsize)
|
|---|
| 231 | {
|
|---|
| 232 | frametimer = new QTimer(this);
|
|---|
| 233 | pump = src ? new QDataPump(src, this) : 0;
|
|---|
| 234 | QObject::connect(frametimer, SIGNAL(timeout()), this, SLOT(refresh()));
|
|---|
| 235 | dirty_cache = FALSE;
|
|---|
| 236 | source = src;
|
|---|
| 237 | buffer = 0;
|
|---|
| 238 | decoder = 0;
|
|---|
| 239 | speed = 100;
|
|---|
| 240 | display_widget=0;
|
|---|
| 241 | init(TRUE);
|
|---|
| 242 | }
|
|---|
| 243 |
|
|---|
| 244 | QMoviePrivate::~QMoviePrivate()
|
|---|
| 245 | {
|
|---|
| 246 | if ( buffer ) // Avoid purify complaint
|
|---|
| 247 | delete [] buffer;
|
|---|
| 248 | delete pump;
|
|---|
| 249 | delete decoder;
|
|---|
| 250 | delete source;
|
|---|
| 251 |
|
|---|
| 252 | // Too bad.. but better be safe than sorry
|
|---|
| 253 | if ( dirty_cache )
|
|---|
| 254 | QPixmapCache::clear();
|
|---|
| 255 | }
|
|---|
| 256 |
|
|---|
| 257 | bool QMoviePrivate::isNull() const
|
|---|
| 258 | {
|
|---|
| 259 | return !buf_size;
|
|---|
| 260 | }
|
|---|
| 261 |
|
|---|
| 262 | // Initialize. Only actually allocate any space if \a fully is TRUE,
|
|---|
| 263 | // otherwise, just enough to be a valid null Private.
|
|---|
| 264 | void QMoviePrivate::init(bool fully)
|
|---|
| 265 | {
|
|---|
| 266 | #ifdef QT_SAVE_MOVIE_HACK
|
|---|
| 267 | save_image = TRUE;
|
|---|
| 268 | image_number = 0;
|
|---|
| 269 | #endif
|
|---|
| 270 |
|
|---|
| 271 | buf_usage = buf_r = buf_w = 0;
|
|---|
| 272 | if ( buffer ) // Avoid purify complaint
|
|---|
| 273 | delete [] buffer;
|
|---|
| 274 | buffer = fully ? new uchar[buf_size] : 0;
|
|---|
| 275 | if ( buffer )
|
|---|
| 276 | memset( buffer, 0, buf_size );
|
|---|
| 277 |
|
|---|
| 278 | delete decoder;
|
|---|
| 279 | decoder = fully ? new QImageDecoder(this) : 0;
|
|---|
| 280 |
|
|---|
| 281 | #ifdef AVOID_OPEN_FDS
|
|---|
| 282 | if ( source && !source->isOpen() )
|
|---|
| 283 | source->open(IO_ReadOnly);
|
|---|
| 284 | #endif
|
|---|
| 285 |
|
|---|
| 286 | waitingForFrameTick = FALSE;
|
|---|
| 287 | stepping = -1;
|
|---|
| 288 | framenumber = 0;
|
|---|
| 289 | frameperiod = -1;
|
|---|
| 290 | if (fully) frametimer->stop();
|
|---|
| 291 | lasttimerinterval = -1;
|
|---|
| 292 | changed_area.setRect(0,0,-1,-1);
|
|---|
| 293 | valid_area = changed_area;
|
|---|
| 294 | loop = -1;
|
|---|
| 295 | movie_ended = FALSE;
|
|---|
| 296 | error = 0;
|
|---|
| 297 | empty = TRUE;
|
|---|
| 298 | }
|
|---|
| 299 |
|
|---|
| 300 | void QMoviePrivate::flushBuffer()
|
|---|
| 301 | {
|
|---|
| 302 | int used;
|
|---|
| 303 | while (buf_usage && !waitingForFrameTick && stepping != 0 && !error) {
|
|---|
| 304 | used = decoder->decode(buffer + buf_r, QMIN(buf_usage, buf_size - buf_r));
|
|---|
| 305 | if (used <= 0) {
|
|---|
| 306 | if ( used < 0 ) {
|
|---|
| 307 | error = 1;
|
|---|
| 308 | emit dataStatus(QMovie::UnrecognizedFormat);
|
|---|
| 309 | }
|
|---|
| 310 | break;
|
|---|
| 311 | }
|
|---|
| 312 | buf_r = (buf_r + used) % buf_size;
|
|---|
| 313 | buf_usage -= used;
|
|---|
| 314 | }
|
|---|
| 315 |
|
|---|
| 316 | // Some formats, like MNG, can make stuff happen without any extra data.
|
|---|
| 317 | // Only do this if the movie hasn't ended, however or we'll never get the end of loop signal.
|
|---|
| 318 | if (!movie_ended) {
|
|---|
| 319 | used = decoder->decode(buffer + buf_r, 0);
|
|---|
| 320 | if (used <= 0) {
|
|---|
| 321 | if ( used < 0 ) {
|
|---|
| 322 | error = 1;
|
|---|
| 323 | emit dataStatus(QMovie::UnrecognizedFormat);
|
|---|
| 324 | }
|
|---|
| 325 | }
|
|---|
| 326 | }
|
|---|
| 327 |
|
|---|
| 328 | if (error)
|
|---|
| 329 | frametimer->stop();
|
|---|
| 330 | maybeReady();
|
|---|
| 331 | }
|
|---|
| 332 |
|
|---|
| 333 | void QMoviePrivate::updatePixmapFromImage()
|
|---|
| 334 | {
|
|---|
| 335 | if (changed_area.isEmpty()) return;
|
|---|
| 336 | updatePixmapFromImage(QPoint(0,0),changed_area);
|
|---|
| 337 | }
|
|---|
| 338 |
|
|---|
| 339 | void QMoviePrivate::updatePixmapFromImage(const QPoint& off,
|
|---|
| 340 | const QRect& area)
|
|---|
| 341 | {
|
|---|
| 342 | // Create temporary QImage to hold the part we want
|
|---|
| 343 | const QImage& gimg = decoder->image();
|
|---|
| 344 | QImage img = gimg.copy(area);
|
|---|
| 345 |
|
|---|
| 346 | #ifdef QT_SAVE_MOVIE_HACK
|
|---|
| 347 | if ( save_image ) {
|
|---|
| 348 | QString name;
|
|---|
| 349 | name.sprintf("movie%i.ppm",image_number++);
|
|---|
| 350 | gimg.save( name, "PPM" );
|
|---|
| 351 | }
|
|---|
| 352 | #endif
|
|---|
| 353 |
|
|---|
| 354 | // Resize to size of image
|
|---|
| 355 | if (mypixmap.width() != gimg.width() || mypixmap.height() != gimg.height())
|
|---|
| 356 | mypixmap.resize(gimg.width(), gimg.height());
|
|---|
| 357 |
|
|---|
| 358 | // Convert to pixmap and paste that onto myself
|
|---|
| 359 | QPixmap lines;
|
|---|
| 360 |
|
|---|
| 361 | #ifndef QT_NO_SPRINTF
|
|---|
| 362 | if (!(frameperiod < 0 && loop == -1)) {
|
|---|
| 363 | // its an animation, lets see if we converted
|
|---|
| 364 | // this frame already.
|
|---|
| 365 | QString key;
|
|---|
| 366 | key.sprintf( "%08lx:%04d", ( long )this, framenumber );
|
|---|
| 367 | if ( !QPixmapCache::find( key, lines ) ) {
|
|---|
| 368 | lines.convertFromImage(img, Qt::ColorOnly);
|
|---|
| 369 | QPixmapCache::insert( key, lines );
|
|---|
| 370 | dirty_cache = TRUE;
|
|---|
| 371 | }
|
|---|
| 372 | } else
|
|---|
| 373 | #endif
|
|---|
| 374 | {
|
|---|
| 375 | lines.convertFromImage(img, Qt::ColorOnly);
|
|---|
| 376 | }
|
|---|
| 377 |
|
|---|
| 378 | if (bg.isValid()) {
|
|---|
| 379 | QPainter p;
|
|---|
| 380 | p.begin(&mypixmap);
|
|---|
| 381 | p.fillRect(area, bg);
|
|---|
| 382 | p.drawPixmap(area, lines);
|
|---|
| 383 | p.end();
|
|---|
| 384 | } else {
|
|---|
| 385 | if (gimg.hasAlphaBuffer()) {
|
|---|
| 386 | // Resize to size of image
|
|---|
| 387 | if (mymask.isNull()) {
|
|---|
| 388 | mymask.resize(gimg.width(), gimg.height());
|
|---|
| 389 | mymask.fill( Qt::color1 );
|
|---|
| 390 | }
|
|---|
| 391 | }
|
|---|
| 392 | mypixmap.setMask(QBitmap()); // Remove reference to my mask
|
|---|
| 393 | copyBlt( &mypixmap, area.left(), area.top(),
|
|---|
| 394 | &lines, off.x(), off.y(), area.width(), area.height() );
|
|---|
| 395 | }
|
|---|
| 396 |
|
|---|
| 397 | #ifdef Q_WS_QWS
|
|---|
| 398 | if(display_widget) {
|
|---|
| 399 | QGfx * mygfx=display_widget->graphicsContext();
|
|---|
| 400 | if(mygfx) {
|
|---|
| 401 | double xscale,yscale;
|
|---|
| 402 | xscale=display_widget->width();
|
|---|
| 403 | yscale=display_widget->height();
|
|---|
| 404 | xscale=xscale/((double)mypixmap.width());
|
|---|
| 405 | yscale=yscale/((double)mypixmap.height());
|
|---|
| 406 | double xh,yh;
|
|---|
| 407 | xh=xscale*((double)area.left());
|
|---|
| 408 | yh=yscale*((double)area.top());
|
|---|
| 409 | mygfx->setSource(&mypixmap);
|
|---|
| 410 | mygfx->setAlphaType(QGfx::IgnoreAlpha);
|
|---|
| 411 | mygfx->stretchBlt(0,0,display_widget->width(),
|
|---|
| 412 | display_widget->height(),mypixmap.width(),
|
|---|
| 413 | mypixmap.height());
|
|---|
| 414 | delete mygfx;
|
|---|
| 415 | }
|
|---|
| 416 | }
|
|---|
| 417 | #endif
|
|---|
| 418 | }
|
|---|
| 419 |
|
|---|
| 420 | void QMoviePrivate::showChanges()
|
|---|
| 421 | {
|
|---|
| 422 | if (changed_area.isValid()) {
|
|---|
| 423 | updatePixmapFromImage();
|
|---|
| 424 |
|
|---|
| 425 | valid_area = valid_area.unite(changed_area);
|
|---|
| 426 | emit areaChanged(changed_area);
|
|---|
| 427 |
|
|---|
| 428 | changed_area.setWidth(-1); // make empty
|
|---|
| 429 | }
|
|---|
| 430 | }
|
|---|
| 431 |
|
|---|
| 432 | // Private as QImageConsumer
|
|---|
| 433 | void QMoviePrivate::changed(const QRect& rect)
|
|---|
| 434 | {
|
|---|
| 435 | if (!frametimer->isActive())
|
|---|
| 436 | frametimer->start(0);
|
|---|
| 437 | changed_area = changed_area.unite(rect);
|
|---|
| 438 | }
|
|---|
| 439 |
|
|---|
| 440 | void QMoviePrivate::end()
|
|---|
| 441 | {
|
|---|
| 442 | movie_ended = TRUE;
|
|---|
| 443 | }
|
|---|
| 444 |
|
|---|
| 445 | void QMoviePrivate::preFrameDone()
|
|---|
| 446 | {
|
|---|
| 447 | if (stepping > 0) {
|
|---|
| 448 | stepping--;
|
|---|
| 449 | if (!stepping) {
|
|---|
| 450 | frametimer->stop();
|
|---|
| 451 | emit dataStatus( QMovie::Paused );
|
|---|
| 452 | }
|
|---|
| 453 | } else {
|
|---|
| 454 | waitingForFrameTick = TRUE;
|
|---|
| 455 | restartTimer();
|
|---|
| 456 | }
|
|---|
| 457 | }
|
|---|
| 458 | void QMoviePrivate::frameDone()
|
|---|
| 459 | {
|
|---|
| 460 | preFrameDone();
|
|---|
| 461 | showChanges();
|
|---|
| 462 | emit dataStatus(QMovie::EndOfFrame);
|
|---|
| 463 | framenumber++;
|
|---|
| 464 | }
|
|---|
| 465 | void QMoviePrivate::frameDone(const QPoint& p,
|
|---|
| 466 | const QRect& rect)
|
|---|
| 467 | {
|
|---|
| 468 | preFrameDone();
|
|---|
| 469 | const QImage& gimg = decoder->image();
|
|---|
| 470 | if (framenumber==0)
|
|---|
| 471 | emit sizeChanged(gimg.size());
|
|---|
| 472 | valid_area = valid_area.unite(QRect(p,rect.size()));
|
|---|
| 473 | updatePixmapFromImage(p,rect);
|
|---|
| 474 | emit areaChanged(QRect(p,rect.size()));
|
|---|
| 475 | emit dataStatus(QMovie::EndOfFrame);
|
|---|
| 476 | framenumber++;
|
|---|
| 477 | }
|
|---|
| 478 |
|
|---|
| 479 | void QMoviePrivate::restartTimer()
|
|---|
| 480 | {
|
|---|
| 481 | if (speed > 0) {
|
|---|
| 482 | int i = frameperiod >= 0 ? frameperiod * 100/speed : 0;
|
|---|
| 483 | if ( i != lasttimerinterval || !frametimer->isActive() ) {
|
|---|
| 484 | lasttimerinterval = i;
|
|---|
| 485 | frametimer->start( i );
|
|---|
| 486 | }
|
|---|
| 487 | } else {
|
|---|
| 488 | frametimer->stop();
|
|---|
| 489 | }
|
|---|
| 490 | }
|
|---|
| 491 |
|
|---|
| 492 | void QMoviePrivate::setLooping(int nloops)
|
|---|
| 493 | {
|
|---|
| 494 | if (loop == -1) { // Only if we don't already know how many loops!
|
|---|
| 495 | if (source && source->rewindable()) {
|
|---|
| 496 | source->enableRewind(TRUE);
|
|---|
| 497 | loop = nloops;
|
|---|
| 498 | } else {
|
|---|
| 499 | // Cannot loop from this source
|
|---|
| 500 | loop = -2;
|
|---|
| 501 | }
|
|---|
| 502 | }
|
|---|
| 503 | }
|
|---|
| 504 |
|
|---|
| 505 | void QMoviePrivate::setFramePeriod(int milliseconds)
|
|---|
| 506 | {
|
|---|
| 507 | // Animation: only show complete frame
|
|---|
| 508 | frameperiod = milliseconds;
|
|---|
| 509 | if (stepping<0 && frameperiod >= 0) restartTimer();
|
|---|
| 510 | }
|
|---|
| 511 |
|
|---|
| 512 | void QMoviePrivate::setSize(int w, int h)
|
|---|
| 513 | {
|
|---|
| 514 | if (mypixmap.width() != w || mypixmap.height() != h) {
|
|---|
| 515 | mypixmap.resize(w, h);
|
|---|
| 516 | emit sizeChanged(QSize(w, h));
|
|---|
| 517 | }
|
|---|
| 518 | }
|
|---|
| 519 |
|
|---|
| 520 |
|
|---|
| 521 | // Private as QDataSink
|
|---|
| 522 |
|
|---|
| 523 | int QMoviePrivate::readyToReceive()
|
|---|
| 524 | {
|
|---|
| 525 | // Could pre-fill buffer, but more efficient to just leave the
|
|---|
| 526 | // data back at the source.
|
|---|
| 527 | return (waitingForFrameTick || !stepping || buf_usage || error)
|
|---|
| 528 | ? 0 : buf_size;
|
|---|
| 529 | }
|
|---|
| 530 |
|
|---|
| 531 | void QMoviePrivate::receive(const uchar* b, int bytecount)
|
|---|
| 532 | {
|
|---|
| 533 | if ( bytecount ) empty = FALSE;
|
|---|
| 534 |
|
|---|
| 535 | while (bytecount && !waitingForFrameTick && stepping != 0) {
|
|---|
| 536 | int used = decoder->decode(b, bytecount);
|
|---|
| 537 | if (used<=0) {
|
|---|
| 538 | if ( used < 0 ) {
|
|---|
| 539 | error = 1;
|
|---|
| 540 | emit dataStatus(QMovie::UnrecognizedFormat);
|
|---|
| 541 | }
|
|---|
| 542 | break;
|
|---|
| 543 | }
|
|---|
| 544 | b+=used;
|
|---|
| 545 | bytecount-=used;
|
|---|
| 546 | }
|
|---|
| 547 |
|
|---|
| 548 | // Append unused to buffer
|
|---|
| 549 | while (bytecount--) {
|
|---|
| 550 | buffer[buf_w] = *b++;
|
|---|
| 551 | buf_w = (buf_w+1)%buf_size;
|
|---|
| 552 | buf_usage++;
|
|---|
| 553 | }
|
|---|
| 554 | }
|
|---|
| 555 |
|
|---|
| 556 | void QMoviePrivate::eof()
|
|---|
| 557 | {
|
|---|
| 558 | if ( !movie_ended )
|
|---|
| 559 | return;
|
|---|
| 560 |
|
|---|
| 561 | if ( empty )
|
|---|
| 562 | emit dataStatus(QMovie::SourceEmpty);
|
|---|
| 563 |
|
|---|
| 564 | #ifdef QT_SAVE_MOVIE_HACK
|
|---|
| 565 | save_image = FALSE;
|
|---|
| 566 | #endif
|
|---|
| 567 |
|
|---|
| 568 | emit dataStatus(QMovie::EndOfLoop);
|
|---|
| 569 |
|
|---|
| 570 | if (loop >= 0) {
|
|---|
| 571 | if (loop) {
|
|---|
| 572 | loop--;
|
|---|
| 573 | if (!loop) return;
|
|---|
| 574 | }
|
|---|
| 575 | delete decoder;
|
|---|
| 576 | decoder = new QImageDecoder(this);
|
|---|
| 577 | source->rewind();
|
|---|
| 578 | framenumber = 0;
|
|---|
| 579 | movie_ended = FALSE;
|
|---|
| 580 | } else {
|
|---|
| 581 | delete decoder;
|
|---|
| 582 | decoder = 0;
|
|---|
| 583 | if ( buffer ) // Avoid purify complaint
|
|---|
| 584 | delete [] buffer;
|
|---|
| 585 | buffer = 0;
|
|---|
| 586 | emit dataStatus(QMovie::EndOfMovie);
|
|---|
| 587 | #ifdef AVOID_OPEN_FDS
|
|---|
| 588 | if ( source )
|
|---|
| 589 | source->close();
|
|---|
| 590 | #endif
|
|---|
| 591 | }
|
|---|
| 592 | }
|
|---|
| 593 |
|
|---|
| 594 | void QMoviePrivate::pause()
|
|---|
| 595 | {
|
|---|
| 596 | if ( stepping ) {
|
|---|
| 597 | stepping = 0;
|
|---|
| 598 | frametimer->stop();
|
|---|
| 599 | emit dataStatus( QMovie::Paused );
|
|---|
| 600 | }
|
|---|
| 601 | }
|
|---|
| 602 |
|
|---|
| 603 | void QMoviePrivate::refresh()
|
|---|
| 604 | {
|
|---|
| 605 | if (!decoder) {
|
|---|
| 606 | frametimer->stop();
|
|---|
| 607 | return;
|
|---|
| 608 | }
|
|---|
| 609 |
|
|---|
| 610 | if (frameperiod < 0 && loop == -1) {
|
|---|
| 611 | // Only show changes if probably not an animation
|
|---|
| 612 | showChanges();
|
|---|
| 613 | }
|
|---|
| 614 |
|
|---|
| 615 | if (!buf_usage) {
|
|---|
| 616 | frametimer->stop();
|
|---|
| 617 | }
|
|---|
| 618 |
|
|---|
| 619 | waitingForFrameTick = FALSE;
|
|---|
| 620 | flushBuffer();
|
|---|
| 621 | }
|
|---|
| 622 |
|
|---|
| 623 | ///////////////// End of Private /////////////////
|
|---|
| 624 |
|
|---|
| 625 |
|
|---|
| 626 |
|
|---|
| 627 |
|
|---|
| 628 |
|
|---|
| 629 | /*!
|
|---|
| 630 | Constructs a null QMovie. The only interesting thing to do with
|
|---|
| 631 | such a movie is to assign another movie to it.
|
|---|
| 632 |
|
|---|
| 633 | \sa isNull()
|
|---|
| 634 | */
|
|---|
| 635 | QMovie::QMovie()
|
|---|
| 636 | {
|
|---|
| 637 | d = new QMoviePrivate();
|
|---|
| 638 | }
|
|---|
| 639 |
|
|---|
| 640 | /*!
|
|---|
| 641 | Constructs a QMovie with an external data source. You should later
|
|---|
| 642 | call pushData() to send incoming animation data to the movie.
|
|---|
| 643 |
|
|---|
| 644 | The \a bufsize argument sets the maximum amount of data the movie
|
|---|
| 645 | will transfer from the data source per event loop. The lower this
|
|---|
| 646 | value, the better interleaved the movie playback will be with
|
|---|
| 647 | other event processing, but the slower the overall processing will
|
|---|
| 648 | be.
|
|---|
| 649 |
|
|---|
| 650 | \sa pushData()
|
|---|
| 651 | */
|
|---|
| 652 | QMovie::QMovie(int bufsize)
|
|---|
| 653 | {
|
|---|
| 654 | d = new QMoviePrivate(0, this, bufsize);
|
|---|
| 655 | }
|
|---|
| 656 |
|
|---|
| 657 | /*!
|
|---|
| 658 | Returns the maximum amount of data that can currently be pushed
|
|---|
| 659 | into the movie by a call to pushData(). This is affected by the
|
|---|
| 660 | initial buffer size, but varies as the movie plays and data is
|
|---|
| 661 | consumed.
|
|---|
| 662 | */
|
|---|
| 663 | int QMovie::pushSpace() const
|
|---|
| 664 | {
|
|---|
| 665 | return d->readyToReceive();
|
|---|
| 666 | }
|
|---|
| 667 |
|
|---|
| 668 | /*!
|
|---|
| 669 | Pushes \a length bytes from \a data into the movie. \a length must
|
|---|
| 670 | be no more than the amount returned by pushSpace() since the
|
|---|
| 671 | previous call to pushData().
|
|---|
| 672 | */
|
|---|
| 673 | void QMovie::pushData(const uchar* data, int length)
|
|---|
| 674 | {
|
|---|
| 675 | d->receive(data,length);
|
|---|
| 676 | }
|
|---|
| 677 |
|
|---|
| 678 | #ifdef Q_WS_QWS // ##### Temporary performance experiment
|
|---|
| 679 | /*!
|
|---|
| 680 | \internal
|
|---|
| 681 | */
|
|---|
| 682 | void QMovie::setDisplayWidget(QWidget * w)
|
|---|
| 683 | {
|
|---|
| 684 | d->display_widget=w;
|
|---|
| 685 | }
|
|---|
| 686 | #endif
|
|---|
| 687 |
|
|---|
| 688 | /*!
|
|---|
| 689 | Constructs a QMovie that reads an image sequence from the given
|
|---|
| 690 | data source, \a src. The source must be allocated dynamically,
|
|---|
| 691 | because QMovie will take ownership of it and will destroy it when
|
|---|
| 692 | the movie is destroyed. The movie starts playing as soon as event
|
|---|
| 693 | processing continues.
|
|---|
| 694 |
|
|---|
| 695 | The \a bufsize argument sets the maximum amount of data the movie
|
|---|
| 696 | will transfer from the data source per event loop. The lower this
|
|---|
| 697 | value, the better interleaved the movie playback will be with
|
|---|
| 698 | other event processing, but the slower the overall processing will
|
|---|
| 699 | be.
|
|---|
| 700 | */
|
|---|
| 701 | QMovie::QMovie(QDataSource* src, int bufsize)
|
|---|
| 702 | {
|
|---|
| 703 | d = new QMoviePrivate(src, this, bufsize);
|
|---|
| 704 | }
|
|---|
| 705 |
|
|---|
| 706 | /*!
|
|---|
| 707 | Constructs a QMovie that reads an image sequence from the file, \a
|
|---|
| 708 | fileName.
|
|---|
| 709 |
|
|---|
| 710 | The \a bufsize argument sets the maximum amount of data the movie
|
|---|
| 711 | will transfer from the data source per event loop. The lower this
|
|---|
| 712 | value, the better interleaved the movie playback will be with
|
|---|
| 713 | other event processing, but the slower the overall processing will
|
|---|
| 714 | be.
|
|---|
| 715 | */
|
|---|
| 716 | QMovie::QMovie(const QString &fileName, int bufsize)
|
|---|
| 717 | {
|
|---|
| 718 | QFile* file = new QFile(fileName);
|
|---|
| 719 | if ( !fileName.isEmpty() )
|
|---|
| 720 | file->open(IO_ReadOnly);
|
|---|
| 721 | d = new QMoviePrivate(new QIODeviceSource(file, bufsize), this, bufsize);
|
|---|
| 722 | }
|
|---|
| 723 |
|
|---|
| 724 | /*!
|
|---|
| 725 | Constructs a QMovie that reads an image sequence from the byte
|
|---|
| 726 | array, \a data.
|
|---|
| 727 |
|
|---|
| 728 | The \a bufsize argument sets the maximum amount of data the movie
|
|---|
| 729 | will transfer from the data source per event loop. The lower this
|
|---|
| 730 | value, the better interleaved the movie playback will be with
|
|---|
| 731 | other event processing, but the slower the overall processing will
|
|---|
| 732 | be.
|
|---|
| 733 | */
|
|---|
| 734 | QMovie::QMovie(QByteArray data, int bufsize)
|
|---|
| 735 | {
|
|---|
| 736 | QBuffer* buffer = new QBuffer(data);
|
|---|
| 737 | buffer->open(IO_ReadOnly);
|
|---|
| 738 | d = new QMoviePrivate(new QIODeviceSource(buffer, bufsize), this, bufsize);
|
|---|
| 739 | }
|
|---|
| 740 |
|
|---|
| 741 | /*!
|
|---|
| 742 | Constructs a movie that uses the same data as movie \a movie.
|
|---|
| 743 | QMovies use explicit sharing, so operations on the copy will
|
|---|
| 744 | affect both.
|
|---|
| 745 | */
|
|---|
| 746 | QMovie::QMovie(const QMovie& movie)
|
|---|
| 747 | {
|
|---|
| 748 | d = movie.d;
|
|---|
| 749 | d->ref();
|
|---|
| 750 | }
|
|---|
| 751 |
|
|---|
| 752 | /*!
|
|---|
| 753 | Destroys the QMovie. If this is the last reference to the data of
|
|---|
| 754 | the movie, the data is deallocated.
|
|---|
| 755 | */
|
|---|
| 756 | QMovie::~QMovie()
|
|---|
| 757 | {
|
|---|
| 758 | if (d->deref()) delete d;
|
|---|
| 759 | }
|
|---|
| 760 |
|
|---|
| 761 | /*!
|
|---|
| 762 | Returns TRUE if the movie is null; otherwise returns FALSE.
|
|---|
| 763 | */
|
|---|
| 764 | bool QMovie::isNull() const
|
|---|
| 765 | {
|
|---|
| 766 | return d->isNull();
|
|---|
| 767 | }
|
|---|
| 768 |
|
|---|
| 769 | /*!
|
|---|
| 770 | Makes this movie use the same data as movie \a movie. QMovies use
|
|---|
| 771 | explicit sharing.
|
|---|
| 772 | */
|
|---|
| 773 | QMovie& QMovie::operator=(const QMovie& movie)
|
|---|
| 774 | {
|
|---|
| 775 | movie.d->ref();
|
|---|
| 776 | if (d->deref()) delete d;
|
|---|
| 777 | d = movie.d;
|
|---|
| 778 | return *this;
|
|---|
| 779 | }
|
|---|
| 780 |
|
|---|
| 781 |
|
|---|
| 782 | /*!
|
|---|
| 783 | Sets the background color of the pixmap to \a c. If the background
|
|---|
| 784 | color isValid(), the pixmap will never have a mask because the
|
|---|
| 785 | background color will be used in transparent regions of the image.
|
|---|
| 786 |
|
|---|
| 787 | \sa backgroundColor()
|
|---|
| 788 | */
|
|---|
| 789 | void QMovie::setBackgroundColor(const QColor& c)
|
|---|
| 790 | {
|
|---|
| 791 | d->bg = c;
|
|---|
| 792 | }
|
|---|
| 793 |
|
|---|
| 794 | /*!
|
|---|
| 795 | Returns the background color of the movie set by
|
|---|
| 796 | setBackgroundColor().
|
|---|
| 797 | */
|
|---|
| 798 | const QColor& QMovie::backgroundColor() const
|
|---|
| 799 | {
|
|---|
| 800 | return d->bg;
|
|---|
| 801 | }
|
|---|
| 802 |
|
|---|
| 803 | /*!
|
|---|
| 804 | Returns the area of the pixmap for which pixels have been
|
|---|
| 805 | generated.
|
|---|
| 806 | */
|
|---|
| 807 | const QRect& QMovie::getValidRect() const
|
|---|
| 808 | {
|
|---|
| 809 | return d->valid_area;
|
|---|
| 810 | }
|
|---|
| 811 |
|
|---|
| 812 | /*!
|
|---|
| 813 | Returns the current frame of the movie, as a QPixmap. It is not
|
|---|
| 814 | generally useful to keep a copy of this pixmap. It is better to
|
|---|
| 815 | keep a copy of the QMovie and get the framePixmap() only when
|
|---|
| 816 | needed for drawing.
|
|---|
| 817 |
|
|---|
| 818 | \sa frameImage()
|
|---|
| 819 | */
|
|---|
| 820 | const QPixmap& QMovie::framePixmap() const
|
|---|
| 821 | {
|
|---|
| 822 | return d->mypixmap;
|
|---|
| 823 | }
|
|---|
| 824 |
|
|---|
| 825 | /*!
|
|---|
| 826 | Returns the current frame of the movie, as a QImage. It is not
|
|---|
| 827 | generally useful to keep a copy of this image. Also note that you
|
|---|
| 828 | must not call this function if the movie is finished(), since by
|
|---|
| 829 | then the image will not be available.
|
|---|
| 830 |
|
|---|
| 831 | \sa framePixmap()
|
|---|
| 832 | */
|
|---|
| 833 | const QImage& QMovie::frameImage() const
|
|---|
| 834 | {
|
|---|
| 835 | return d->decoder->image();
|
|---|
| 836 | }
|
|---|
| 837 |
|
|---|
| 838 | /*!
|
|---|
| 839 | Returns the number of steps remaining after a call to step(). If
|
|---|
| 840 | the movie is paused, steps() returns 0. If it's running normally
|
|---|
| 841 | or is finished, steps() returns a negative number.
|
|---|
| 842 | */
|
|---|
| 843 | int QMovie::steps() const
|
|---|
| 844 | {
|
|---|
| 845 | return d->stepping;
|
|---|
| 846 | }
|
|---|
| 847 |
|
|---|
| 848 | /*!
|
|---|
| 849 | Returns the number of times EndOfFrame has been emitted since the
|
|---|
| 850 | start of the current loop of the movie. Thus, before any
|
|---|
| 851 | EndOfFrame has been emitted the value will be 0; within slots
|
|---|
| 852 | processing the first signal, frameNumber() will be 1, and so on.
|
|---|
| 853 | */
|
|---|
| 854 | int QMovie::frameNumber() const { return d->framenumber; }
|
|---|
| 855 |
|
|---|
| 856 | /*!
|
|---|
| 857 | Returns TRUE if the image is paused; otherwise returns FALSE.
|
|---|
| 858 | */
|
|---|
| 859 | bool QMovie::paused() const
|
|---|
| 860 | {
|
|---|
| 861 | return d->stepping == 0;
|
|---|
| 862 | }
|
|---|
| 863 |
|
|---|
| 864 | /*!
|
|---|
| 865 | Returns TRUE if the image is no longer playing: this happens when
|
|---|
| 866 | all loops of all frames are complete; otherwise returns FALSE.
|
|---|
| 867 | */
|
|---|
| 868 | bool QMovie::finished() const
|
|---|
| 869 | {
|
|---|
| 870 | return !d->decoder;
|
|---|
| 871 | }
|
|---|
| 872 |
|
|---|
| 873 | /*!
|
|---|
| 874 | Returns TRUE if the image is not single-stepping, not paused, and
|
|---|
| 875 | not finished; otherwise returns FALSE.
|
|---|
| 876 | */
|
|---|
| 877 | bool QMovie::running() const
|
|---|
| 878 | {
|
|---|
| 879 | return d->stepping<0 && d->decoder;
|
|---|
| 880 | }
|
|---|
| 881 |
|
|---|
| 882 | /*!
|
|---|
| 883 | Pauses the progress of the animation.
|
|---|
| 884 |
|
|---|
| 885 | \sa unpause()
|
|---|
| 886 | */
|
|---|
| 887 | void QMovie::pause()
|
|---|
| 888 | {
|
|---|
| 889 | d->pause();
|
|---|
| 890 | }
|
|---|
| 891 |
|
|---|
| 892 | /*!
|
|---|
| 893 | Unpauses the progress of the animation.
|
|---|
| 894 |
|
|---|
| 895 | \sa pause()
|
|---|
| 896 | */
|
|---|
| 897 | void QMovie::unpause()
|
|---|
| 898 | {
|
|---|
| 899 | if ( d->stepping >= 0 ) {
|
|---|
| 900 | if (d->isNull())
|
|---|
| 901 | return;
|
|---|
| 902 | d->stepping = -1;
|
|---|
| 903 | d->restartTimer();
|
|---|
| 904 | }
|
|---|
| 905 | }
|
|---|
| 906 |
|
|---|
| 907 | /*!
|
|---|
| 908 | \overload
|
|---|
| 909 |
|
|---|
| 910 | Steps forward, showing \a steps frames, and then pauses.
|
|---|
| 911 | */
|
|---|
| 912 | void QMovie::step(int steps)
|
|---|
| 913 | {
|
|---|
| 914 | if (d->isNull())
|
|---|
| 915 | return;
|
|---|
| 916 | d->stepping = steps;
|
|---|
| 917 | d->frametimer->start(0);
|
|---|
| 918 | d->waitingForFrameTick = FALSE; // Full speed ahead!
|
|---|
| 919 | }
|
|---|
| 920 |
|
|---|
| 921 | /*!
|
|---|
| 922 | Steps forward 1 frame and then pauses.
|
|---|
| 923 | */
|
|---|
| 924 | void QMovie::step()
|
|---|
| 925 | {
|
|---|
| 926 | step(1);
|
|---|
| 927 | }
|
|---|
| 928 |
|
|---|
| 929 | /*!
|
|---|
| 930 | Rewinds the movie to the beginning. If the movie has not been
|
|---|
| 931 | paused, it begins playing again.
|
|---|
| 932 | */
|
|---|
| 933 | void QMovie::restart()
|
|---|
| 934 | {
|
|---|
| 935 | if (d->isNull())
|
|---|
| 936 | return;
|
|---|
| 937 | if (d->source->rewindable()) {
|
|---|
| 938 | d->source->enableRewind(TRUE);
|
|---|
| 939 | d->source->rewind();
|
|---|
| 940 | int s = d->stepping;
|
|---|
| 941 | d->init(TRUE);
|
|---|
| 942 | if ( s>0 )
|
|---|
| 943 | step(s);
|
|---|
| 944 | else if ( s==0 )
|
|---|
| 945 | pause();
|
|---|
| 946 | }
|
|---|
| 947 | }
|
|---|
| 948 |
|
|---|
| 949 | /*!
|
|---|
| 950 | Returns the movie's play speed as a percentage. The default is 100
|
|---|
| 951 | percent.
|
|---|
| 952 |
|
|---|
| 953 | \sa setSpeed()
|
|---|
| 954 | */
|
|---|
| 955 | int QMovie::speed() const
|
|---|
| 956 | {
|
|---|
| 957 | return d->speed;
|
|---|
| 958 | }
|
|---|
| 959 |
|
|---|
| 960 | /*!
|
|---|
| 961 | Sets the movie's play speed as a percentage, to \a percent. This
|
|---|
| 962 | is a percentage of the speed dictated by the input data format.
|
|---|
| 963 | The default is 100 percent.
|
|---|
| 964 | */
|
|---|
| 965 | void QMovie::setSpeed(int percent)
|
|---|
| 966 | {
|
|---|
| 967 | int oldspeed = d->speed;
|
|---|
| 968 | if ( oldspeed != percent && percent >= 0 ) {
|
|---|
| 969 | d->speed = percent;
|
|---|
| 970 | // Restart timer only if really needed
|
|---|
| 971 | if (d->stepping < 0) {
|
|---|
| 972 | if ( !percent || !oldspeed // To or from zero
|
|---|
| 973 | || oldspeed*4 / percent > 4 // More than 20% slower
|
|---|
| 974 | || percent*4 / oldspeed > 4 // More than 20% faster
|
|---|
| 975 | )
|
|---|
| 976 | d->restartTimer();
|
|---|
| 977 | }
|
|---|
| 978 | }
|
|---|
| 979 | }
|
|---|
| 980 |
|
|---|
| 981 | /*!
|
|---|
| 982 | Connects the \a{receiver}'s \a member of type \c{void member(const
|
|---|
| 983 | QSize&)} so that it is signalled when the movie changes size.
|
|---|
| 984 |
|
|---|
| 985 | Note that due to the explicit sharing of QMovie objects, these
|
|---|
| 986 | connections persist until they are explicitly disconnected with
|
|---|
| 987 | disconnectResize() or until \e every shared copy of the movie is
|
|---|
| 988 | deleted.
|
|---|
| 989 | */
|
|---|
| 990 | void QMovie::connectResize(QObject* receiver, const char *member)
|
|---|
| 991 | {
|
|---|
| 992 | QObject::connect(d, SIGNAL(sizeChanged(const QSize&)), receiver, member);
|
|---|
| 993 | }
|
|---|
| 994 |
|
|---|
| 995 | /*!
|
|---|
| 996 | Disconnects the \a{receiver}'s \a member (or all members if \a
|
|---|
| 997 | member is zero) that were previously connected by connectResize().
|
|---|
| 998 | */
|
|---|
| 999 | void QMovie::disconnectResize(QObject* receiver, const char *member)
|
|---|
| 1000 | {
|
|---|
| 1001 | QObject::disconnect(d, SIGNAL(sizeChanged(const QSize&)), receiver, member);
|
|---|
| 1002 | }
|
|---|
| 1003 |
|
|---|
| 1004 | /*!
|
|---|
| 1005 | Connects the \a{receiver}'s \a member of type \c{void member(const
|
|---|
| 1006 | QRect&)} so that it is signalled when an area of the framePixmap()
|
|---|
| 1007 | has changed since the previous frame.
|
|---|
| 1008 |
|
|---|
| 1009 | Note that due to the explicit sharing of QMovie objects, these
|
|---|
| 1010 | connections persist until they are explicitly disconnected with
|
|---|
| 1011 | disconnectUpdate() or until \e every shared copy of the movie is
|
|---|
| 1012 | deleted.
|
|---|
| 1013 | */
|
|---|
| 1014 | void QMovie::connectUpdate(QObject* receiver, const char *member)
|
|---|
| 1015 | {
|
|---|
| 1016 | QObject::connect(d, SIGNAL(areaChanged(const QRect&)), receiver, member);
|
|---|
| 1017 | }
|
|---|
| 1018 |
|
|---|
| 1019 | /*!
|
|---|
| 1020 | Disconnects the \a{receiver}'s \a member (or all members if \q
|
|---|
| 1021 | member is zero) that were previously connected by connectUpdate().
|
|---|
| 1022 | */
|
|---|
| 1023 | void QMovie::disconnectUpdate(QObject* receiver, const char *member)
|
|---|
| 1024 | {
|
|---|
| 1025 | QObject::disconnect(d, SIGNAL(areaChanged(const QRect&)), receiver, member);
|
|---|
| 1026 | }
|
|---|
| 1027 |
|
|---|
| 1028 | /*!
|
|---|
| 1029 | Connects the \a{receiver}'s \a member, of type \c{void
|
|---|
| 1030 | member(int)} so that it is signalled when the movie changes
|
|---|
| 1031 | status. The status codes are negative for errors and positive for
|
|---|
| 1032 | information.
|
|---|
| 1033 |
|
|---|
| 1034 | \table
|
|---|
| 1035 | \header \i Status Code \i Meaning
|
|---|
| 1036 | \row \i QMovie::SourceEmpty
|
|---|
| 1037 | \i signalled if the input cannot be read.
|
|---|
| 1038 | \row \i QMovie::UnrecognizedFormat
|
|---|
| 1039 | \i signalled if the input data is unrecognized.
|
|---|
| 1040 | \row \i QMovie::Paused
|
|---|
| 1041 | \i signalled when the movie is paused by a call to paused()
|
|---|
| 1042 | or by after \link step() stepping \endlink pauses.
|
|---|
| 1043 | \row \i QMovie::EndOfFrame
|
|---|
| 1044 | \i signalled at end-of-frame after any update and Paused signals.
|
|---|
| 1045 | \row \i QMovie::EndOfLoop
|
|---|
| 1046 | \i signalled at end-of-loop, after any update signals,
|
|---|
| 1047 | EndOfFrame - but before EndOfMovie.
|
|---|
| 1048 | \row \i QMovie::EndOfMovie
|
|---|
| 1049 | \i signalled when the movie completes and is not about to loop.
|
|---|
| 1050 | \endtable
|
|---|
| 1051 |
|
|---|
| 1052 | More status messages may be added in the future, so a general test
|
|---|
| 1053 | for errors would test for negative.
|
|---|
| 1054 |
|
|---|
| 1055 | Note that due to the explicit sharing of QMovie objects, these
|
|---|
| 1056 | connections persist until they are explicitly disconnected with
|
|---|
| 1057 | disconnectStatus() or until \e every shared copy of the movie is
|
|---|
| 1058 | deleted.
|
|---|
| 1059 | */
|
|---|
| 1060 | void QMovie::connectStatus(QObject* receiver, const char *member)
|
|---|
| 1061 | {
|
|---|
| 1062 | QObject::connect(d, SIGNAL(dataStatus(int)), receiver, member);
|
|---|
| 1063 | }
|
|---|
| 1064 |
|
|---|
| 1065 | /*!
|
|---|
| 1066 | Disconnects the \a{receiver}'s \a member (or all members if \a
|
|---|
| 1067 | member is zero) that were previously connected by connectStatus().
|
|---|
| 1068 | */
|
|---|
| 1069 | void QMovie::disconnectStatus(QObject* receiver, const char *member)
|
|---|
| 1070 | {
|
|---|
| 1071 | QObject::disconnect(d, SIGNAL(dataStatus(int)), receiver, member);
|
|---|
| 1072 | }
|
|---|
| 1073 |
|
|---|
| 1074 |
|
|---|
| 1075 | #include "qmovie.moc"
|
|---|
| 1076 |
|
|---|
| 1077 | #endif // QT_NO_MOVIE
|
|---|