/* This file is part of the KDE project Copyright (C) 2002 Matthias Kretz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* $Id$ */ #include "kviewpresenter.h" #include "imagelistdialog.h" #include "imagelistitem.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef KGenericFactory KViewPresenterFactory; K_EXPORT_COMPONENT_FACTORY( kview_presenterplugin, KViewPresenterFactory( "kviewpresenterplugin" ) ) KViewPresenter::KViewPresenter( TQObject* parent, const char* name, const TQStringList & ) : Plugin( parent, name ) , m_pImageList( new ImageListDialog() ) , m_paFileOpen( 0 ) , m_bDontAdd( false ) , m_pCurrentItem( 0 ) , m_pSlideshowTimer( new TQTimer( this ) ) { kdDebug( 4630 ) << k_funcinfo << endl; m_imagelist.setAutoDelete( true ); TQObjectList * viewerList = parent->queryList( 0, "KImageViewer Part", false, false ); m_pViewer = static_cast( viewerList->getFirst() ); delete viewerList; if( m_pViewer ) { ( void ) new TDEAction( i18n( "&Image List..." ), 0, 0, this, TQ_SLOT( slotImageList() ), actionCollection(), "plugin_presenter_imageList" ); m_paSlideshow = new TDEToggleAction( i18n( "Start &Slideshow" ), Key_S, actionCollection(), "plugin_presenter_slideshow" ); ( void ) new TDEAction( i18n( "&Previous Image in List" ), "go-previous", ALT+Key_Left, this, TQ_SLOT( prev() ), actionCollection(), "plugin_presenter_prev" ); ( void ) new TDEAction( i18n( "&Next Image in List" ), "go-next", ALT+Key_Right, this, TQ_SLOT( next() ), actionCollection(), "plugin_presenter_next" ); connect( m_paSlideshow, TQ_SIGNAL( toggled( bool ) ), m_pImageList->m_pSlideshow, TQ_SLOT( setOn( bool ) ) ); connect( m_pImageList->m_pSlideshow, TQ_SIGNAL( toggled( bool ) ), m_paSlideshow, TQ_SLOT( setChecked( bool ) ) ); // search for file_open action KXMLGUIClient * parentClient = static_cast( parent->tqt_cast( "KXMLGUIClient" ) ); if( parentClient ) { m_paFileOpen = parentClient->actionCollection()->action( "file_open" ); m_paFileClose = parentClient->actionCollection()->action( "file_close" ); } if( m_paFileClose ) connect( m_paFileClose, TQ_SIGNAL( activated() ), this, TQ_SLOT( slotClose() ) ); if( m_paFileOpen ) { disconnect( m_paFileOpen, TQ_SIGNAL( activated() ), parent, TQ_SLOT( slotOpenFile() ) ); connect( m_paFileOpen, TQ_SIGNAL( activated() ), this, TQ_SLOT( slotOpenFiles() ) ); } else { (void) new TDEAction( i18n( "Open &Multiple Files..." ), "queue", CTRL+SHIFT+Key_O, this, TQ_SLOT( slotOpenFiles() ), actionCollection(), "plugin_presenter_openFiles" ); } connect( m_pViewer, TQ_SIGNAL( imageOpened( const KURL & ) ), TQ_SLOT( slotImageOpened( const KURL & ) ) ); } else kdWarning( 4630 ) << "no KImageViewer interface found - the presenter plugin won't work" << endl; //( void )new KViewPresenterConfModule( this ); connect( m_pImageList->m_pListView, TQ_SIGNAL( executed( TQListViewItem* ) ), this, TQ_SLOT( changeItem( TQListViewItem* ) ) ); connect( m_pImageList->m_pPrevious, TQ_SIGNAL( clicked() ), this, TQ_SLOT( prev() ) ); connect( m_pImageList->m_pNext, TQ_SIGNAL( clicked() ), this, TQ_SLOT( next() ) ); connect( m_pImageList->m_pListView, TQ_SIGNAL( spacePressed( TQListViewItem* ) ), this, TQ_SLOT( changeItem( TQListViewItem* ) ) ); connect( m_pImageList->m_pListView, TQ_SIGNAL( returnPressed( TQListViewItem* ) ), this, TQ_SLOT( changeItem( TQListViewItem* ) ) ); connect( m_pImageList->m_pSlideshow, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slideshow( bool ) ) ); connect( m_pImageList->m_pInterval, TQ_SIGNAL( valueChanged( int ) ), this, TQ_SLOT( setSlideshowInterval( int ) ) ); connect( m_pImageList->m_pShuffle, TQ_SIGNAL( clicked() ), this, TQ_SLOT( shuffle() ) ); connect( m_pImageList->m_pLoad, TQ_SIGNAL( clicked() ), this, TQ_SLOT( loadList() ) ); connect( m_pImageList->m_pSave, TQ_SIGNAL( clicked() ), this, TQ_SLOT( saveList() ) ); connect( m_pImageList->m_pCloseAll, TQ_SIGNAL( clicked() ), this, TQ_SLOT( closeAll() ) ); // allow drop on the dialog m_pImageList->installEventFilter( this ); m_pImageList->m_pListView->installEventFilter( this ); m_pImageList->m_pListView->viewport()->installEventFilter( this ); // grab drops on the main view m_pViewer->widget()->installEventFilter( this ); connect( m_pSlideshowTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( next() ) ); } KViewPresenter::~KViewPresenter() { kdDebug( 4630 ) << k_funcinfo << endl; if( m_paFileOpen ) { disconnect( m_paFileOpen, TQ_SIGNAL( activated() ), this, TQ_SLOT( slotOpenFiles() ) ); // If the parent() doesn't exist we either leave the "File Open" action // in an unusable state or KView was just shutting down and therefor we // can ignore this. I've only seen the second one happening and to get // rid of the TQObject::connect warning we do the parent() check. if( parent() ) connect( m_paFileOpen, TQ_SIGNAL( activated() ), parent(), TQ_SLOT( slotOpenFile() ) ); } } bool KViewPresenter::eventFilter( TQObject *obj, TQEvent *ev ) { if( obj == m_pImageList || obj == m_pImageList->m_pListView || obj == m_pImageList->m_pListView->viewport() || obj == m_pViewer->widget() ) { switch( ev->type() ) { case TQEvent::DragEnter: case TQEvent::DragMove: { // drag enter event in the image list //kdDebug( 4630 ) << "DragEnterEvent in the image list: " << obj->className() << endl; TQDragEnterEvent * e = static_cast( ev ); //for( int i = 0; e->format( i ); ++i ) //kdDebug( 4630 ) << " - " << e->format( i ) << endl; if( KURLDrag::canDecode( e ) )// || TQImageDrag::canDecode( e ) ) { e->accept(); return true; } } case TQEvent::Drop: { // drop event in the image list kdDebug( 4630 ) << "DropEvent in the image list: " << obj->className() << endl; TQDropEvent * e = static_cast( ev ); TQStringList l; //TQImage image; if( KURLDrag::decodeToUnicodeUris( e, l ) ) { for( TQStringList::const_iterator it = l.begin(); it != l.end(); ++it ) { ImageInfo * info = new ImageInfo( KURL( *it ) ); if( ! m_imagelist.contains( info ) ) { m_imagelist.inSort( info ); ( void )new ImageListItem( m_pImageList->m_pListView, KURL( *it ) ); } else delete info; } return true; } //else if( TQImageDrag::decode( e, image ) ) //newImage( image ); } default: // do nothing break; } } return KParts::Plugin::eventFilter( obj, ev ); } void KViewPresenter::slotImageOpened( const KURL & url ) { kdDebug( 4630 ) << k_funcinfo << endl; if( ! m_bDontAdd ) { kdDebug( 4630 ) << k_funcinfo << "imagelist:" << endl; ImageInfo * info = new ImageInfo( url ); if( ! m_imagelist.contains( info ) ) { m_imagelist.inSort( info ); TQListViewItem * item = new ImageListItem( m_pImageList->m_pListView, url ); makeCurrent( item ); } else delete info; } } void KViewPresenter::slotImageList() { kdDebug( 4630 ) << k_funcinfo << endl; m_pImageList->show(); } void KViewPresenter::slotOpenFiles() { kdDebug( 4630 ) << k_funcinfo << endl; KURL::List urls = KFileDialog::getOpenURLs( ":load_image", KImageIO::pattern( KImageIO::Reading ), m_pViewer->widget() ); if( urls.isEmpty() ) return; KURL::List::Iterator it = urls.begin(); m_pViewer->openURL( *it ); for( ++it; it != urls.end(); ++it ) { ImageInfo * info = new ImageInfo( *it ); if( ! m_imagelist.contains( info ) ) { m_imagelist.inSort( info ); ( void )new ImageListItem( m_pImageList->m_pListView, *it ); } else delete info; } } void KViewPresenter::slotClose() { TQListViewItem * next = m_pCurrentItem->itemBelow() ? m_pCurrentItem->itemBelow() : m_pImageList->m_pListView->firstChild(); if( next == m_pCurrentItem ) next = 0; ImageInfo info( m_pCurrentItem->url() ); m_imagelist.remove( &info ); delete m_pCurrentItem; m_pCurrentItem = 0; if( next ) changeItem( next ); } void KViewPresenter::changeItem( TQListViewItem * qitem ) { kdDebug( 4630 ) << k_funcinfo << endl; if( qitem->rtti() == 48294 ) { ImageListItem * item = static_cast( qitem ); if( ! item->url().isEmpty() ) { if( item->url().isLocalFile() && ! TQFile::exists( item->url().path() ) ) { kdDebug( 4630 ) << "file doesn't exist. removed." << endl; ImageInfo info( item->url() ); m_imagelist.remove( &info ); if( m_pCurrentItem == item ) { TQListViewItem * next = m_pCurrentItem->itemBelow() ? m_pCurrentItem->itemBelow() : m_pImageList->m_pListView->firstChild(); if( next->rtti() != 48294 ) kdWarning( 4630 ) << "unknown ListView item" << endl; else m_pCurrentItem = static_cast( next ); if( m_pCurrentItem == item ) m_pCurrentItem = 0; // don't create a dangling pointer delete item; if( m_pCurrentItem ) changeItem( m_pCurrentItem ); } else { delete item; next(); } return; } kdDebug( 4630 ) << "got url" << endl; makeCurrent( qitem ); bool dontadd = m_bDontAdd; m_bDontAdd = true; m_pViewer->openURL( item->url() ); m_bDontAdd = dontadd; } else kdWarning( 4630 ) << "got nothing" << endl; } else kdWarning( 4630 ) << "unknown ListView item" << endl; } void KViewPresenter::prev() { kdDebug( 4630 ) << k_funcinfo << endl; if( m_pCurrentItem ) { TQListViewItem * prev = m_pCurrentItem->itemAbove() ? m_pCurrentItem->itemAbove() : m_pImageList->m_pListView->lastItem(); if( prev ) changeItem( prev ); } } void KViewPresenter::next() { kdDebug( 4630 ) << k_funcinfo << endl; if( m_pCurrentItem ) { TQListViewItem * next = m_pCurrentItem->itemBelow() ? m_pCurrentItem->itemBelow() : m_pImageList->m_pListView->firstChild(); if( next ) changeItem( next ); } } void KViewPresenter::makeCurrent( TQListViewItem * item ) { if( m_pCurrentItem ) m_pCurrentItem->setPixmap( 0, TQPixmap() ); if( item->rtti() != 48294 ) kdWarning( 4630 ) << "unknown ListView item" << endl; else { m_pCurrentItem = static_cast( item ); m_pCurrentItem->setPixmap( 0, TDEGlobal::iconLoader()->loadIcon( "1rightarrow", TDEIcon::Small ) ); m_pImageList->m_pListView->ensureItemVisible( m_pCurrentItem ); } } void KViewPresenter::slideshow( bool running ) { if( running ) { m_pSlideshowTimer->start( m_pImageList->m_pInterval->value() ); actionCollection()->action( "plugin_presenter_slideshow" )->setText( i18n( "Stop &Slideshow" ) ); m_pImageList->m_pSlideshow->setText( i18n( "Stop &Slideshow" ) ); } else { m_pSlideshowTimer->stop(); actionCollection()->action( "plugin_presenter_slideshow" )->setText( i18n( "Start &Slideshow" ) ); m_pImageList->m_pSlideshow->setText( i18n( "Start &Slideshow" ) ); } } void KViewPresenter::setSlideshowInterval( int msec ) { if( m_pSlideshowTimer->isActive() ) m_pSlideshowTimer->changeInterval( msec ); } void KViewPresenter::shuffle() { m_pImageList->noSort(); TDEListView * listview = m_pImageList->m_pListView; TQPtrList items; for( TQListViewItem * item = listview->firstChild(); item; item = listview->firstChild() ) { items.append( item ); listview->takeItem( item ); } while( ! items.isEmpty() ) listview->insertItem( items.take( TDEApplication::random() % items.count() ) ); } void KViewPresenter::closeAll() { m_imagelist.clear(); m_pImageList->m_pListView->clear(); m_pCurrentItem = 0; if( m_pViewer->closeURL() ) m_pViewer->canvas()->clear(); } void KViewPresenter::loadList() { KURL url = KFileDialog::getOpenURL( ":load_list", TQString(), m_pImageList ); if( url.isEmpty() ) return; TQString tempfile; if( ! TDEIO::NetAccess::download( url, tempfile, m_pViewer->widget() ) ) { KMessageBox::error( m_pImageList, i18n( "Could not load\n%1" ).arg( url.prettyURL() ) ); return; } TQFile file( tempfile ); if( file.open( IO_ReadOnly ) ) { TQTextStream t( &file ); if( t.readLine() == "[KView Image List]" ) { //clear old image list closeAll(); TQStringList list; if( ! t.eof() ) m_pViewer->openURL( KURL( t.readLine() ) ); while( ! t.eof() ) { KURL url ( t.readLine() ); ImageInfo * info = new ImageInfo( url ); if( ! m_imagelist.contains( info ) ) { m_imagelist.inSort( info ); ( void )new ImageListItem( m_pImageList->m_pListView, url ); } else delete info; } } else { KMessageBox::error( m_pImageList, i18n( "Wrong format\n%1" ).arg( url.prettyURL() ) ); } file.close(); } TDEIO::NetAccess::removeTempFile( tempfile ); } void KViewPresenter::saveList() { KURL url = KFileDialog::getSaveURL( ":save_list", TQString(), m_pImageList ); if( url.isEmpty() ) return; TQString tempfile; if( url.isLocalFile() ) tempfile = url.path(); else { KTempFile ktempf; tempfile = ktempf.name(); } TQFile file( tempfile ); if( file.open( IO_WriteOnly ) ) { TQTextStream t( &file ); // write header t << "[KView Image List]" << endl; TQListViewItem * item = m_pImageList->m_pListView->firstChild(); while( item ) { if( item->rtti() == 48294 ) t << static_cast( item )->url().url() << endl; item = item->itemBelow(); } file.close(); if( ! url.isLocalFile() ) { TDEIO::NetAccess::upload( tempfile, url, m_pViewer->widget() ); TDEIO::NetAccess::removeTempFile( tempfile ); } } } #include "kviewpresenter.moc"