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