KIO
kimagefilepreview.cpp
Go to the documentation of this file.
00001 /* 00002 * This file is part of the KDE project 00003 * Copyright (C) 2001 Martin R. Jones <mjones@kde.org> 00004 * 2001 Carsten Pfeiffer <pfeiffer@kde.org> 00005 * 2008 Rafael Fernández López <ereslibre@kde.org> 00006 * 00007 * You can Freely distribute this program under the GNU Library General Public 00008 * License. See the file "COPYING" for the exact licensing terms. 00009 */ 00010 00011 #include "kimagefilepreview.h" 00012 00013 #include <QtGui/QLayout> 00014 #include <QtGui/QLabel> 00015 #include <QtGui/QPainter> 00016 #include <QtGui/QComboBox> 00017 #include <QtGui/QCheckBox> 00018 #include <QtGui/QResizeEvent> 00019 #include <QtCore/QTimer> 00020 #include <QtCore/QTimeLine> 00021 00022 #include <kapplication.h> 00023 #include <kglobalsettings.h> 00024 #include <kconfig.h> 00025 #include <kglobal.h> 00026 #include <kiconloader.h> 00027 #include <kpushbutton.h> 00028 #include <kstandarddirs.h> 00029 #include <kdebug.h> 00030 #include <klocale.h> 00031 #include <kfiledialog.h> 00032 #include <kfileitem.h> 00033 #include <kio/previewjob.h> 00034 #include <kconfiggroup.h> 00035 00036 #include <config-kfile.h> 00037 00038 /**** KImageFilePreview ****/ 00039 00040 class KImageFilePreview::KImageFilePreviewPrivate 00041 { 00042 public: 00043 KImageFilePreviewPrivate() 00044 : m_job(0) 00045 , clear(true) 00046 { 00047 m_timeLine = new QTimeLine(150); 00048 m_timeLine->setCurveShape(QTimeLine::EaseInCurve); 00049 m_timeLine->setDirection(QTimeLine::Forward); 00050 m_timeLine->setFrameRange(0, 100); 00051 } 00052 00053 ~KImageFilePreviewPrivate() 00054 { 00055 delete m_timeLine; 00056 } 00057 00058 void _k_slotResult( KJob* ); 00059 void _k_slotFailed( const KFileItem& ); 00060 void _k_slotStepAnimation( int frame ); 00061 void _k_slotFinished( ); 00062 void _k_slotActuallyClear( ); 00063 00064 KUrl currentURL; 00065 KUrl lastShownURL; 00066 QLabel *imageLabel; 00067 KIO::PreviewJob *m_job; 00068 QTimeLine *m_timeLine; 00069 QPixmap m_pmCurrent; 00070 QPixmap m_pmTransition; 00071 float m_pmCurrentOpacity; 00072 float m_pmTransitionOpacity; 00073 bool clear; 00074 }; 00075 00076 KImageFilePreview::KImageFilePreview( QWidget *parent ) 00077 : KPreviewWidgetBase(parent), d(new KImageFilePreviewPrivate) 00078 { 00079 QVBoxLayout *vb = new QVBoxLayout( this ); 00080 vb->setMargin( 0 ); 00081 00082 d->imageLabel = new QLabel(this); 00083 d->imageLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 00084 d->imageLabel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); 00085 vb->addWidget(d->imageLabel); 00086 00087 setSupportedMimeTypes( KIO::PreviewJob::supportedMimeTypes() ); 00088 setMinimumWidth( 50 ); 00089 00090 connect(d->m_timeLine, SIGNAL(frameChanged(int)), this, SLOT(_k_slotStepAnimation(int))); 00091 connect(d->m_timeLine, SIGNAL(finished()), this, SLOT(_k_slotFinished())); 00092 } 00093 00094 KImageFilePreview::~KImageFilePreview() 00095 { 00096 if (d->m_job) { 00097 d->m_job->kill(); 00098 } 00099 00100 delete d; 00101 } 00102 00103 void KImageFilePreview::showPreview() 00104 { 00105 // Pass a copy since clearPreview() will clear currentURL 00106 KUrl url = d->currentURL; 00107 showPreview( url, true ); 00108 } 00109 00110 // called via KPreviewWidgetBase interface 00111 void KImageFilePreview::showPreview( const KUrl& url ) 00112 { 00113 showPreview( url, false ); 00114 } 00115 00116 void KImageFilePreview::showPreview( const KUrl &url, bool force ) 00117 { 00118 if (!url.isValid() || 00119 (d->lastShownURL.isValid() && 00120 url.equals(d->lastShownURL, KUrl::CompareWithoutTrailingSlash) && 00121 d->currentURL.isValid())) 00122 return; 00123 00124 d->clear = false; 00125 d->currentURL = url; 00126 d->lastShownURL = url; 00127 00128 int w = d->imageLabel->contentsRect().width() - 4; 00129 int h = d->imageLabel->contentsRect().height() - 4; 00130 00131 if (d->m_job) { 00132 disconnect(d->m_job, SIGNAL(result(KJob *)), 00133 this, SLOT( _k_slotResult( KJob * ))); 00134 disconnect(d->m_job, SIGNAL(gotPreview(const KFileItem&, 00135 const QPixmap& )), this, 00136 SLOT( gotPreview( const KFileItem&, const QPixmap& ) )); 00137 00138 disconnect(d->m_job, SIGNAL(failed(const KFileItem&)), 00139 this, SLOT(_k_slotFailed(const KFileItem&))); 00140 00141 d->m_job->kill(); 00142 } 00143 00144 d->m_job = createJob(url, w, h); 00145 if ( force ) // explicitly requested previews shall always be generated! 00146 d->m_job->setIgnoreMaximumSize(true); 00147 00148 connect(d->m_job, SIGNAL(result(KJob *)), 00149 this, SLOT( _k_slotResult( KJob * ))); 00150 connect(d->m_job, SIGNAL(gotPreview(const KFileItem&, 00151 const QPixmap& )), 00152 SLOT( gotPreview( const KFileItem&, const QPixmap& ) )); 00153 00154 connect(d->m_job, SIGNAL(failed(const KFileItem&)), 00155 this, SLOT(_k_slotFailed(const KFileItem&))); 00156 } 00157 00158 void KImageFilePreview::resizeEvent( QResizeEvent * ) 00159 { 00160 clearPreview(); 00161 d->currentURL = KUrl(); // force this to actually happen 00162 showPreview( d->lastShownURL ); 00163 } 00164 00165 QSize KImageFilePreview::sizeHint() const 00166 { 00167 return QSize( 100, 200 ); 00168 } 00169 00170 KIO::PreviewJob * KImageFilePreview::createJob( const KUrl& url, int w, int h ) 00171 { 00172 KUrl::List urls; 00173 urls.append( url ); 00174 return KIO::filePreview( urls, w, h, 0, 0, true, false ); 00175 } 00176 00177 void KImageFilePreview::gotPreview( const KFileItem& item, const QPixmap& pm ) 00178 { 00179 if (item.url() == d->currentURL) { // should always be the case 00180 if (KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) { 00181 if (d->m_timeLine->state() == QTimeLine::Running) { 00182 d->m_timeLine->setCurrentTime(0); 00183 } 00184 00185 d->m_pmTransition = pm; 00186 d->m_pmTransitionOpacity = 0; 00187 d->m_pmCurrentOpacity = 1; 00188 d->m_timeLine->setDirection(QTimeLine::Forward); 00189 d->m_timeLine->start(); 00190 } 00191 else 00192 { 00193 d->imageLabel->setPixmap(pm); 00194 } 00195 } 00196 } 00197 00198 void KImageFilePreview::KImageFilePreviewPrivate::_k_slotFailed( const KFileItem& item ) 00199 { 00200 if ( item.isDir() ) 00201 imageLabel->clear(); 00202 else if (item.url() == currentURL) // should always be the case 00203 imageLabel->setPixmap(SmallIcon( "image-missing", KIconLoader::SizeLarge, 00204 KIconLoader::DisabledState )); 00205 } 00206 00207 void KImageFilePreview::KImageFilePreviewPrivate::_k_slotResult( KJob *job ) 00208 { 00209 if (job == m_job) { 00210 m_job = 0L; 00211 } 00212 } 00213 00214 void KImageFilePreview::KImageFilePreviewPrivate::_k_slotStepAnimation( int frame ) 00215 { 00216 Q_UNUSED(frame) 00217 00218 QPixmap pm(QSize(qMax(m_pmCurrent.size().width(), m_pmTransition.size().width()), 00219 qMax(m_pmCurrent.size().height(), m_pmTransition.size().height()))); 00220 pm.fill(Qt::transparent); 00221 00222 QPainter p(&pm); 00223 p.setOpacity(m_pmCurrentOpacity); 00224 00225 //If we have a current pixmap 00226 if (!m_pmCurrent.isNull()) 00227 p.drawPixmap(QPoint(((float) pm.size().width() - m_pmCurrent.size().width()) / 2.0, 00228 ((float) pm.size().height() - m_pmCurrent.size().height()) / 2.0), m_pmCurrent); 00229 if (!m_pmTransition.isNull()) { 00230 p.setOpacity(m_pmTransitionOpacity); 00231 p.drawPixmap(QPoint(((float) pm.size().width() - m_pmTransition.size().width()) / 2.0, 00232 ((float) pm.size().height() - m_pmTransition.size().height()) / 2.0), m_pmTransition); 00233 } 00234 p.end(); 00235 00236 imageLabel->setPixmap(pm); 00237 00238 m_pmCurrentOpacity = qMax(m_pmCurrentOpacity - 0.4, 0.0); // krazy:exclude=qminmax 00239 m_pmTransitionOpacity = qMin(m_pmTransitionOpacity + 0.4, 1.0); //krazy:exclude=qminmax 00240 } 00241 00242 void KImageFilePreview::KImageFilePreviewPrivate::_k_slotFinished() 00243 { 00244 m_pmCurrent = m_pmTransition; 00245 m_pmTransitionOpacity = 0; 00246 m_pmCurrentOpacity = 1; 00247 m_pmTransition = QPixmap(); 00248 // The animation might have lost some frames. Be sure that if the last one 00249 // was dropped, the last image shown is the opaque one. 00250 imageLabel->setPixmap(m_pmCurrent); 00251 clear = false; 00252 } 00253 00254 void KImageFilePreview::clearPreview() 00255 { 00256 if (d->m_job) { 00257 d->m_job->kill(); 00258 d->m_job = 0L; 00259 } 00260 00261 if (d->clear || d->m_timeLine->state() == QTimeLine::Running) { 00262 return; 00263 } 00264 00265 if (KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) { 00266 d->m_pmTransition = QPixmap(); 00267 //If we add a previous preview then we run the animation 00268 if (!d->m_pmCurrent.isNull()) { 00269 d->m_timeLine->setCurrentTime(0); 00270 d->m_timeLine->setDirection(QTimeLine::Backward); 00271 d->m_timeLine->start(); 00272 } 00273 d->currentURL = KUrl(); 00274 d->clear = true; 00275 } 00276 else 00277 { 00278 d->imageLabel->clear(); 00279 } 00280 } 00281 00282 #include "kimagefilepreview.moc"
KDE 4.6 API Reference