OSDN Git Service

>>129, image viewer update.
authorikemo <ikemo@56b19765-1e22-0410-a548-a0f45d66c51a>
Mon, 30 Aug 2004 15:19:17 +0000 (15:19 +0000)
committerikemo <ikemo@56b19765-1e22-0410-a548-a0f45d66c51a>
Mon, 30 Aug 2004 15:19:17 +0000 (15:19 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/kita/kita/trunk@1344 56b19765-1e22-0410-a548-a0f45d66c51a

12 files changed:
kita/src/kita.cpp
kita/src/kitaimgtabwidget.cpp
kita/src/kitaimgtabwidget.h
kita/src/kitatabwidgetbase.h
kita/src/libkita/Makefile.am
kita/src/libkita/cache.cpp
kita/src/libkita/cache.h
kita/src/libkita/imgmanager.cpp [new file with mode: 0644]
kita/src/libkita/imgmanager.h [new file with mode: 0644]
kita/src/part/Makefile.am
kita/src/part/kitaimgview.cpp [new file with mode: 0644]
kita/src/part/kitaimgview.h [new file with mode: 0644]

index 6d61058..8cf2092 100644 (file)
@@ -27,6 +27,7 @@
 #include "libkita/signalcollection.h"
 #include "libkita/parsemisc.h"
 #include "libkita/account.h"
+#include "libkita/imgmanager.h"
 
 #include <qdragobject.h>
 #include <qtextcodec.h>
@@ -66,6 +67,9 @@ KitaMainWindow::KitaMainWindow()
     // accept dnd
     setAcceptDrops( true );
 
+    // setup imgmanager
+    Kita::ImgManager::setup( this );
+
     // setup view, dock
     setupView();
 
@@ -702,21 +706,10 @@ void KitaMainWindow::slotOpenURLRequest( const KURL& url, const KParts::URLArgs&
        /* 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 */
index b335f75..0fdea85 100644 (file)
@@ -8,23 +8,21 @@
 *   (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>
@@ -39,6 +37,14 @@ KitaImgTabWidget::KitaImgTabWidget( QWidget* parent, const char* name, WFlags fl
     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& ) ) );
 }
 
 
@@ -55,16 +61,65 @@ void KitaImgTabWidget::slotOpenURL( const KURL& url )
     }
 
     /* 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 );
+       }       
     }
 }
 
@@ -73,13 +128,43 @@ void KitaImgTabWidget::slotOpenURL( const KURL& url )
 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 ) {
@@ -89,6 +174,21 @@ void KitaImgTabWidget::deleteWidget( QWidget* w )
 
 
 /* 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();
@@ -119,6 +219,15 @@ KitaImgView* KitaImgTabWidget::isImgView( QWidget* w )
 }
 
 
+/* 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 */
@@ -134,6 +243,13 @@ void KitaImgTabWidget::setupActions(){
                  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,
@@ -161,14 +277,34 @@ void KitaImgTabWidget::setupActions(){
                  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() );
 }
 
 
@@ -184,26 +320,46 @@ void KitaImgTabWidget::slotOriginalSize()
 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()
 {
@@ -224,11 +380,61 @@ 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++;
+    }
+}
+
+
 
 /*--------------------------------------------------------------------------*/
 /*--------------------------------------------------------------------------*/
@@ -246,17 +452,21 @@ void KitaImgTabBar::contextMenuEvent( QContextMenuEvent* e )
     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;
@@ -305,200 +515,3 @@ void KitaImgDock::slotOpenURL( const KURL& url )
     
     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();
-}
index 60615a3..c2f99e9 100644 (file)
 
 #include "kitatabwidgetbase.h"
 
-#include <kurl.h>
-#include <qimage.h>
-
-#include <sys/types.h>
-
+class KURL;
 class KitaImgView;
 
-namespace KParts{
-    class ReadWritePart;
-}
-
-
 /*------------------------------------------------*/
 
 
@@ -35,18 +26,22 @@ class KitaImgTabWidget : public KitaTabWidgetBase
 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 */
     
@@ -55,10 +50,14 @@ private:
 
 public slots:
     void slotCancelMosaic();
+    void slotCancelAllMosaic(); 
     void slotShowFitToWin();
     void slotOriginalSize();
     void slotCopyURL();
     void slotOpenBrowser();
+    void slotDelete();
+    void slotCopy();
+    void slotCloseErrorTab();
 };
 
 
@@ -102,49 +101,4 @@ public slots:
 };
 
 
-
-/*--------------------------------------------------*/
-
-
-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
index b22703d..e5539a4 100644 (file)
@@ -24,6 +24,7 @@
 
 class KLibFactory;
 class KURL;
+class KitaImgView;
 
 namespace KParts
 {
@@ -34,6 +35,7 @@ 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 )
 
 
 
@@ -211,9 +213,24 @@ class ShowDockEvent : public QCustomEvent
 /* 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
index 4ce14ef..a3a5398 100644 (file)
@@ -2,9 +2,9 @@ INCLUDES = $(all_includes)
 
 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
index 5c4f4ba..2c4c5d7 100644 (file)
@@ -33,3 +33,71 @@ QString Cache::getPath( const KURL& datURL )
     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;
+}
index 54c2f11..1389c20 100644 (file)
@@ -23,8 +23,15 @@ namespace Kita
     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); 
     };
 
 }
diff --git a/kita/src/libkita/imgmanager.cpp b/kita/src/libkita/imgmanager.cpp
new file mode 100644 (file)
index 0000000..2e15f67
--- /dev/null
@@ -0,0 +1,811 @@
+/**************************************************************************
+*   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 );
+}
diff --git a/kita/src/libkita/imgmanager.h b/kita/src/libkita/imgmanager.h
new file mode 100644 (file)
index 0000000..fc31a5b
--- /dev/null
@@ -0,0 +1,188 @@
+/**************************************************************************
+*   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
index 7b09387..a6598d8 100644 (file)
@@ -9,9 +9,9 @@ libkitapart_la_LDFLAGS = -L../libkita $(all_libraries) -module -avoid-version -n
 
 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
 
diff --git a/kita/src/part/kitaimgview.cpp b/kita/src/part/kitaimgview.cpp
new file mode 100644 (file)
index 0000000..3d42fad
--- /dev/null
@@ -0,0 +1,221 @@
+/***************************************************************************
+*   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();
+}
diff --git a/kita/src/part/kitaimgview.h b/kita/src/part/kitaimgview.h
new file mode 100644 (file)
index 0000000..809ff05
--- /dev/null
@@ -0,0 +1,62 @@
+/***************************************************************************
+*   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