#include "libkita/signalcollection.h"
#include "libkita/parsemisc.h"
#include "libkita/account.h"
+#include "libkita/imgmanager.h"
#include <qdragobject.h>
#include <qtextcodec.h>
// accept dnd
setAcceptDrops( true );
+ // setup imgmanager
+ Kita::ImgManager::setup( this );
+
// setup view, dock
setupView();
/* open with image viewer */
if ( KitaConfig::useImageViewer() )
{
- QStringList extlist; // = KitaConfig::imgExtList();
- extlist = "jpg";
- extlist += "jpeg";
- extlist += "gif";
- extlist += "png";
- extlist += "bmp";
-
- for ( QStringList::iterator it = extlist.begin(); it != extlist.end(); ++it ){
- QRegExp reg_ext = ".*\\."+(*it)+"$";
- reg_ext.setCaseSensitive( FALSE );
- if ( reg_ext.search( datURL.prettyURL() ) != -1 ) {
- m_imgDock->slotOpenURL( url );
- return;
- }
- }
+ if( Kita::ImgManager::isImgFile( url, FALSE )){
+ m_imgDock->slotOpenURL( url );
+ return;
+ }
}
/* open with kpart */
* (at your option) any later version. *
***************************************************************************/
-/* Kita Image Viewer */
+/* Kita Image Tab */
#include "kitaimgtabwidget.h"
+#include "kitaimgview.h"
+#include "libkita/imgmanager.h"
#include "libkita/signalcollection.h"
-#include <klibloader.h>
#include <kapplication.h>
#include <klocale.h>
#include <kstdaccel.h>
#include <kpopupmenu.h>
-#include <kparts/browserextension.h>
-#include <kparts/partmanager.h>
-#include <kio/netaccess.h>
#include <kaction.h>
#include <krun.h>
+#include <kiconloader.h>
-#include <qlayout.h>
#include <qiconset.h>
#include <qclipboard.h>
#include <qmessagebox.h>
setXMLFile( "kitaimgtabwidgetui.rc" );
setTabBar( new KitaImgTabBar( this ) );
setupActions();
+
+ /* When loading is done, ImgManager emits finishImgLoad SIGNAL. */
+ /* See also ImgManager::slotResult. */
+ connect( Kita::ImgManager::getInstance(), SIGNAL( finishImgLoad( const KURL& ) ),
+ SLOT( slotUpdateView( const KURL& ) ) );
+
+ connect( Kita::ImgManager::getInstance(), SIGNAL( cacheDeleted( const KURL& ) ),
+ SLOT( slotCloseImgView( const KURL& ) ) );
}
}
/* create and show new image viewer */
- view = new KitaImgView( url, this, "Viewer", 0L );
+ view = createImgView( url );
if( view ){
- addTab( view, QIconSet( view->icon(), QIconSet::Small ), "" );
- view->slotShowImage();
- showPage( view );
- /* resize */
- QRect rt = view->rect();
- if( rt.right()-rt.left() < view->imgWidth()
- || rt.bottom()-rt.top() < view->imgHeight() ) view->slotFitToWin();
+ if( Kita::ImgManager::isLoadingNow( url ) ) return;
+
+ /* cache exists. */
+ if( Kita::ImgManager::code( url ) == 200 ){
+ slotUpdateView( url );
+ return;
+ }
+
+ /* start loading the image. */
+ /* When done, slotUpdateView() is called back. */
+ if( !Kita::ImgManager::load( url ) ){
+ QMessageBox::warning( this,
+ "Kita",
+ i18n( "can't start downloading. try again later." ) );
+ setTabIconSet( view, QIconSet( SmallIcon( "unread" ), QIconSet::Small ) );
+ setTabToolTip( view, "error" );
+ }
+ }
+}
+
+
+/* public slot */
+void KitaImgTabWidget::slotCloseImgView( const KURL& url )
+{
+ KitaImgView* view = findImgView( url );
+ if( view ) slotCloseTab ( indexOf( view ) );
+}
+
+
+/* public slot */
+void KitaImgTabWidget::slotUpdateView( const KURL& url )
+{
+ KitaImgView* view = findImgView( url );
+
+ if( view ){
+
+ int code = Kita::ImgManager::code( url );
+
+ if( code == 200 ){
+
+ setTabIconSet( view, QIconSet( Kita::ImgManager::icon( url ), QIconSet::Small ) );
+ setTabToolTip( view, url.prettyURL() );
+ view->slotShowImage( 0, 0 );
+
+ /* resize */
+ QRect rt = view->rect();
+ int wd = Kita::ImgManager::width( url );
+ int ht = Kita::ImgManager::height( url );
+ if( rt.right()-rt.left() < wd || rt.bottom()-rt.top() < ht ) fitImageToWin( view );
+ }
+ else{ /* error */
+
+ setTabIconSet( view, QIconSet( SmallIcon( "unread" ), QIconSet::Small ) );
+ QString str = "error " + QString().setNum( code );
+ setTabToolTip( view, str );
+ }
}
}
void KitaImgTabWidget::customEvent( QCustomEvent * e )
{
KitaTabWidgetBase::customEvent( e );
- if ( e->type() == EVENT_FitImageToWinEvent ) slotShowFitToWin();
+
+ /* fit image to window */
+ if ( e->type() == EVENT_FitImageToWinEvent ){
+ KitaImgView* view = isImgView( static_cast< FitImageToWinEvent* >( e )->getWidget() );
+ if( view ) view->slotFitToWin();
+ }
+
+ /* cancel mosaic */
+ else if( e->type() == EVENT_CancelMoszicEvent ){
+
+ KitaImgView* view = static_cast< CancelMosaicEvent* >( e )->getView();
+
+ KURL url = view->url();
+ if( !Kita::ImgManager::mosaic( url ) ) return;
+
+ QRect rt = currentPage()->rect();
+ int wd = Kita::ImgManager::width( view->url() );
+ int ht = Kita::ImgManager::height( view->url() );
+
+ Kita::ImgManager::setMosaic( url, FALSE );
+ view->slotShowImage( 0, 0 );
+
+ /* resize */
+ if( rt.right()-rt.left() < wd || rt.bottom()-rt.top() < ht ) fitImageToWin( view );
+ }
}
/* protected */ /* virtual */
void KitaImgTabWidget::deleteWidget( QWidget* w )
{
+ /* stop loading */
+ KitaImgView* view = isImgView( w );
+ if( view ){
+ Kita::ImgManager::stop( view->url() );
+ }
+
KitaTabWidgetBase::deleteWidget( w );
if ( count() == 0 ) {
/* private */
+KitaImgView* KitaImgTabWidget::createImgView( const KURL& url )
+{
+ KitaImgView* view = new KitaImgView( url, actionCollection(), this, "Viewer", 0L );
+ if( view ){
+ addTab( view, "" );
+ setTabIconSet( view, QIconSet( SmallIcon( "read" ), QIconSet::Small ) );
+ setTabToolTip( view, "Loading..." );
+ showPage( view );
+ }
+
+ return view;
+}
+
+
+/* private */
KitaImgView* KitaImgTabWidget::findImgView( const KURL& url )
{
int max = count();
}
+/* private */
+void KitaImgTabWidget::fitImageToWin( QWidget* w )
+{
+ /* If the image is not shown, kview can't get the exact image size.
+ So, post custom event, and fit image size after the image shows. */
+ FitImageToWinEvent* e = new FitImageToWinEvent( w );
+ QApplication::postEvent( this, e ); // Qt will delete it when done
+}
+
/*------------------------------------*/
/* Image View actions */
actionCollection(),
"imgviewer_cancelmosaic" );
+ new KAction( i18n( "Cancel All mosaics" ),
+ 0,
+ this,
+ SLOT( slotCancelAllMosaic() ),
+ actionCollection(),
+ "imgviewer_cancelallmosaic" );
+
new KAction( i18n( "Fit Image to Window" ),
0,
this,
SLOT( slotOpenBrowser() ),
actionCollection(),
"imgviewer_openbrowser" );
+
+ new KAction( i18n( "Delete" ),
+ Key_Delete,
+ this,
+ SLOT( slotDelete() ),
+ actionCollection(),
+ "imgviewer_delete" );
+
+ new KAction( i18n( "Copy" ),
+ 0,
+ this,
+ SLOT( slotCopy() ),
+ actionCollection(),
+ "imgviewer_copy" );
+
+ new KAction( i18n( "Close all error tabs" ),
+ 0,
+ this,
+ SLOT( slotCloseErrorTab() ),
+ actionCollection(),
+ "imgviewer_closeerrortab" );
}
/* public slot */
void KitaImgTabWidget::slotShowFitToWin()
{
- KitaImgView* view = isImgView( currentPage() );
- if( view ) view->slotFitToWin();
+ fitImageToWin( currentPage() );
}
void KitaImgTabWidget::slotCancelMosaic()
{
KitaImgView* view = isImgView( currentPage() );
- if( view && view->mosaic() ){
- QRect rt = view->rect();
- int wd = view->imgWidth();
- int ht = view->imgHeight();
- view->slotCancelMosaic();
+ if( view
+ && Kita::ImgManager::mosaic( view->url() )
+ ){
+ /* Calling KitaImgView::slotCancelMosaic() in KitaImgView::slotPopupMenu()
+ will crush the Kita, because popupMenu SIGNAL is emitted
+ from KViewViewer ( and KViewViewer is deleted in
+ KitaImgView::createKView() ). So, mosaic should be canceled later.
+
+ See also customEvent(), KitaImgView::slotPopupMenu(),
+ KitaImgView::slotShowImage(), and KitaImgView::createKView() . */
+ CancelMosaicEvent* e = new CancelMosaicEvent( view );
+ QApplication::postEvent( this, e ); // Qt will delete it when done
+ }
+}
- /* resize */
- if( rt.right()-rt.left() < wd
- || rt.bottom()-rt.top() < ht ){
+
+
+/* public slot */
+void KitaImgTabWidget::slotCancelAllMosaic()
+{
+ int max = count();
+ if( max == 0 ) return;
+
+ int i = 0;
+
+ while( i < max ){
- /* The image is not shown here, and kview can't get the exact image size.
- So, post custom event, and fit image size after showing it. */
- FitImageToWinEvent* e = new FitImageToWinEvent();
+ KitaImgView* view = isImgView( page( i ) );
+ if( view
+ && Kita::ImgManager::mosaic( view->url() )
+ ){
+ CancelMosaicEvent* e = new CancelMosaicEvent( view );
QApplication::postEvent( this, e ); // Qt will delete it when done
}
+
+ i++;
}
}
-
/* public slot */
void KitaImgTabWidget::slotCopyURL()
{
void KitaImgTabWidget::slotOpenBrowser(){
KitaImgView* view = isImgView( currentPage() );
- if( view ) KRun::runURL( view->url(), "text/html" );
+ if( view ) {
+ int code = Kita::ImgManager::code( view->url() );
+ if( code != 200 ) KRun::runURL( view->url(), "text/html" );
+ else {
+ KRun::runURL( Kita::ImgManager::getPath( view->url() ), "text/html" );
+ }
+ }
+}
+
+
+/* public slot */
+void KitaImgTabWidget::slotDelete()
+{
+ KitaImgView* view = isImgView( currentPage() );
+ if( view ){
+ if( Kita::ImgManager::deleteCache( view->url(), this ) ) slotCloseCurrentTab();
+ }
+}
+
+
+/* public slot */
+void KitaImgTabWidget::slotCopy()
+{
+ KitaImgView* view = isImgView( currentPage() );
+ if( view ){
+ Kita::ImgManager::copyCache( view->url(), this );
+ }
}
+/* public slot */
+void KitaImgTabWidget::slotCloseErrorTab()
+{
+ int max = count();
+ if( max == 0 ) return;
+
+ int i = 0, i2 = 0;
+
+ while( i < max ){
+
+ KitaImgView* view = isImgView( page( i ) );
+ if( view ){
+ int code = Kita::ImgManager::code( view->url() );
+
+ if( code != 200 ) slotCloseTab( i2 );
+ else i2++;
+ }
+ else i2++;
+
+ i++;
+ }
+}
+
+
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
KPopupMenu* popup = new KPopupMenu( this );
KActionCollection * collection = static_cast<KitaImgTabWidget*>( parentWidget() )->actionCollection();
plugDefaultActions( popup );
-
+ collection->action( "imgviewer_closeerrortab" )->plug( popup );
+
popup->insertSeparator();
collection->action( "imgviewer_cancelmosaic" )->plug( popup );
+ collection->action( "imgviewer_cancelallmosaic" )->plug( popup );
collection->action( "imgviewer_fittowin" )->plug( popup );
collection->action( "imgviewer_original" )->plug( popup );
+ popup->insertSeparator();
collection->action( "imgviewer_openbrowser" )->plug( popup );
collection->action( "imgviewer_copyurl" )->plug( popup );
+ collection->action( "imgviewer_copy" )->plug( popup );
+ collection->action( "imgviewer_delete" )->plug( popup );
popup->insertSeparator();
collection->action( "tab_configkeys" )->plug( popup );
-
popup->exec( e->globalPos() );
delete popup;
if( m_imgTab ) m_imgTab->slotOpenURL( url );
}
-
-
-
-/*--------------------------------------------------------------------------*/
-/*--------------------------------------------------------------------------*/
-/*--------------------------------------------------------------------------*/
-
-/* Image Viewer Widget */
-/* KViewViewer is embedded in the viewer */
-
-KitaImgView::KitaImgView( const KURL& url,
- QWidget* parent, const char* name, WFlags fl )
- : QWidget( parent, name, fl )
-{
- m_url = url;
- m_part = NULL;
- m_mosaic = TRUE;
- m_layout = new QVBoxLayout( this, 0, 0, "BoxLayout");
- m_wd = 0;
- m_ht = 0;
-
- /* download image file */
- QString tmpFile;
- if ( KIO::NetAccess::download( m_url, tmpFile ) ){
-
- m_orgimg = QImage( tmpFile );
-
- if( !m_orgimg.isNull() ){
-
- m_wd = m_orgimg.width();
- m_ht = m_orgimg.height();
-
- /* create icon */
- m_icon.convertFromImage( m_orgimg.scale( 32, 32, QImage::ScaleMin ) );
- }
-
- KIO::NetAccess::removeTempFile( tmpFile );
- }
-}
-
-
-KitaImgView::~KitaImgView()
-{
- if( m_part ) delete m_part->widget();
- if( m_layout ) delete m_layout;
-}
-
-
-/* public */
-const KURL KitaImgView::url() const
-{
- return m_url;
-}
-
-
-/* public */
-const QPixmap& KitaImgView::icon() {
- return m_icon;
-}
-
-
-/* public */
-const bool KitaImgView::mosaic(){
- return m_mosaic;
-}
-
-
-/* public */
-const int KitaImgView::imgWidth(){
- return m_wd;
-}
-
-
-/* public */
-const int KitaImgView::imgHeight(){
- return m_ht;
-}
-
-
-/* public slot */
-void KitaImgView::slotShowImage()
-{
- if( m_orgimg.isNull() ) return;
-
- createKView();
-
- if( m_part ){
- if( m_mosaic ){
- QImage img = m_orgimg.scale( 48, 48, QImage::ScaleMin).scale( m_wd, m_ht, QImage::ScaleMin );
- emit newImage( img );
- }
- else{
- emit newImage( m_orgimg );
- m_orgimg = QImage(); /* reset */
- }
- }
-}
-
-
-/* public slot */
-void KitaImgView::slotCancelMosaic()
-{
- if( !m_mosaic ) return;
- m_mosaic = FALSE;
- slotShowImage();
-}
-
-
-/* public slot */
-void KitaImgView::slotFitToWin()
-{
- if( m_part ) m_part->action( "fittowin" )->activate();
-}
-
-
-/* public slot */
-void KitaImgView::slotOriginalSize()
-{
- if( m_part ){
- KSelectAction* act = static_cast< KSelectAction* >( m_part->action( "view_zoom" ));
- QStringList items = act->items();
-
- int i = 0;
- QStringList::iterator it = items.begin();
- for ( ; it != items.end(); ++it, ++i ){
- if( (*it) == "100%" ) break;
- }
- act->setCurrentItem( i );
- act->activate();
- }
-}
-
-
-
-/* private slot */
-void KitaImgView::slotPopupMenu( KXMLGUIClient* , const QPoint& global, const KURL& , const QString& , mode_t )
-{
- if( !m_part ) return;
-
- KPopupMenu *popup = new KPopupMenu( this );
-
- m_part->action( "fittowin" )->plug( popup );
- m_part->action( "view_zoom" )->plug( popup );
- m_part->action( "zoomin" )->plug( popup );
- m_part->action( "zoomout" )->plug( popup );
- if( m_part->action( "rotateCW" ) ) m_part->action( "rotateCW" )->plug( popup );
- if( m_part->action( "rotateCCW" ) ) m_part->action( "rotateCCW" )->plug( popup );
-
- popup->exec( global );
- delete popup;
-}
-
-
-/* create kviewviewer and connect signals */ /* private */
-void KitaImgView::createKView()
-{
- /* remove the previous part */
-
- /* Emitting newImage signal without removing the previous part
- always opens the "save as" dialog box.
- So, to avoid it, you need to remove the previous part here. */
- if( m_part ) delete m_part->widget();
- m_part = NULL;
-
- /* create part */
- KLibrary* lib = KLibLoader::self()->library( "libkviewviewer" );
- KLibFactory* factory;
- if( lib ) factory = lib->factory();
- if( ! lib || ! factory ){
- QMessageBox::critical( parentWidget(), i18n( " Load Error" ),
- QString( i18n( "can't load libkviewviewer.") ) );
- return;
- }
-
- m_part = static_cast<KParts::ReadWritePart *>
- ( factory->create( this, 0L, "KParts::ReadWritePart" ) );
-
- if( !m_part ){
- QMessageBox::critical( parentWidget(), i18n( " Load Error" ),
- QString( i18n( "can't create KViewViewer.") ) );
- return;
- }
-
- m_layout->addWidget( m_part->widget() );
-
- connect( this, SIGNAL( newImage( const QImage & ) ),
- m_part, SLOT( newImage( const QImage & ) ));
-
- KParts::BrowserExtension* ext = KParts::BrowserExtension::childObject( m_part );
- if( ext ){
- connect( ext, SIGNAL( popupMenu( KXMLGUIClient*, const QPoint&,
- const KURL&, const QString&, mode_t ) ),
- SLOT( slotPopupMenu( KXMLGUIClient* , const QPoint& , const KURL& , const QString& , mode_t ) ) );
- }
-
- m_part->widget()->show();
-}
#include "kitatabwidgetbase.h"
-#include <kurl.h>
-#include <qimage.h>
-
-#include <sys/types.h>
-
+class KURL;
class KitaImgView;
-namespace KParts{
- class ReadWritePart;
-}
-
-
/*------------------------------------------------*/
public:
KitaImgTabWidget( QWidget* parent, const char* name = 0, WFlags fl = 0 );
~KitaImgTabWidget();
-
+
public slots:
void slotOpenURL( const KURL& url );
-
+ void slotCloseImgView( const KURL& url );
+ void slotUpdateView( const KURL& url );
+
protected:
virtual void customEvent( QCustomEvent * e );
virtual void deleteWidget( QWidget* w );
private:
+ KitaImgView* createImgView( const KURL& url );
KitaImgView* findImgView( const KURL& url );
KitaImgView* isImgView( QWidget* w );
-
+ void fitImageToWin( QWidget* w );
+
/*------------------------------------*/
/* Image View actions */
public slots:
void slotCancelMosaic();
+ void slotCancelAllMosaic();
void slotShowFitToWin();
void slotOriginalSize();
void slotCopyURL();
void slotOpenBrowser();
+ void slotDelete();
+ void slotCopy();
+ void slotCloseErrorTab();
};
};
-
-/*--------------------------------------------------*/
-
-
-class KitaImgView: public QWidget
-{
- Q_OBJECT
-
- KParts::ReadWritePart *m_part;
- QVBoxLayout* m_layout;
-
- KURL m_url;
- QPixmap m_icon;
- QImage m_orgimg;
- bool m_mosaic;
- int m_wd;
- int m_ht;
-
-public:
- KitaImgView( const KURL& url, QWidget* parent, const char* name, WFlags fl );
- ~KitaImgView();
-
- const KURL url() const;
- const QPixmap& icon();
- const bool mosaic();
- const int imgWidth();
- const int imgHeight();
-
-public slots:
- void slotShowImage();
- void slotCancelMosaic();
- void slotFitToWin();
- void slotOriginalSize();
-
-private slots:
- void slotPopupMenu( KXMLGUIClient* , const QPoint& global, const KURL& , const QString& , mode_t );
-
-private:
- void createKView();
-
-signals:
- void newImage( const QImage & );
- void popupMenu( KXMLGUIClient*, const QPoint&, const KURL&, const QString&, mode_t );
-};
-
#endif
class KLibFactory;
class KURL;
+class KitaImgView;
namespace KParts
{
#define EVENT_CloseTab ( QEvent::User + 100 )
#define EVENT_ShowDock ( QEvent::User + 101 )
#define EVENT_FitImageToWinEvent ( QEvent::User + 102 )
+#define EVENT_CancelMoszicEvent ( QEvent::User + 103 )
/* FitImageToWinEvent is used in kitaimgviewer.cpp */
class FitImageToWinEvent : public QCustomEvent
{
+ QWidget* m_w;
+
+ public:
+ FitImageToWinEvent( QWidget* w ):QCustomEvent( EVENT_FitImageToWinEvent ), m_w( w ){}
+ QWidget* getWidget() const { return m_w; }
+};
+
+
+/* CancelMosaicEvent is used in kitaimgviewer.cpp */
+class CancelMosaicEvent : public QCustomEvent
+{
+ KitaImgView* m_imgview;
+
public:
- FitImageToWinEvent():QCustomEvent( EVENT_FitImageToWinEvent ){}
+ CancelMosaicEvent( KitaImgView* imgview ):QCustomEvent( EVENT_CancelMoszicEvent ), m_imgview( imgview ){}
+ KitaImgView* getView() const { return m_imgview; }
};
+
#endif
lib_LTLIBRARIES = libkita.la
-libkita_la_SOURCES = thread.h thread.cpp qcp932codec.cpp qcp932codec.h board.h board.cpp bbs.h bbs.cpp category.h category.cpp favoritethreads.h favoritethreads.cpp k2ch_articlefile.h k2ch_articlefile.cpp kita_misc.cpp threadinfo.h threadinfo.cpp access.cpp cache.cpp favoriteboards.cpp parsemisc.cpp kitaconfig.cpp datmanager.cpp datinfo.cpp signalcollection.cpp account.cpp
+libkita_la_SOURCES = thread.h thread.cpp qcp932codec.cpp qcp932codec.h board.h board.cpp bbs.h bbs.cpp category.h category.cpp favoritethreads.h favoritethreads.cpp k2ch_articlefile.h k2ch_articlefile.cpp kita_misc.cpp threadinfo.h threadinfo.cpp access.cpp cache.cpp favoriteboards.cpp parsemisc.cpp kitaconfig.cpp datmanager.cpp datinfo.cpp signalcollection.cpp account.cpp imgmanager.cpp
METASOURCES = AUTO
SUBDIRS = tests
-noinst_HEADERS = kita_misc.h access.h cache.h favoriteboards.h parsemisc.h kitaconfig.h datmanager.h datinfo.h signalcollection.cpp account.h
+noinst_HEADERS = kita_misc.h access.h cache.h favoriteboards.h parsemisc.h kitaconfig.h datmanager.h datinfo.h signalcollection.cpp account.h imgmanager.h
if ( path == QString::null ) return QString::null;
return baseDir() + path;
}
+
+
+/*------------------------------------*/
+/* for Image files */
+
+
+/* public */
+QString Cache::getImgPath( const KURL& url )
+{
+ return baseDir() + "image/" + subDir( url ) + "/" + getImgFileName( url );
+}
+
+
+/* path for image index */ /* public */
+QString Cache::getImgIdxPath( const KURL& url )
+{
+ return getImgPath( url ) + ".idx";
+}
+
+
+/* private */
+QString Cache::subDir( const KURL& url )
+{
+ QString host = url.host().lower();
+ int l = host.length();
+ for ( int i = 0; i < l; i++ ) {
+ if ( host[ i ].isLetter() && ( host[ i ] != 'w' ) ) {
+ return QString( host[ i ] );
+ }
+ }
+ return "0";
+}
+
+
+/* private */
+QString Cache::hashString( const KURL& url )
+{
+ unsigned long hash = 0x00000000;
+ QCString u = url.url().latin1();
+ for ( int i = u.length(); i--; ) {
+ hash = ( hash * 12211 + u[ i ] ) % 2147483563;
+ }
+
+ QString ret;
+ ret.sprintf( "%08lx", hash );
+
+ return ret;
+}
+
+
+/* private */
+QString Cache::getImgBaseDir()
+{
+ QString basedir = baseDir() + "image/";
+ return basedir;
+}
+
+
+/* private */
+QString Cache::getImgFileName( const KURL& url )
+{
+ QString host = url.host().lower();
+ host.replace( QChar( '.' ), QChar( '_' ) );
+
+ QString filename = url.fileName().lower();
+
+ return host + "_" + hashString( url ) + filename;
+}
class Cache
{
static QString baseDir();
+ static QString subDir( const KURL& url );
+ static QString hashString( const KURL& url );
+ static QString getImgBaseDir();
+ static QString getImgFileName( const KURL& src);
+
public:
static QString getPath( const KURL& url );
+ static QString getImgPath( const KURL& url);
+ static QString getImgIdxPath( const KURL& url);
};
}
--- /dev/null
+/**************************************************************************
+* Copyright (C) 2003,2004 by Hideki Ikemoto , (c) 2004 by 421 *
+* ikemo@wakaba.jp *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+**************************************************************************/
+
+/* Image Manager class */
+
+#include "imgmanager.h"
+#include "cache.h"
+
+#include <kurl.h>
+#include <kdeversion.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kconfig.h>
+
+#include <qregexp.h>
+#include <qfile.h>
+#include <qdatastream.h>
+#include <qmessagebox.h>
+#include <qapplication.h>
+#include <qimage.h>
+
+using namespace Kita;
+
+ImgManager* ImgManager::instance = NULL;
+QMutex ImgManager::m_mutex;
+
+/*-----------------------------------------------------------*/
+
+
+ImgManager::ImgManager( QWidget* mainwidget )
+{
+ m_loaderList.clear();
+ m_imgDatDict.clear();
+ m_mainwidget = mainwidget;
+}
+
+
+ImgManager::~ImgManager()
+{
+ /* delete all loaders */
+ FileLoader* loader;
+ QPtrListIterator< FileLoader > it( m_loaderList );
+ while( ( loader = it.current() ) != NULL ){
+ delete loader;
+ ++it;
+ }
+}
+
+
+/* call this first */ /* public */ /* static */
+void ImgManager::setup( QWidget* mainwidget )
+{
+ instance = new ImgManager( mainwidget );
+}
+
+
+/* public */ /* static */
+void ImgManager::deleteInstance()
+{
+ if( instance ) delete instance;
+}
+
+
+/* public */ /* static */
+ImgManager* ImgManager::getInstance()
+{
+ return instance;
+}
+
+
+/* public */ /* static */
+bool ImgManager::isImgFile( const KURL& url, bool use_mimetype )
+{
+ QMutexLocker locker( &m_mutex );
+
+ return instance->isImgFilePrivate( url, use_mimetype );
+}
+
+
+/* public */ /* static */
+bool ImgManager::load( const KURL& url )
+{
+ QMutexLocker locker( &m_mutex );
+
+ return instance->loadPrivate( url );
+}
+
+
+/* public */ /* static */
+void ImgManager::stop( const KURL& url )
+{
+ QMutexLocker locker( &m_mutex );
+
+ instance->stopPrivate( url );
+}
+
+
+/* public */ /* static */
+QString ImgManager::getPath( const KURL& url )
+{
+ return Cache::getImgPath( url );
+}
+
+
+/* public */ /* static */
+bool ImgManager::isLoadingNow( const KURL& url )
+{
+ QMutexLocker locker( &m_mutex );
+
+ return instance->isLoadingNowPrivate( url );
+}
+
+
+/* public */ /* static */
+bool ImgManager::deleteCache( const KURL& url, QWidget* parent )
+{
+ QMutexLocker locker( &m_mutex );
+
+ return instance->deleteCachePrivate( url, parent );
+}
+
+
+/* public */ /* static */
+bool ImgManager::copyCache( const KURL& url, QWidget* parent )
+{
+ QMutexLocker locker( &m_mutex );
+
+ return instance->copyCachePrivate( url, parent );
+}
+
+
+/* public */ /* static */
+bool ImgManager::mosaic( const KURL& url )
+{
+ instance->cacheExists( url ); /* to create IMGDAT if cache exists */
+
+ IMGDAT* imgdat = instance->getImgDat( url );
+ if( !imgdat ) return TRUE;
+
+ return imgdat->mosaic;
+}
+
+
+/* public */ /* static */
+void ImgManager::setMosaic( const KURL& url, bool status )
+{
+ instance->setMosaicPrivate( url, status );
+}
+
+
+/* return -1 if IMGDAT doesn't exist. */ /* public */ /* static */
+int ImgManager::code( const KURL& url )
+{
+ instance->cacheExists( url ); /* to create IMGDAT if cache exists */
+
+ IMGDAT* imgdat = instance->getImgDat( url );
+ if( !imgdat ) return -1;
+
+ return imgdat->code;
+}
+
+
+/* public */ /* static */
+unsigned int ImgManager::size( const KURL& url )
+{
+ instance->cacheExists( url ); /* to create IMGDAT if cache exists */
+
+ IMGDAT* imgdat = instance->getImgDat( url );
+ if( !imgdat ) return 0;
+
+ return imgdat->size;
+}
+
+
+/* public */ /* static */
+int ImgManager::width( const KURL& url )
+{
+ instance->cacheExists( url ); /* to create IMGDAT if cache exists */
+
+ IMGDAT* imgdat = instance->getImgDat( url );
+ if( !imgdat ) return 0;
+ if( imgdat->width == 0 ) instance->getSize( url );
+
+ return imgdat->width;
+}
+
+
+/* public */ /* static */
+int ImgManager::height( const KURL& url )
+{
+ instance->cacheExists( url ); /* to create IMGDAT if cache exists */
+
+ IMGDAT* imgdat = instance->getImgDat( url );
+ if( !imgdat ) return 0;
+ if( imgdat->height == 0 ) instance->getSize( url );
+
+ return imgdat->height;
+}
+
+
+/* get icon pixmap */ /* public */ /* static */
+QPixmap ImgManager::icon( const KURL& url )
+{
+ const int iconsize = 32;
+
+ /*---------------------------*/
+
+ QPixmap pixmap;
+ QString path = Cache::getImgPath( url );
+ QImage img = QImage( path );
+ if( img.isNull() ) return QPixmap();
+
+ pixmap.convertFromImage( img.scale( iconsize, iconsize, QImage::ScaleMin ) );
+ return pixmap;
+}
+
+
+/*---------------------------------*/
+/* internal functions */
+
+
+/* private */
+bool ImgManager::isImgFilePrivate( const KURL& url, bool use_mimetype )
+{
+ /* don't use mimetype */
+ if( !use_mimetype ){
+
+ QStringList extlist; // = KitaConfig::imgExtList();
+ extlist = "jpg";
+ extlist += "jpeg";
+ extlist += "gif";
+ extlist += "png";
+ extlist += "bmp";
+
+ for ( QStringList::iterator it = extlist.begin(); it != extlist.end(); ++it ){
+ QRegExp reg_ext = ".*\\."+(*it)+"$";
+ if ( reg_ext.search( url.fileName().lower() ) != -1 ) return TRUE;
+
+ }
+
+ return FALSE;
+ }
+
+ /*-----------------------------------*/
+
+ /* use mimetype ( very slow! ) */
+ if( cacheExists( url ) ) return TRUE;
+
+#if KDE_IS_VERSION( 3, 2, 0 )
+ QString mimetype = KIO::NetAccess::mimetype( url, m_mainwidget );
+#else
+ QString mimetype = KIO::NetAccess::mimetype( url );
+#endif
+ if( mimetype.left( 6 ) == "image/" ) return TRUE;
+
+ return FALSE;
+}
+
+
+/* create new loader and start loading the image */
+/* when done, ImgManager emits finishImgLoad SIGNAL. */ /* private */
+bool ImgManager::loadPrivate( const KURL& url )
+{
+ const unsigned int maxload = 5; // = KitaConfig::maxImgLoader();
+
+ /*-----------------------------------------*/
+
+ if( isLoadingNowPrivate( url ) ) return FALSE;
+
+ /* cache exists? */
+ if( cacheExists( url ) ){
+
+ /* create EmitFinishEvent to emit finishImgLoad SIGNAL later. */
+ /* See also customEvent(). */
+ EmitFinishEvent* e = new EmitFinishEvent( url );
+ QApplication::postEvent( this, e ); // Qt will delete it when done
+
+ return TRUE;
+ }
+
+ if( m_loaderList.count() >= maxload ) return FALSE;
+
+ /* create directry of cache */
+ QString path = Cache::getImgPath( url );
+ KURL cacheDir = KURL( path, "." );
+ KURL cacheDir2 = KURL( cacheDir, ".." );
+#if KDE_IS_VERSION( 3, 2, 0 )
+ if ( !KIO::NetAccess::exists( cacheDir2, TRUE, m_mainwidget ) ) KIO::NetAccess::mkdir( cacheDir2, m_mainwidget );
+ if ( !KIO::NetAccess::exists( cacheDir, TRUE, m_mainwidget ) ) KIO::NetAccess::mkdir( cacheDir, m_mainwidget );
+#else
+ if ( !KIO::NetAccess::exists( cacheDir2 ) ) KIO::NetAccess::mkdir( cacheDir2 );
+ if ( !KIO::NetAccess::exists( cacheDir ) ) KIO::NetAccess::mkdir( cacheDir );
+#endif
+
+ deleteImgDat( url );
+
+ /* create new loader, and start loading the file */
+ FileLoader* loader = new FileLoader( url, path );
+ if( loader->get() ){
+ m_loaderList.append( loader );
+
+ connect( loader, SIGNAL( data( Kita::FileLoader* ) ),
+ SLOT( slotData( Kita::FileLoader* ) ) );
+
+ connect( loader, SIGNAL( result( Kita::FileLoader* ) ),
+ SLOT( slotResult( Kita::FileLoader* ) ) );
+ }
+ else{
+ deleteLoader( loader );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/* stop loading */ /* private */
+void ImgManager::stopPrivate( const KURL& url )
+{
+ FileLoader* loader = getLoader( url );
+ if( !loader ) return;
+
+ loader->stopJob(); /* slotResult() will be called later. */
+}
+
+
+/* private */
+bool ImgManager::isLoadingNowPrivate( const KURL& url )
+{
+ if( getLoader( url ) ) return TRUE;
+
+ return FALSE;
+}
+
+
+/* delete cache */
+/* when done, cacheDeleted SIGNAL emitted */ /* private */
+bool ImgManager::deleteCachePrivate( const KURL& url, QWidget* parent )
+{
+ if( !cacheExists( url ) ) return FALSE;
+
+ if( QMessageBox::warning( parent,
+ "Kita",
+ i18n( "Do you want to delete the image ?" ),
+ QMessageBox::Ok, QMessageBox::Cancel | QMessageBox::Default )
+ ==QMessageBox::Ok ){
+
+ bool ret;;
+
+ QString path = Cache::getImgPath( url );
+ QString idxpath = Cache::getImgIdxPath( url );
+
+#if KDE_IS_VERSION( 3, 2, 0 )
+ KIO::NetAccess::del( idxpath, m_mainwidget );
+ ret = KIO::NetAccess::del( path, m_mainwidget );
+#else
+ KIO::NetAccess::del( idxpath );
+ ret = KIO::NetAccess::del( path );
+#endif
+
+ if( ret ){
+ deleteImgDat( url );
+ emit cacheDeleted( url );
+ }
+
+ return ret;
+ }
+
+ return FALSE;
+}
+
+
+/* copy cache */ /* public */
+bool ImgManager::copyCachePrivate( const KURL& url, QWidget* parent )
+{
+ if( !cacheExists( url ) ) return FALSE;
+
+ /* make filter */
+ QString filter;
+ QString file = url.fileName().lower();
+ int i = file.findRev('.');
+ if(i == -1) filter = "*|All files";
+ else{
+ QString ext = file.mid(i);
+ filter = "*"+ext+"|*"+ext;
+ }
+
+ /* get filename */
+ QString savefile = KFileDialog::getSaveFileName( url.fileName(), filter,parent );
+ if( savefile.isEmpty() ) return FALSE;
+
+ /* file exists */
+ if(
+#if KDE_IS_VERSION( 3, 2, 0 )
+ KIO::NetAccess::exists( savefile, TRUE, m_mainwidget )
+#else
+ KIO::NetAccess::exists( savefile )
+#endif
+ ){
+
+ if(QMessageBox::warning( parent,
+ "Kita",
+ i18n( "Do you want to replace the file?" ),
+ QMessageBox::Ok, QMessageBox::Cancel | QMessageBox::Default )
+ != QMessageBox::Ok ) return FALSE;
+
+#if KDE_IS_VERSION( 3, 2, 0 )
+ KIO::NetAccess::del( savefile, m_mainwidget );
+#else
+ KIO::NetAccess::del( savefile );
+#endif
+ }
+
+ /* copy */
+ QString src = Cache::getImgPath( url );
+
+#if KDE_IS_VERSION( 3, 2, 0 )
+ KIO::NetAccess::copy( src, savefile, m_mainwidget );
+#else
+ KIO::NetAccess::copy( src, savefile );
+#endif
+
+ return TRUE;
+}
+
+
+/* private */
+void ImgManager::setMosaicPrivate( const KURL& url, bool status )
+{
+ IMGDAT* imgdat = getImgDat( url );
+ if( !imgdat ) return;
+ if( imgdat->code != 200 ) return;
+
+ imgdat->mosaic = status;
+
+ /* save status */
+ KConfig cfg( Cache::getImgIdxPath( url ) );
+ cfg.writeEntry( "Mosaic", status );
+}
+
+
+/* get loader from url */ /* private */
+FileLoader* ImgManager::getLoader( const KURL& url )
+{
+ if( m_loaderList.count() == 0 ) return NULL;
+
+ FileLoader* loader;
+ QPtrListIterator< FileLoader > it( m_loaderList );
+ while( ( loader = it.current() ) != NULL ){
+
+ if( loader->url() == url ){
+ return loader;
+ }
+ ++it;
+ }
+
+ return NULL;
+}
+
+
+/* delete loader */ /* private */
+void ImgManager::deleteLoader( FileLoader* loader )
+{
+ /* Deleting the FileLoader in the call-backed
+ functions ( e.g. slotResult() ) causes many
+ problems. Maybe kita will crush. So,
+ delete it later. See also customEvent(). */
+ DeleteLoaderEvent* e = new DeleteLoaderEvent( loader );
+ QApplication::postEvent( this, e ); // Qt will delete it when done
+}
+
+
+/* private */
+void ImgManager::createImgDat( const KURL& url, int code )
+{
+ IMGDAT* imgdat = getImgDat( url );
+ if( !imgdat ){
+ imgdat = new IMGDAT;
+ m_imgDatDict.insert( url.prettyURL(), imgdat );
+ }
+
+ KConfig cfg( Cache::getImgIdxPath( url ) );
+ if( code == 200 ) cfg.writeEntry( "URL", url.prettyURL() );
+
+ imgdat->mosaic = cfg.readBoolEntry( "Mosaic", TRUE );
+ imgdat->height = cfg.readNumEntry( "Height", 0 );
+ imgdat->width = cfg.readNumEntry( "Width", 0 );
+ imgdat->size = cfg.readUnsignedNumEntry( "Size", 0 );
+ imgdat->code = code;
+}
+
+
+/* private */
+IMGDAT* ImgManager::getImgDat( const KURL& url )
+{
+ return m_imgDatDict.find( url.prettyURL() );
+}
+
+
+/* private */
+void ImgManager::deleteImgDat( const KURL& url )
+{
+ IMGDAT* imgdat = getImgDat( url );
+ if( !imgdat ) return;
+
+ if( m_imgDatDict.remove( url.prettyURL() )){
+ delete imgdat;
+ }
+}
+
+
+/* private */
+void ImgManager::getSize( const KURL& url )
+{
+ IMGDAT* imgdat = getImgDat( url );
+ if( !imgdat ) return;
+ if( imgdat->code != 200 ) return;
+
+ QString path = Cache::getImgPath( url );
+ QImage img = QImage( path );
+
+ if( !img.isNull() ){
+
+ imgdat->width = img.width();
+ imgdat->height = img.height();
+
+ /* save size */
+ KConfig cfg( Cache::getImgIdxPath( url ) );
+ cfg.writeEntry( "Height", imgdat->width );
+ cfg.writeEntry( "Width", imgdat->height );
+ }
+}
+
+
+/* private */
+bool ImgManager::cacheExists( const KURL& url )
+{
+ if( isLoadingNowPrivate( url ) ) return FALSE;
+
+ bool ret;
+ QString path = Cache::getImgPath( url );
+
+#if KDE_IS_VERSION( 3, 2, 0 )
+ ret = KIO::NetAccess::exists( path, TRUE, m_mainwidget );
+#else
+ ret = KIO::NetAccess::exists( path );
+#endif
+
+ if( ret && !getImgDat( url ) ) createImgDat( url, 200 );
+
+ return ret;
+}
+
+
+
+/* This slot is called when loader received the data. */ /* private slot */
+void ImgManager::slotData( Kita::FileLoader* loader )
+{
+ /* I assume that file size is smaller than 2^32 byte */
+ unsigned int size = loader->size();
+ unsigned int totalsize = loader->totalsize();
+
+ emit receiveImgData( loader->url(), size, totalsize );
+}
+
+
+/* This slot is called when loading is done. */ /* private slot */
+void ImgManager::slotResult( Kita::FileLoader* loader )
+{
+ createImgDat( loader->url(), loader->code() );
+ m_loaderList.remove( loader );
+
+ /* save size */
+ if( loader->code() == 200 ){
+ unsigned int totalsize = loader->totalsize();
+ KConfig cfg( Cache::getImgIdxPath( loader->url() ) );
+ cfg.writeEntry( "Size", totalsize );
+ }
+
+ emit finishImgLoad( loader->url() );
+
+ deleteLoader( loader );
+}
+
+
+/* protected */ /* virtual */
+void ImgManager::customEvent( QCustomEvent * e )
+{
+ /* delete loader */
+ if ( e->type() == EVENT_DeleteLoader ){
+ FileLoader* loader = static_cast< DeleteLoaderEvent* >( e )->getLoader();
+ if( loader ){
+
+ m_loaderList.remove( loader );
+
+ /* error file is also deleted here. */
+ if( loader->code() != 200 ) KIO::del( loader->path(), FALSE, FALSE );
+
+ delete loader;
+ }
+ }
+
+ /* emit finishImgLoad SIGNAL */
+ else if ( e->type() == EVENT_EmitFinigh ){
+ KURL url = static_cast< EmitFinishEvent* >( e )->url();
+ emit finishImgLoad( url );
+ }
+}
+
+
+
+/*-----------------------------------------------------------*/
+/*-----------------------------------------------------------*/
+/*-----------------------------------------------------------*/
+
+
+
+FileLoader::FileLoader( const KURL& url, const QString& path )
+{
+ m_url = url;
+ m_path = path;
+
+ m_ds = NULL;
+ m_file = NULL;
+ m_totalsize = 0;
+ m_size = 0;
+
+ m_code = 0;
+ m_currentJob = NULL;
+ m_header = QString::null;
+}
+
+FileLoader::~FileLoader()
+{
+ killJob();
+}
+
+
+/* terminate job. */ /* public */
+void FileLoader::killJob()
+{
+ if ( m_currentJob == NULL ) return;
+
+ m_currentJob->kill(); /* without emitting result SIGNAL */
+ m_currentJob = NULL;
+ m_code = 0;
+ closeFile();
+}
+
+
+/* stop job. slotResult is called later. */ /* public */
+void FileLoader::stopJob()
+{
+ if ( m_currentJob ) m_currentJob->kill( FALSE ); /* with emitting result SIGNL */
+}
+
+
+/* start downloading */
+/* When done, signal loadFinished is emitted. */ /* public */
+bool FileLoader::get()
+{
+ /* now loading */
+ if( m_currentJob ) return FALSE;
+
+ m_totalsize = 0;
+ m_size = 0;
+ m_code = 0;
+ m_header = QString::null;
+
+ /* open file */
+ m_file = new QFile( m_path );
+ if( m_file == NULL || ! m_file->open( IO_WriteOnly ) ){
+ closeFile();
+ return FALSE;
+ }
+ m_ds = new QDataStream( m_file );
+
+ /* create job */
+ m_currentJob = KIO::get( m_url, TRUE, FALSE );
+ if( m_currentJob == NULL ){
+ closeFile();
+ return FALSE;
+ }
+
+ connect( m_currentJob, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
+ SLOT( slotData( KIO::Job*, const QByteArray& ) ) );
+
+ connect( m_currentJob, SIGNAL( result(KIO::Job*)),
+ SLOT( slotResult( KIO::Job* ) ) );
+
+ connect( m_currentJob, SIGNAL( redirection( KIO::Job *, const KURL& ) ),
+ SLOT( slotRedirection( KIO::Job *, const KURL& ) ) );
+
+ connect( m_currentJob, SIGNAL( totalSize(KIO::Job*, KIO::filesize_t ) ),
+ SLOT(slotTotalSize( KIO::Job*, KIO::filesize_t ) ) );
+
+ /* use 'HTTP-Headers' metadata.*/
+ m_currentJob->addMetaData( "PropagateHttpHeader", "true" );
+
+ return TRUE;
+}
+
+/* public */
+const bool FileLoader::isRunning() const
+{
+ if( m_currentJob ) return TRUE;
+ return FALSE;
+}
+
+/* public */
+const int FileLoader::code() const
+{
+ return m_code;
+}
+
+/* public */
+const KURL FileLoader::url() const
+{
+ return m_url;
+}
+
+/* public */
+const QString FileLoader::path() const
+{
+ return m_path;
+}
+
+/* public */
+const KIO::filesize_t FileLoader::size() const
+{
+ return m_size;
+}
+
+/* public */
+const KIO::filesize_t FileLoader::totalsize() const
+{
+ return m_totalsize;
+}
+
+
+/* private */
+void FileLoader::closeFile()
+{
+ if( m_file ) m_file->close();
+ if( m_ds ) delete m_ds;
+ if( m_file ) delete m_file;
+
+ m_ds = NULL;
+ m_file = NULL;
+}
+
+/* private */ /* copied from Access::responseCode() */
+int FileLoader::responseCode()
+{
+ // parse HTTP headers
+ QStringList headerList = QStringList::split( "\n", m_header );
+ QRegExp regexp( "HTTP/1\\.[01] ([0-9]+) .*" );
+ QString dateStr = headerList.grep( regexp ) [ 0 ];
+ if ( regexp.search( dateStr ) == -1 ) {
+ // invalid response
+ return 0;
+ } else {
+ return regexp.cap( 1 ).toInt();
+ }
+}
+
+
+/* slots called from job */ /* private slots */
+
+void FileLoader::slotData( KIO::Job* job, const QByteArray& barray )
+{
+ if( job->error() == 0 ){
+
+ m_size += barray.size();
+ m_ds->writeRawBytes( barray.data(), barray.size() );
+
+ emit data( this );
+ }
+}
+
+
+void FileLoader::slotTotalSize( KIO::Job * job, KIO::filesize_t size )
+{
+ if( job->error() == 0 ) m_totalsize = size;
+}
+
+
+void FileLoader::slotRedirection( KIO::Job*, const KURL& )
+{
+ stopJob();
+}
+
+
+void FileLoader::slotResult( KIO::Job* job )
+{
+ m_currentJob = NULL;
+ if ( job->error() ==0 ) m_header = job->queryMetaData( "HTTP-Headers" );
+ m_code = responseCode();
+ closeFile();
+
+ emit result( this );
+}
--- /dev/null
+/**************************************************************************
+* Copyright (C) 2003,2004 by Hideki Ikemoto , (c) 2004 by 421 *
+* ikemo@wakaba.jp *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+**************************************************************************/
+
+#ifndef KITAIMGMANAGER_H
+#define KITAIMGMANAGER_H
+
+#include <kio/job.h>
+
+#include <qobject.h>
+#include <qdict.h>
+#include <qmutex.h>
+#include <qevent.h>
+
+class QFile;
+class QDataStream;
+class QStringList;
+
+struct IMGDAT
+{
+ int code;
+ bool mosaic;
+ int width;
+ int height;
+ unsigned int size;
+};
+
+
+/*----------------------------------------------------------*/
+
+namespace Kita
+{
+ class FileLoader;
+
+ class ImgManager : public QObject
+ {
+ Q_OBJECT
+
+ static ImgManager* instance;
+ static QMutex m_mutex;
+ QPtrList< FileLoader > m_loaderList;
+ QDict< IMGDAT > m_imgDatDict;
+ QWidget* m_mainwidget;
+
+ public:
+ ImgManager( QWidget* mainwidget );
+ ~ImgManager();
+
+ static void setup( QWidget* mainwidget );
+ static void deleteInstance();
+ static ImgManager* getInstance();
+ static bool isImgFile( const KURL& url, bool use_mimetype );
+
+ static bool load( const KURL& url );
+ static void stop( const KURL& url );
+ static QString getPath( const KURL& url );
+ static bool isLoadingNow( const KURL& url );
+ static bool deleteCache( const KURL& url, QWidget* parent );
+ static bool copyCache( const KURL& url, QWidget* parent );
+
+ static bool mosaic( const KURL& url );
+ static void setMosaic( const KURL& url, bool status );
+ static int code( const KURL& url );
+ static int width( const KURL& url );
+ static int height( const KURL& url );
+ static unsigned int size( const KURL& url );
+ static QPixmap icon( const KURL& url );
+
+ private:
+ bool isImgFilePrivate( const KURL& url, bool use_mimetype );
+ bool loadPrivate( const KURL& url );
+ void stopPrivate( const KURL& url );
+ bool isLoadingNowPrivate( const KURL& url );
+ bool deleteCachePrivate( const KURL& url, QWidget* parent );
+ bool copyCachePrivate( const KURL& url, QWidget* parent );
+ void setMosaicPrivate( const KURL& url, bool status );
+
+ FileLoader* getLoader( const KURL& url );
+ void deleteLoader( FileLoader* loader );
+ void createImgDat( const KURL& url, int code );
+ IMGDAT* getImgDat( const KURL& url );
+ void deleteImgDat( const KURL& url );
+ void getSize( const KURL& url );
+ bool cacheExists( const KURL& url );
+
+ private slots:
+ void slotData( Kita::FileLoader* );
+ void slotResult( Kita::FileLoader* );
+
+ protected:
+ virtual void customEvent( QCustomEvent * e );
+
+ signals:
+ void receiveImgData( const KURL&, unsigned int, unsigned int );
+ void finishImgLoad( const KURL& );
+ void cacheDeleted( const KURL& );
+ };
+
+/*---------------------------------------------------------*/
+
+ class FileLoader : public QObject
+ {
+ Q_OBJECT
+
+ KURL m_url;
+ QString m_path;
+
+ /* job */
+ KIO::Job* m_currentJob;
+ int m_code;
+ QString m_header;
+
+ /* file */
+ QFile *m_file;
+ QDataStream *m_ds;
+ KIO::filesize_t m_size;
+ KIO::filesize_t m_totalsize;
+
+ public:
+ FileLoader( const KURL& url, const QString& path );
+ ~FileLoader();
+
+ void killJob();
+ void stopJob();
+ bool get();
+
+ const bool isRunning() const;
+ const int code() const;
+ const KURL url() const;
+ const QString path() const;
+ const KIO::filesize_t size() const;
+ const KIO::filesize_t totalsize() const;
+
+ private:
+ void closeFile();
+ int responseCode();
+
+ private slots:
+ void slotData( KIO::Job* , const QByteArray& );
+ void slotTotalSize( KIO::Job * , KIO::filesize_t );
+ void slotRedirection( KIO::Job* , const KURL& );
+ void slotResult( KIO::Job* );
+
+ signals:
+ void data( Kita::FileLoader* );
+ void result( Kita::FileLoader* );
+ };
+
+}
+
+
+/*---------------------------------------------------------*/
+
+#define EVENT_EmitFinigh ( QEvent::User + 200 )
+#define EVENT_DeleteLoader ( QEvent::User + 201 )
+
+
+class EmitFinishEvent : public QCustomEvent
+{
+ KURL m_url;
+
+ public:
+ EmitFinishEvent( KURL url ):QCustomEvent( EVENT_EmitFinigh ),m_url( url ){}
+
+ KURL url() const { return m_url; }
+};
+
+
+class DeleteLoaderEvent : public QCustomEvent
+{
+ Kita::FileLoader* m_loader;
+
+ public:
+ DeleteLoaderEvent( Kita::FileLoader* loader ):QCustomEvent( EVENT_DeleteLoader )
+ ,m_loader( loader ){}
+
+ Kita::FileLoader* getLoader() const { return m_loader; }
+};
+
+
+
+#endif
libkitapart_la_LIBADD = $(LIB_KPARTS) $(LIB_KHTML) -lkita
-libkitapart_la_SOURCES = kitathreadview.cpp kitathreadviewbase.ui kitathreadpart.cpp kitawritedialogbase.ui kitawritedialog.cpp kita2ch.cpp kitahtmlpart.cpp kitahtmlview.cpp kitadomtree.cpp kitanavi.cpp
+libkitapart_la_SOURCES = kitathreadview.cpp kitathreadviewbase.ui kitathreadpart.cpp kitawritedialogbase.ui kitawritedialog.cpp kita2ch.cpp kitahtmlpart.cpp kitahtmlview.cpp kitadomtree.cpp kitanavi.cpp kitaimgview.cpp
-noinst_HEADERS = kitathreadview.h kitathreadpart.h kitawritedialog.h kita2ch.h kitahtmlpart.h kitahtmlview.h kitadomtree.h kitanavi.h
+noinst_HEADERS = kitathreadview.h kitathreadpart.h kitawritedialog.h kita2ch.h kitahtmlpart.h kitahtmlview.h kitadomtree.h kitanavi.h kitaimgview.h
METASOURCES = AUTO
--- /dev/null
+/***************************************************************************
+* Copyright (C) 2004 by Hideki Ikemoto , (c) 2004 by 421 *
+* ikemo@users.sourceforge.jp *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+***************************************************************************/
+
+/* Image Viewer Widget */
+/* KViewViewer is embedded in the viewer */
+
+#include "kitaimgview.h"
+#include "libkita/imgmanager.h"
+
+#include <klibloader.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kparts/browserextension.h>
+#include <kparts/partmanager.h>
+#include <kaction.h>
+
+#include <qlayout.h>
+#include <qmessagebox.h>
+#include <qimage.h>
+
+
+/*---------------------------------------------------------------*/
+
+
+KitaImgView::KitaImgView( const KURL& url, KActionCollection* action,
+ QWidget* parent, const char* name, WFlags fl )
+ : QWidget( parent, name, fl )
+{
+ m_url = url;
+ m_action = action;
+ m_part = NULL;
+ m_popup = NULL;
+ m_layout = new QVBoxLayout( this, 0, 0, "BoxLayout");
+}
+
+KitaImgView::~KitaImgView()
+{
+ if( m_part ) delete m_part->widget();
+ if( m_layout ) delete m_layout;
+ if( m_popup ) delete m_popup;
+}
+
+
+/* public */
+const KURL KitaImgView::url() const
+{
+ return m_url;
+}
+
+
+/* show image */
+/* If wd == 0 or ht == 0, use original image.size */ /* public slot */
+void KitaImgView::slotShowImage( int wd, int ht )
+{
+
+ const int mosaic_wd = 48;
+ const int mosaic_ht = 48;
+
+ /*-------------------------------------------*/
+
+ if( Kita::ImgManager::code( m_url ) != 200 ) return;
+
+ /* ! notice : createKView deletes current m_part ! */
+ /* see also createKView. */
+ createKView();
+
+ if( m_part ){
+
+ QString path = Kita::ImgManager::getPath( m_url );
+
+ if( Kita::ImgManager::mosaic( m_url ) ){ /* mosaic image */
+
+ QImage orgimg = QImage( path );
+ if( orgimg.isNull() ) return;
+
+ if( wd == 0 || ht == 0 ){
+ wd = Kita::ImgManager::width( m_url );
+ ht = Kita::ImgManager::height( m_url );
+ }
+
+ /* create mosaic */
+ QImage img= orgimg.scale( mosaic_wd, mosaic_ht, QImage::ScaleMin).scale( wd, ht, QImage::ScaleMin );
+
+ if( !img.isNull() ) emit newImage( img );
+ }
+ else{ /* normal image */
+
+ if( wd == 0 || ht == 0 ) m_part->openURL( path );
+ else {
+ /* resize */
+ QImage img = QImage( path ).scale( wd, ht, QImage::ScaleMin );
+ if( !img.isNull() ) emit newImage( img );
+ }
+ }
+ }
+}
+
+
+/* public slot */
+void KitaImgView::slotFitToWin()
+{
+ if( m_part ) m_part->action( "fittowin" )->activate();
+}
+
+
+/* public slot */
+void KitaImgView::slotOriginalSize()
+{
+ if( m_part ){
+ KSelectAction* act = static_cast< KSelectAction* >( m_part->action( "view_zoom" ));
+ QStringList items = act->items();
+
+ int i = 0;
+ QStringList::iterator it = items.begin();
+ for ( ; it != items.end(); ++it, ++i ){
+ if( (*it) == "100%" ) break;
+ }
+ act->setCurrentItem( i );
+ act->activate();
+ }
+}
+
+
+/* popup menu */ /* private slot */
+void KitaImgView::slotPopupMenu( KXMLGUIClient* , const QPoint& global, const KURL& , const QString& , mode_t )
+{
+ if( !m_part ) return;
+
+ if( m_popup ) delete m_popup;
+ m_popup = new KPopupMenu( this );
+
+
+ if( m_action ){
+ if( Kita::ImgManager::mosaic( m_url ) ){
+ if( m_action->action( "imgviewer_cancelmosaic" ) )
+ m_action->action( "imgviewer_cancelmosaic" )->plug( m_popup );
+ m_popup->insertSeparator();
+ }
+ }
+
+ if( m_part->action( "fittowin" ) )
+ m_part->action( "fittowin" )->plug( m_popup );
+
+ if( m_action ){
+ if( m_action->action( "imgviewer_original" ) )
+ m_action->action( "imgviewer_original" )->plug( m_popup );
+ }
+
+ if( m_part->action( "view_zoom" ) )
+ m_part->action( "view_zoom" )->plug( m_popup );
+ if( m_part->action( "zoomin" ) )
+ m_part->action( "zoomin" )->plug( m_popup );
+ if( m_part->action( "zoomout" ) )
+ m_part->action( "zoomout" )->plug( m_popup );
+ if( m_part->action( "rotateCW" ) )
+ m_part->action( "rotateCW" )->plug( m_popup );
+ if( m_part->action( "rotateCCW" ) )
+ m_part->action( "rotateCCW" )->plug( m_popup );
+
+ if( m_action ){
+ m_popup->insertSeparator();
+ if( m_action->action( "imgviewer_openbrowser" ) )
+ m_action->action( "imgviewer_openbrowser" )->plug( m_popup );
+ if( m_action->action( "imgviewer_copy" ) )
+ m_action->action( "imgviewer_copy" )->plug( m_popup );
+ }
+
+ m_popup->exec( global );
+}
+
+
+/* create kviewviewer and connect signals to it */ /* private */
+void KitaImgView::createKView()
+{
+ /* delete the current part */
+ /* Emitting newImage signal without deleting the previous part
+ always opens the "save as" dialog box.
+ So, to avoid it, the part should be deleted here. */
+ if( m_part ) delete m_part->widget();
+ m_part = NULL;
+
+ /* create part */
+ KLibrary* lib = KLibLoader::self()->library( "libkviewviewer" );
+ KLibFactory* factory;
+ if( lib ) factory = lib->factory();
+ if( ! lib || ! factory ){
+ QMessageBox::critical( parentWidget(), i18n( " Load Error" ),
+ QString( i18n( "can't load libkviewviewer.") ) );
+ return;
+ }
+
+ m_part = static_cast<KParts::ReadWritePart *>
+ ( factory->create( this, 0L, "KParts::ReadWritePart" ) );
+
+ if( !m_part ){
+ QMessageBox::critical( parentWidget(), i18n( " Load Error" ),
+ QString( i18n( "can't create KViewViewer.") ) );
+ return;
+ }
+
+ m_layout->addWidget( m_part->widget() );
+
+ connect( this, SIGNAL( newImage( const QImage & ) ),
+ m_part, SLOT( newImage( const QImage & ) ));
+
+ KParts::BrowserExtension* ext = KParts::BrowserExtension::childObject( m_part );
+ if( ext ){
+ connect( ext, SIGNAL( popupMenu( KXMLGUIClient*, const QPoint&,
+ const KURL&, const QString&, mode_t ) ),
+ SLOT( slotPopupMenu( KXMLGUIClient* , const QPoint& , const KURL& , const QString& , mode_t ) ) );
+ }
+
+ m_part->widget()->show();
+}
--- /dev/null
+/***************************************************************************
+* Copyright (C) 2004 by Hideki Ikemoto , (c) 2004 by 421 *
+* ikemo@users.sourceforge.jp *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+***************************************************************************/
+
+#ifndef KITAIMGVIEW_H
+#define KITAIMGVIEW_H
+
+#include <kurl.h>
+#include <qwidget.h>
+
+#include <sys/types.h>
+
+namespace KParts{
+ class ReadWritePart;
+}
+
+class QImage;
+class QVBoxLayout;
+class KXMLGUIClient;
+class KActionCollection;
+class KPopupMenu;
+
+/*----------------------------------------------------*/
+
+class KitaImgView: public QWidget
+{
+ Q_OBJECT
+
+ KParts::ReadWritePart* m_part;
+ QVBoxLayout* m_layout;
+ KURL m_url;
+ KActionCollection* m_action;
+ KPopupMenu* m_popup;
+
+public:
+ KitaImgView( const KURL& url, KActionCollection* action, QWidget* parent, const char* name, WFlags fl );
+ ~KitaImgView();
+
+ const KURL url() const;
+
+public slots:
+ void slotShowImage( int wd, int ht );
+ void slotFitToWin();
+ void slotOriginalSize();
+
+private slots:
+ void slotPopupMenu( KXMLGUIClient* , const QPoint& global, const KURL& , const QString& , mode_t );
+
+private:
+ void createKView();
+
+signals:
+ void newImage( const QImage & ); /* to KviewViewer */
+};
+
+#endif