KDEUI
kanimatedbutton.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2000 Kurt Granroth <granroth@kde.org> 00003 Copyright (C) 2006 Hamish Rodda <rodda@kde.org> 00004 Copyright (C) 2008 Pino Toscano <pino@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License version 2 as published by the Free Software Foundation. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include <kanimatedbutton.h> 00022 00023 #include <QAction> 00024 #include <QPixmap> 00025 #include <QTimer> 00026 #include <QImage> 00027 #include <QToolBar> 00028 #include <QPainter> 00029 #include <QMovie> 00030 00031 #include <kdebug.h> 00032 #include <kiconloader.h> 00033 00034 class KAnimatedButtonPrivate 00035 { 00036 public: 00037 KAnimatedButtonPrivate(KAnimatedButton *qq) 00038 : q(qq), movie(0) 00039 { 00040 } 00041 00042 void updateCurrentIcon(); 00043 void _k_movieFrameChanged(int number); 00044 void _k_movieFinished(); 00045 00046 KAnimatedButton *q; 00047 QMovie *movie; 00048 00049 int frames; 00050 int current_frame; 00051 QPixmap pixmap; 00052 QTimer timer; 00053 QString icon_name; 00054 QVector<QPixmap*> framesCache; // We keep copies of each frame so that 00055 // the icon code can properly cache them in QPixmapCache, 00056 // and not fill it up with dead copies 00057 }; 00058 00059 KAnimatedButton::KAnimatedButton( QWidget *parent ) 00060 : QToolButton(parent), d(new KAnimatedButtonPrivate(this)) 00061 { 00062 connect( &d->timer, SIGNAL(timeout()), this, SLOT(slotTimerUpdate())); 00063 } 00064 00065 KAnimatedButton::~KAnimatedButton() 00066 { 00067 d->timer.stop(); 00068 qDeleteAll(d->framesCache); 00069 delete d->movie; 00070 00071 delete d; 00072 } 00073 00074 void KAnimatedButton::start() 00075 { 00076 if (d->movie) { 00077 d->movie->start(); 00078 } else { 00079 d->current_frame = 0; 00080 d->timer.start(50); 00081 } 00082 } 00083 00084 void KAnimatedButton::stop() 00085 { 00086 if (d->movie) { 00087 d->movie->stop(); 00088 d->movie->jumpToFrame(0); 00089 d->_k_movieFrameChanged(0); 00090 } else { 00091 d->current_frame = 0; 00092 d->timer.stop(); 00093 d->updateCurrentIcon(); 00094 } 00095 } 00096 00097 void KAnimatedButton::setIcons( const QString& icons ) 00098 { 00099 if ( d->icon_name == icons ) 00100 return; 00101 00102 d->timer.stop(); 00103 d->icon_name = icons; 00104 updateIcons(); 00105 } 00106 00107 QString KAnimatedButton::icons( ) const 00108 { 00109 return d->icon_name; 00110 } 00111 00112 void KAnimatedButton::slotTimerUpdate() 00113 { 00114 if(!isVisible()) 00115 return; 00116 00117 d->current_frame++; 00118 if (d->current_frame == d->frames) 00119 d->current_frame = 0; 00120 00121 d->updateCurrentIcon(); 00122 } 00123 00124 void KAnimatedButtonPrivate::updateCurrentIcon() 00125 { 00126 if (pixmap.isNull()) 00127 return; 00128 00129 QPixmap* frame = framesCache[current_frame]; 00130 if (!frame) 00131 { 00132 const int icon_size = q->iconDimensions(); 00133 const int row_size = pixmap.width() / icon_size; 00134 const int row = current_frame / row_size; 00135 const int column = current_frame % row_size; 00136 frame = new QPixmap(icon_size, icon_size); 00137 frame->fill(Qt::transparent); 00138 QPainter p(frame); 00139 p.drawPixmap(QPoint(0, 0), pixmap, QRect(column * icon_size, row * icon_size, icon_size, icon_size)); 00140 p.end(); 00141 framesCache[current_frame] = frame; 00142 } 00143 00144 q->setIcon(QIcon(*frame)); 00145 } 00146 00147 void KAnimatedButtonPrivate::_k_movieFrameChanged(int number) 00148 { 00149 Q_UNUSED(number); 00150 q->setIcon(QIcon(movie->currentPixmap())); 00151 } 00152 00153 void KAnimatedButtonPrivate::_k_movieFinished() 00154 { 00155 // if not running, make it loop 00156 if (movie->state() == QMovie::NotRunning) { 00157 movie->start(); 00158 } 00159 } 00160 00161 void KAnimatedButton::updateIcons() 00162 { 00163 const int icon_size = iconDimensions(); 00164 d->pixmap = QPixmap(); 00165 QMovie *movie = KIconLoader::global()->loadMovie(d->icon_name, KIconLoader::NoGroup, -icon_size); 00166 if (movie) { 00167 d->frames = 0; 00168 movie->setCacheMode(QMovie::CacheAll); 00169 connect(movie, SIGNAL(frameChanged(int)), this, SLOT(_k_movieFrameChanged(int))); 00170 connect(movie, SIGNAL(finished()), this, SLOT(_k_movieFinished())); 00171 } else { 00172 const QString path = KIconLoader::global()->iconPath(d->icon_name, -icon_size); 00173 QImage img(path); 00174 if (img.isNull()) 00175 return; 00176 00177 if ((img.width() % icon_size != 0) || (img.height() % icon_size != 0)) 00178 return; 00179 00180 d->frames = (img.height() / icon_size) * (img.width() / icon_size); 00181 d->pixmap = QPixmap::fromImage(img); 00182 } 00183 00184 d->current_frame = 0; 00185 qDeleteAll(d->framesCache); 00186 d->framesCache.fill(0); 00187 d->framesCache.resize(d->frames); 00188 delete d->movie; 00189 d->movie = movie; 00190 00191 if (d->movie) { 00192 d->movie->jumpToFrame(0); 00193 d->_k_movieFrameChanged(0); 00194 } else { 00195 d->updateCurrentIcon(); 00196 } 00197 } 00198 00199 int KAnimatedButton::iconDimensions() const 00200 { 00201 return qMin(iconSize().width(), iconSize().height()); 00202 } 00203 00204 #include "kanimatedbutton.moc"
KDE 4.6 API Reference