1 /***************************************************************************
2 * Copyright (C) 2004 by Kita Developers *
3 * ikemo@users.sourceforge.jp *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 ***************************************************************************/
11 /* Image Manager class */
13 #include "imgmanager.h"
15 #include "kitaconfig.h"
16 #include "downloadmanager.h"
18 #include <kdeversion.h>
19 #include <kio/netaccess.h>
21 #include <kfiledialog.h>
26 #include <qdatastream.h>
27 #include <qmessagebox.h>
28 #include <qapplication.h>
33 ImgManager* ImgManager::instance = NULL;
34 QMutex ImgManager::m_mutex;
36 /*-----------------------------------------------------------*/
39 ImgManager::ImgManager( QWidget* mainwidget )
42 m_mainwidget = mainwidget;
47 ImgManager::~ImgManager()
51 /* call this first */ /* public */ /* static */
52 void ImgManager::setup( QWidget* mainwidget )
54 instance = new ImgManager( mainwidget );
58 /* public */ /* static */
59 void ImgManager::deleteInstance()
61 if ( instance ) delete instance;
65 /* public */ /* static */
66 ImgManager* ImgManager::getInstance()
72 /* public */ /* static */
73 bool ImgManager::isImgFile( const KURL& url, bool use_mimetype )
75 return instance->isImgFilePrivate( url, use_mimetype );
79 /* public */ /* static */
80 bool ImgManager::isAnimationGIF( const KURL& url )
82 QRegExp reg_ext( ".*\\.gif$" );
83 if ( reg_ext.search( url.fileName().lower() ) != -1 ) return TRUE;
89 /* public */ /* static */
90 bool ImgManager::isBMP( const KURL& url )
92 QRegExp reg_ext( ".*\\.bmp$" );
93 if ( reg_ext.search( url.fileName().lower() ) != -1 ) return TRUE;
99 /* public */ /* static */
100 bool ImgManager::load( const KURL& url, const KURL& datURL )
102 QMutexLocker locker( &m_mutex );
104 return instance->loadPrivate( url, datURL );
108 /* public */ /* static */
109 void ImgManager::stop( const KURL& url )
111 QMutexLocker locker( &m_mutex );
113 DownloadManager::stopLoading( url );
117 /* public */ /* static */
118 QString ImgManager::getPath( const KURL& url )
120 return Cache::getImgPath( url );
124 /* public */ /* static */
125 bool ImgManager::isLoadingNow( const KURL& url )
128 return DownloadManager::isLoadingNow( url );
132 /* public */ /* static */
133 bool ImgManager::deleteCache( const KURL& url, QWidget* parent )
135 QMutexLocker locker( &m_mutex );
137 return instance->deleteCachePrivate( url, parent );
141 /* public */ /* static */
142 bool ImgManager::copyCache( const KURL& url, QWidget* parent )
144 QMutexLocker locker( &m_mutex );
146 return instance->copyCachePrivate( url, parent );
150 /* public */ /* static */
151 bool ImgManager::mosaic( const KURL& url )
153 instance->cacheExists( url ); /* to create IMGDAT if cache exists */
155 IMGDAT* imgdat = instance->getImgDat( url );
156 if ( !imgdat ) return TRUE;
158 return imgdat->mosaic;
162 /* public */ /* static */
163 void ImgManager::setMosaic( const KURL& url, bool status )
165 instance->setMosaicPrivate( url, status );
169 /* return -1 if IMGDAT doesn't exist. */ /* public */ /* static */
170 int ImgManager::code( const KURL& url )
172 instance->cacheExists( url ); /* to create IMGDAT if cache exists */
174 IMGDAT* imgdat = instance->getImgDat( url );
175 if ( !imgdat ) return -1;
181 /* public */ /* static */
182 unsigned int ImgManager::size( const KURL& url )
184 instance->cacheExists( url ); /* to create IMGDAT if cache exists */
186 IMGDAT* imgdat = instance->getImgDat( url );
187 if ( !imgdat ) return 0;
193 /* public */ /* static */
194 int ImgManager::width( const KURL& url )
196 instance->cacheExists( url ); /* to create IMGDAT if cache exists */
198 IMGDAT* imgdat = instance->getImgDat( url );
199 if ( !imgdat ) return 0;
200 if ( imgdat->width == 0 ) instance->getSize( url );
202 return imgdat->width;
206 /* public */ /* static */
207 int ImgManager::height( const KURL& url )
209 instance->cacheExists( url ); /* to create IMGDAT if cache exists */
211 IMGDAT* imgdat = instance->getImgDat( url );
212 if ( !imgdat ) return 0;
213 if ( imgdat->height == 0 ) instance->getSize( url );
215 return imgdat->height;
219 /* get icon pixmap */ /* public */ /* static */
220 QPixmap ImgManager::icon( const KURL& url )
222 const int iconsize = 32;
224 /*---------------------------*/
227 QString path = Cache::getImgPath( url );
228 QImage img = QImage( path );
229 if ( img.isNull() ) return QPixmap();
231 pixmap.convertFromImage( img.scale( iconsize, iconsize, QImage::ScaleMin ) );
236 /* public */ /* static */
237 KURL ImgManager::datURL( const KURL& url )
239 instance->cacheExists( url ); /* to create IMGDAT if cache exists */
241 IMGDAT* imgdat = instance->getImgDat( url );
242 if ( !imgdat ) return KURL();
244 return imgdat->datURL;
248 /*---------------------------------*/
249 /* internal functions */
253 bool ImgManager::isImgFilePrivate( const KURL& url, bool use_mimetype )
255 /* don't use mimetype */
256 if ( !use_mimetype ) {
258 QStringList extlist; // = KitaConfig::imgExtList();
265 for ( QStringList::iterator it = extlist.begin(); it != extlist.end(); ++it ) {
266 QRegExp reg_ext = ".*\\." + ( *it ) + "$";
267 if ( reg_ext.search( url.fileName().lower() ) != -1 ) return TRUE;
274 /*-----------------------------------*/
276 /* use mimetype ( very slow! ) */
277 if ( cacheExists( url ) ) return TRUE;
279 #if KDE_IS_VERSION( 3, 2, 0 )
280 QString mimetype = KIO::NetAccess::mimetype( url, m_mainwidget );
282 QString mimetype = KIO::NetAccess::mimetype( url );
284 if ( mimetype.left( 6 ) == "image/" ) return TRUE;
290 /* create new loader and start loading the image */
291 /* when done, ImgManager emits finishImgLoad SIGNAL. */ /* private */
292 bool ImgManager::loadPrivate( const KURL& url, const KURL& datURL )
294 const unsigned int maxload = 5; // = KitaConfig::maxLoader();
296 /*------------------------------*/
298 if ( DownloadManager::isLoadingNow( url ) ) return FALSE;
301 if ( cacheExists( url ) ) {
303 /* create EmitFinishEvent to emit finishImgLoad SIGNAL later. */
304 /* See also customEvent(). */
305 EmitFinishEvent * e = new EmitFinishEvent( url );
306 QApplication::postEvent( this, e ); // Qt will delete it when done
311 if( m_urlList.count() > maxload ) return FALSE;
313 QString path = Cache::getImgPath( url );
316 /* create new loader, and start loading the file */
317 /* slotResult is called when done. */
319 option.usrurl = datURL;
320 FileLoader* loader = DownloadManager::download( url, path, option );
321 if ( loader == NULL ) return FALSE;
323 connect( loader, SIGNAL( data( const Kita::LoaderData&, const QByteArray& ) ),
324 SLOT( slotData( const Kita::LoaderData&, const QByteArray& ) ) );
326 connect( loader, SIGNAL( result( const Kita::LoaderData& ) ),
327 SLOT( slotResult( const Kita::LoaderData& ) ) );
329 m_urlList += url.prettyURL();
336 /* when done, cacheDeleted SIGNAL emitted */ /* private */
337 bool ImgManager::deleteCachePrivate( const KURL& url, QWidget* parent )
339 if ( !cacheExists( url ) ) return FALSE;
341 if ( QMessageBox::warning( parent,
343 i18n( "Do you want to delete the image ?" ),
344 QMessageBox::Ok, QMessageBox::Cancel | QMessageBox::Default )
345 == QMessageBox::Ok ) {
349 QString path = Cache::getImgPath( url );
350 QString idxpath = Cache::getImgIdxPath( url );
352 #if KDE_IS_VERSION( 3, 2, 0 )
353 KIO::NetAccess::del( idxpath, m_mainwidget );
354 ret = KIO::NetAccess::del( path, m_mainwidget );
356 KIO::NetAccess::del( idxpath );
357 ret = KIO::NetAccess::del( path );
362 emit cacheDeleted( url );
372 /* copy cache */ /* public */
373 bool ImgManager::copyCachePrivate( const KURL& url, QWidget* parent )
375 if ( !cacheExists( url ) ) return FALSE;
379 QString file = url.fileName().lower();
380 int i = file.findRev( '.' );
381 if ( i == -1 ) filter = "*|All files";
383 QString ext = file.mid( i );
384 filter = "*" + ext + "|*" + ext;
388 QString savefile = KFileDialog::getSaveFileName( url.fileName(), filter, parent );
389 if ( savefile.isEmpty() ) return FALSE;
393 #if KDE_IS_VERSION( 3, 2, 0 )
394 KIO::NetAccess::exists( savefile, TRUE, m_mainwidget )
396 KIO::NetAccess::exists( savefile )
400 if ( QMessageBox::warning( parent,
402 i18n( "Do you want to replace the file?" ),
403 QMessageBox::Ok, QMessageBox::Cancel | QMessageBox::Default )
404 != QMessageBox::Ok ) return FALSE;
406 #if KDE_IS_VERSION( 3, 2, 0 )
407 KIO::NetAccess::del( savefile, m_mainwidget );
409 KIO::NetAccess::del( savefile );
415 QString src = Cache::getImgPath( url );
417 #if KDE_IS_VERSION( 3, 2, 0 )
418 KIO::NetAccess::copy( src, savefile, m_mainwidget );
420 KIO::NetAccess::copy( src, savefile );
428 void ImgManager::setMosaicPrivate( const KURL& url, bool status )
430 IMGDAT * imgdat = getImgDat( url );
431 if ( !imgdat ) return ;
432 if ( imgdat->code != 200 ) return ;
434 imgdat->mosaic = status;
437 KConfig cfg( Cache::getImgIdxPath( url ) );
438 cfg.writeEntry( "Mosaic", status );
443 void ImgManager::createImgDat( const KURL& url, int code )
445 IMGDAT * imgdat = getImgDat( url );
448 m_imgDatDict.insert( url.prettyURL(), imgdat );
451 KConfig cfg( Cache::getImgIdxPath( url ) );
452 if ( code == 200 ) cfg.writeEntry( "URL", url.prettyURL() );
454 imgdat->mosaic = cfg.readBoolEntry( "Mosaic", KitaConfig::useMosaic() );
455 imgdat->height = cfg.readNumEntry( "Height", 0 );
456 imgdat->width = cfg.readNumEntry( "Width", 0 );
457 imgdat->size = cfg.readUnsignedNumEntry( "Size", 0 );
458 imgdat->datURL = cfg.readEntry( "datURL", QString::null );
464 IMGDAT* ImgManager::getImgDat( const KURL& url )
466 return m_imgDatDict.find( url.prettyURL() );
471 void ImgManager::deleteImgDat( const KURL& url )
473 IMGDAT * imgdat = getImgDat( url );
474 if ( !imgdat ) return ;
476 if ( m_imgDatDict.remove( url.prettyURL() ) ) {
483 void ImgManager::getSize( const KURL& url )
485 IMGDAT * imgdat = getImgDat( url );
486 if ( !imgdat ) return ;
487 if ( imgdat->code != 200 ) return ;
489 QString path = Cache::getImgPath( url );
490 QImage img = QImage( path );
492 if ( !img.isNull() ) {
494 imgdat->width = img.width();
495 imgdat->height = img.height();
498 KConfig cfg( Cache::getImgIdxPath( url ) );
499 cfg.writeEntry( "Width", imgdat->width );
500 cfg.writeEntry( "Height", imgdat->height );
506 bool ImgManager::cacheExists( const KURL& url )
508 if ( DownloadManager::isLoadingNow( url ) ) return FALSE;
511 QString path = Cache::getImgPath( url );
513 #if KDE_IS_VERSION( 3, 2, 0 )
514 ret = KIO::NetAccess::exists( path, TRUE, m_mainwidget );
516 ret = KIO::NetAccess::exists( path );
519 if ( ret && !getImgDat( url ) ) createImgDat( url, 200 );
526 /* This slot is called when loader received the data. */ /* private slot */
527 void ImgManager::slotData( const Kita::LoaderData& data, const QByteArray& barray )
529 /* check BMP header */
530 if ( barray.size() > 2 && data.size == barray.size()
531 && barray[ 0 ] == 'B' && barray[ 1 ] == 'M' ) {
532 DownloadManager::stopLoading( data.url );
536 /* I assume that file size is smaller than 2^32 byte */
537 emit receiveImgData( data.url, data.size, data.totalsize );
541 /* This slot is called when loading is done. */ /* private slot */
542 void ImgManager::slotResult( const Kita::LoaderData& data )
544 m_urlList.remove( data.url.prettyURL() );
545 createImgDat( data.url, data.code );
547 /* save size, datURL, etc */
548 if ( data.code == 200 ) {
549 unsigned int totalsize = data.totalsize;
550 KURL datURL = data.option.usrurl;
551 KConfig cfg( Cache::getImgIdxPath( data.url ) );
552 cfg.writeEntry( "Size", totalsize );
553 cfg.writeEntry( "datURL", datURL.prettyURL() );
554 IMGDAT* imgdat = instance->getImgDat( data.url );
555 imgdat->size = totalsize;
556 imgdat->datURL = datURL;
559 emit finishImgLoad( data.url );
563 /* protected */ /* virtual */
564 void ImgManager::customEvent( QCustomEvent * e )
566 /* emit finishImgLoad SIGNAL */
567 if ( e->type() == EVENT_EmitFinigh ) {
568 KURL url = static_cast< EmitFinishEvent* >( e ) ->url();
569 emit finishImgLoad( url );