Index: trunk/kdegraphics/kghostview/thumbnailservice.h =================================================================== --- trunk/kdegraphics/kghostview/thumbnailservice.h (revision 251917) +++ trunk/kdegraphics/kghostview/thumbnailservice.h (revision 251918) @@ -1,68 +1,76 @@ #ifndef THUMBNAILSERVICE_H #define THUMBNAILSERVICE_H /** * Copyright (C) 1997-2003 the KGhostView authors. See file AUTHORS. * * 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. * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include class KPSWidget; class KGVMiniWidget; class ThumbnailService : public QObject { Q_OBJECT public: ThumbnailService( KGVMiniWidget* parent, const char* name = 0 ); ~ThumbnailService(); public slots: void delayedGetThumbnail( int page, QObject* receiver, const char* slot ); void reset(); + /** + * This "suspends" the service. + * Unlike @ref reset(), if you call setEnabled( false ), + * old requests will be kept and will be serviced when + * you call setEnabled( true ) later. + */ + void setEnabled( bool ); signals: /** * Don't connect to this directly */ void relayPixmap( QPixmap ); private slots: void slotDone( QPixmap ); void processOne(); private: struct Request { Request( int p, QObject* r, const char* s ) : page( p ), receiver( r ), slot( s ) { } int page; QObject* receiver; const char* slot; }; static bool pageCmp( Request, Request ); std::vector pending; QGuardedPtr _thumbnailDrawer; KGVMiniWidget* _mini; bool _busy; + bool _enabled; }; // vim:sw=4:sts=4:ts=8:sta:tw=78:noet #endif // THUMBNAILSERVICE_H Index: trunk/kdegraphics/kghostview/kgv_view.cpp =================================================================== --- trunk/kdegraphics/kghostview/kgv_view.cpp (revision 251917) +++ trunk/kdegraphics/kghostview/kgv_view.cpp (revision 251918) @@ -1,983 +1,985 @@ /** * Copyright (C) 2000-2002 the KGhostView authors. See file AUTHORS. * * 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. * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kgv_view.h" #include "kgv_miniwidget.h" #include "kgvconfigdialog.h" #include "kgvdocument.h" #include "kgvpagedecorator.h" #include "kgvpageview.h" #include "kgvmainwidget.h" #include "kpswidget.h" #include "kgvfactory.h" #include "logwindow.h" #include "marklist.h" #include "scrollbox.h" #include "version.h" namespace KGV { /* * This is because Qt's iterators * are not standard iterators bc of missing typedefs, * so they are only *almost* STL compatible */ template unsigned distance( T a, T b ) { unsigned res = 0; while ( a != b ) { ++res; ++a; } return res; } } K_EXPORT_COMPONENT_FACTORY( libkghostviewpart, KGVFactory ) KGVPart::KGVPart( QWidget* parentWidget, const char*, QObject* parent, const char* name, const QStringList &args ) : KParts::ReadOnlyPart( parent, name ), _job( 0 ), _mimetypeScanner( 0 ), _dirtyHandler( new QTimer( this ) ), _isGuiInitialized( false ), _isFileDirty( false ), _stickyOptions( false ) { setInstance( KGVFactory::instance() ); // Don't show the progress info dialog if we're embedded in Konqueror. setProgressInfoEnabled( !args.contains( "Browser/View") ); _document = new KGVDocument( this ); connect( _document, SIGNAL( fileChangeFailed() ), this, SLOT( slotCancelWatch() ) ); connect( _document, SIGNAL( completed() ), this, SLOT( slotOpenFileCompleted() ) ); connect( _document, SIGNAL( canceled( const QString& ) ), this, SIGNAL( canceled( const QString& ) ) ); _fileWatcher = new KDirWatch( this ); connect( _fileWatcher, SIGNAL( dirty( const QString& ) ), this, SLOT( slotFileDirty( const QString& ) ) ); connect( _dirtyHandler, SIGNAL( timeout() ), this, SLOT( slotDoFileDirty() ) ); // Setup main widget _mainWidget = new KGVMainWidget( parentWidget ); _mainWidget->setFocusPolicy( QWidget::StrongFocus ); _mainWidget->installEventFilter( this ); _mainWidget->setAcceptDrops( true ); connect( _mainWidget, SIGNAL( spacePressed() ), this, SLOT( slotReadDown() ) ); connect( _mainWidget, SIGNAL( urlDropped( const KURL& ) ), this, SLOT( openURL( const KURL& ) ) ); QHBoxLayout* hlay = new QHBoxLayout( _mainWidget, 0, 0 ); QVBoxLayout* vlay = new QVBoxLayout( hlay ); const int PAGELIST_WIDTH = 75; _scrollBox = new ScrollBox( _mainWidget , "scrollbox" ); _scrollBox->setFixedWidth( PAGELIST_WIDTH ); _scrollBox->setMinimumHeight( PAGELIST_WIDTH ); vlay->addWidget( _scrollBox ); _divider = new QFrame( _mainWidget, "divider" ); _divider->setFrameStyle( QFrame::Panel | QFrame::Raised ); _divider->setLineWidth( 1 ); _divider->setMinimumWidth( 3 ); hlay->addWidget( _divider ); _pageView = new KGVPageView( _mainWidget, "pageview" ); _pageView->viewport()->setBackgroundMode( QWidget::PaletteMid ); hlay->addWidget( _pageView, 1 ); _mainWidget->setFocusProxy( _pageView ); setWidget( _mainWidget ); _pageDecorator = new KGVPageDecorator( _pageView->viewport() ); _pageDecorator->hide(); _configDialog = new KGVConfigDialog( _mainWidget, "configdialog" ); _psWidget = new KPSWidget( _pageDecorator ); _psWidget->readSettings( _configDialog ); _pageView->setPage( _pageDecorator ); connect( _psWidget, SIGNAL( output( char*, int ) ), this, SLOT( slotGhostscriptOutput( char*, int ) ) ); connect( _psWidget, SIGNAL( ghostscriptError( const QString& ) ), this, SLOT( slotGhostscriptError( const QString& ) ) ); _logWindow = new LogWindow( "Ghostscript Messages", _mainWidget, "logwindow" ); _showLogWindow = false; connect( _logWindow, SIGNAL( configureGS() ), _configDialog, SLOT( show() ) ); _docManager = new KGVMiniWidget( this ); _docManager->setPSWidget( _psWidget ); _docManager->setDocument( document() ); _markList = new MarkList( _mainWidget, "marklist", _docManager ); _markList->setFixedWidth( PAGELIST_WIDTH ); vlay->addWidget( _markList, 1 ); connect( _markList, SIGNAL( contextMenuRequested ( int, int, const QPoint& ) ), this, SLOT( showPopup( int, int, const QPoint& ) ) ); connect( _markList, SIGNAL( selected( int ) ), _docManager, SLOT( goToPage( int ) ) ); connect( _docManager, SIGNAL( newPageShown( int ) ), _markList, SLOT( select( int ) ) ); connect( _docManager, SIGNAL( setStatusBarText( const QString& ) ), this, SIGNAL( setStatusBarText( const QString& ) ) ); connect( _scrollBox, SIGNAL( valueChangedRelative( int, int ) ), _pageView, SLOT( scrollBy( int, int ) ) ); connect( _pageView, SIGNAL( pageSizeChanged( const QSize& ) ), _scrollBox, SLOT( setPageSize( const QSize& ) ) ); connect( _pageView, SIGNAL( viewSizeChanged( const QSize& ) ), _scrollBox, SLOT( setViewSize( const QSize& ) ) ); connect( _pageView, SIGNAL( contentsMoving( int, int ) ), _scrollBox, SLOT( setViewPos( int, int ) ) ); //-- File Menu ---------------------------------------------------------- KStdAction::saveAs( document(), SLOT( saveAs() ), actionCollection() ); new KAction( i18n( "Document &Info" ), 0, miniWidget(), SLOT( info() ), actionCollection(), "info" ); //-- Edit Menu ----------------------------------------------------- _popup = new KPopupMenu( _markList, "marklist_menu" ); KAction *act = new KAction( i18n( "Mark Current Page" ), "flag", CTRL+SHIFT+Key_M, _markList, SLOT( markCurrent() ), actionCollection(), "mark_current" ); act->plug( _popup ); act = new KAction( i18n( "Mark &All Pages" ), 0, _markList, SLOT( markAll() ), actionCollection(), "mark_all" ); act->plug( _popup ); act = new KAction( i18n( "Mark &Even Pages" ), 0, _markList, SLOT( markEven() ), actionCollection(), "mark_even" ); act->plug( _popup ); act = new KAction( i18n( "Mark &Odd Pages" ), 0, _markList, SLOT( markOdd() ), actionCollection(), "mark_odd" ); act->plug( _popup ); act = new KAction( i18n( "&Toggle Page Marks" ), 0, _markList, SLOT( toggleMarks() ), actionCollection(), "toggle" ); act->plug( _popup ); act = new KAction( i18n("&Remove Page Marks"), 0, _markList, SLOT( removeMarks() ), actionCollection(), "remove" ); act->plug( _popup ); // TODO -- disable entry if there aren't any page names //-- View Menu ---------------------------------------------------------- _selectOrientation = new KSelectAction( i18n( "&Orientation" ), 0, 0, 0, actionCollection(), "orientation_menu" ); _selectMedia = new KSelectAction( i18n( "Paper &Size" ), 0, 0, 0, actionCollection(), "media_menu" ); QStringList orientations; orientations.append( i18n( "Auto" ) ); orientations.append( i18n( "Portrait" ) ); orientations.append( i18n( "Landscape" ) ); orientations.append( i18n( "Upside Down" ) ); orientations.append( i18n( "Seascape" ) ); _selectOrientation->setItems( orientations ); connect( _selectOrientation, SIGNAL( activated( int ) ), this, SLOT( slotOrientation( int ) ) ); connect( _selectMedia, SIGNAL( activated( int ) ), this, SLOT( slotMedia( int ) ) ); _zoomIn = KStdAction::zoomIn( this, SLOT( slotZoomIn() ), actionCollection(), "zoomIn" ); _zoomOut = KStdAction::zoomOut( this, SLOT( slotZoomOut() ), actionCollection(), "zoomOut" ); _zoomTo = new KSelectAction( i18n( "Zoom" ), "zoomTo", 0, actionCollection(), "zoomTo" ); connect( _zoomTo, SIGNAL( activated( const QString & ) ), this, SLOT( slotZoom( const QString& ) ) ); _zoomTo->setEditable( true ); _zoomTo->clear(); QValueList mags = DisplayOptions::normalMagnificationValues(); QStringList translated; int idx = 0; int cur = 0; for ( QValueList::iterator first = mags.begin(), last = mags.end(); first != last; ++first ) { translated << QString( "%1%" ).arg( *first * 100.0 ); if ( *first == 1.0 ) idx = cur; ++cur; } _zoomTo->setItems( translated ); _zoomTo->setCurrentItem( idx ); /* _fitWidth = new KAction( i18n( "Fit Width" ), 0, this, SLOT( slotFitWidth() ), actionCollection(), "fitWidth" ); */ _prevPage = KStdAction::prior( this, SLOT( slotPrevPage() ), actionCollection(), "prevPage" ); _prevPage->setWhatsThis( i18n( "Moves to the previous page of the document" ) ); _nextPage = KStdAction::next( this, SLOT( slotNextPage() ), actionCollection(), "nextPage" ); _nextPage->setWhatsThis( i18n( "Moves to the next page of the document" ) ); _firstPage = KStdAction::firstPage( this, SLOT( slotGotoStart() ), actionCollection(), "goToStart" ); _firstPage->setWhatsThis( i18n( "Moves to the first page of the document" ) ); _lastPage = KStdAction::lastPage( this, SLOT( slotGotoEnd() ), actionCollection(), "goToEnd" ); _lastPage->setWhatsThis( i18n( "Moves to the last page of the document" ) ); _readUp = new KAction( i18n( "Read Up Document" ), "previous", SHIFT+Key_Space, this, SLOT( slotReadUp() ), actionCollection(), "readUp" ); // don't specify Key_Space as Accel, it breaks the lineedit in konq! (Simon) _readDown = new KAction( i18n( "Read Down Document" ), "next", /*Key_Space*/0, this, SLOT( slotReadDown() ), actionCollection(), "readDown" ); _gotoPage = KStdAction::gotoPage( _docManager, SLOT( goToPage() ), actionCollection(), "goToPage" ); //-- Settings Menu ------------------------------------------------------ _showScrollBars = new KToggleAction( i18n( "Show &Scrollbars" ), 0, actionCollection(), "show_scrollbars" ); _watchFile = new KToggleAction( i18n( "&Watch File" ), 0, this, SLOT( slotWatchFile() ), actionCollection(), "watch_file" ); _showPageList = new KToggleAction( i18n( "Show &Page List" ), 0, actionCollection(), "show_page_list" ); _showPageLabels = new KToggleAction( i18n("Show Page &Labels"), 0, actionCollection(), "show_page_labels" ); new KAction( i18n( "&Configure KGhostView..." ), "configure", 0, this, SLOT( slotConfigure() ), actionCollection(), "configure" ); KStdAction::keyBindings( this, SLOT( slotConfigureKeys() ), actionCollection() ); connect( _showScrollBars, SIGNAL( toggled( bool ) ), SLOT( showScrollBars( bool ) ) ); connect( _showPageList, SIGNAL( toggled( bool ) ), SLOT( showMarkList( bool ) ) ); connect( _showPageLabels, SIGNAL( toggled( bool ) ), SLOT( showPageLabels( bool ) ) ); _extension = new KGVBrowserExtension( this ); setXMLFile( "kgv_part.rc" ); connect( miniWidget(), SIGNAL( newPageShown( int ) ), this, SLOT( slotNewPage( int ) ) ); connect( _pageView, SIGNAL( contentsMoving( int, int ) ), this, SLOT( slotPageMoved( int, int ) ) ); connect( _pageView, SIGNAL( nextPage() ), SLOT( slotNextPage() )); connect( _pageView, SIGNAL( prevPage() ), SLOT( slotPrevPage() )); connect( _pageView, SIGNAL( zoomIn() ), SLOT( slotZoomIn() )); connect( _pageView, SIGNAL( zoomOut() ), SLOT( slotZoomOut() )); connect( _pageView, SIGNAL( ReadUp() ), SLOT( slotReadUp() )); connect( _pageView, SIGNAL( ReadDown() ), SLOT( slotReadDown() )); readSettings(); QStringList items = document()->mediaNames(); items.prepend( i18n( "Auto ") ); _selectMedia->setItems( items ); } KGVPart::~KGVPart() { if ( _job ) _job -> kill(); delete _mimetypeScanner; writeSettings(); } void KGVPart::slotConfigureKeys() { KKeyDialog::configure( actionCollection(), this ); } KAboutData* KGVPart::createAboutData() { KAboutData* about = new KAboutData( "kghostview", I18N_NOOP( "KGhostView"), KGHOSTVIEW_VERSION, I18N_NOOP( "Viewer for PostScript (.ps, .eps) and Portable Document Format (.pdf) files."), KAboutData::License_GPL, "(C) 1998 Mark Donohoe, (C) 1999-2000 David Sweet, " "(C) 2000-2003 Wilco Greven", I18N_NOOP( "KGhostView displays, prints, and saves " "PostScript and PDF files.\n" "Based on original work by Tim Theisen." ) ); about->addAuthor( "Luís Pedro Coelho", I18N_NOOP( "Current maintainer" ), "luis_pedro@netcabo.pt" ); about->addAuthor( "Wilco Greven", I18N_NOOP( "Maintainer 2000-2003" ), "greven@kde.org" ); about->addAuthor( "David Sweet", I18N_NOOP( "Maintainer 1999-2000" ), "dsweet@kde.org", "http://www.andamooka.org/~dsweet" ); about->addAuthor( "Mark Donohoe", I18N_NOOP( "Original author" ), "donohoe@kde.org" ); about->addAuthor( "David Faure", I18N_NOOP( "Basis for shell"), "faure@kde.org" ); about->addAuthor( "Daniel Duley", I18N_NOOP( "Port to KParts" ), "mosfet@kde.org" ); about->addAuthor( "Espen Sand", I18N_NOOP( "Dialog boxes" ), "espen@kde.org" ); about->addCredit( "Russell Lang of Ghostgum Software Pty Ltd", I18N_NOOP( "for contributing GSView's DSC parser." ), 0, "http://www.ghostgum.com.au/" ); about->addCredit( "The Ghostscript authors", 0, 0, "http://www.cs.wisc.edu/~ghost/" ); return about; } bool KGVPart::closeURL() { document()->close(); _psWidget->stopInterpreter(); _docManager->getThumbnailService()->reset(); _markList->clear(); _pageDecorator->hide(); //_scrollBox->clear(); _isFileDirty = false; if ( _job ) { _job -> kill(); _job = 0; } if( _mimetypeScanner != 0 ) _mimetypeScanner->abort(); if( !m_file.isEmpty() ) _fileWatcher->removeFile( m_file ); _mimetype = QString::null; stateChanged( "initState" ); return KParts::ReadOnlyPart::closeURL(); } void KGVPart::writeSettings() { KConfigGroup general( KGVFactory::instance()->config(), "General" ); general.writeEntry( "ShowScrollBars", _showScrollBars->isChecked() ); general.writeEntry( "WatchFile", _watchFile->isChecked() ); general.writeEntry( "ShowPageList", _showPageList->isChecked() ); general.writeEntry( "ShowPageNames", _showPageLabels->isChecked() ); general.sync(); } void KGVPart::readSettings() { KConfigGroup general( KGVFactory::instance()->config(), "General" ); _showScrollBars->setChecked( general.readBoolEntry( "ShowScrollBars", true ) ); showScrollBars( _showScrollBars->isChecked() ); _watchFile->setChecked( general.readBoolEntry( "WatchFile", false ) ); slotWatchFile(); _showPageList->setChecked( general.readBoolEntry( "ShowPageList", true ) ); showMarkList( _showPageList->isChecked() ); _showPageLabels->setChecked( general.readBoolEntry( "ShowPageNames", false ) ); showPageLabels( _showPageLabels->isChecked() ); _showLogWindow = _configDialog->showMessages(); } void KGVPart::slotScrollLeft() { _pageView->scrollLeft(); } void KGVPart::slotScrollRight() { _pageView->scrollRight(); } void KGVPart::slotScrollUp() { _pageView->scrollUp(); } void KGVPart::slotScrollDown() { _pageView->scrollDown(); } void KGVPart::slotReadUp() { if( !( document() && document()->isOpen() ) ) return; if( !_pageView->readUp() ) { if (_docManager->prevPage()) _pageView->scrollBottom(); } } void KGVPart::slotReadDown() { if( !( document() && document()->isOpen() ) ) return; if( !_pageView->readDown() ) { if( _docManager->nextPage() ) _pageView->scrollTop(); } } void KGVPart::slotPrevPage() { if( !( document() && document()->isOpen() ) ) return; _docManager->prevPage(); // I am commenting the line below in response to 58514 // I am afraid that someone will dislike the new behaviour, though :-) // // BTW, this seems to mirror kdvi, although I admit I don't use that app // much, so I could be wrong. // // If no one does, then the comment should be reverted. // LPC (27 Jun 2003) //_pageView->scrollTop(); } void KGVPart::slotNextPage() { if( !( document() && document()->isOpen() ) ) return; if( _docManager->nextPage() ) { // See above //_pageView->scrollTop(); } else _pageView->scrollBottom(); } void KGVPart::slotGotoStart() { _docManager->firstPage(); _pageView->scrollTop(); } void KGVPart::slotGotoEnd() { _docManager->lastPage(); _pageView->scrollTop(); } void KGVPart::slotWatchFile() { if( _watchFile->isChecked() ) _fileWatcher->startScan(); else { _dirtyHandler->stop(); _fileWatcher->stopScan(); } } void KGVPart::slotCancelWatch() { _fileWatcher->stopScan(); _watchFile->setChecked( false ); } /* void KGVPart::slotFitWidth() { _docManager->fitWidth( pageView()->viewport()->width() - 2*( pageDecorator()->margin() + pageDecorator()->borderWidth() ) ); } */ void KGVPart::updateZoomActions() { if( !( document() && document()->isOpen() ) ) return; _zoomIn->setEnabled(!_docManager->atMaxZoom()); _zoomOut->setEnabled(!_docManager->atMinZoom()); _zoomTo->setEnabled( true ); QStringList items = _zoomTo->items(); double zoom = miniWidget()->displayOptions().magnification(); unsigned idx = 0; for ( QStringList::iterator first = items.begin(), last = items.end(); first != last; ++first ) { QString cur = *first; cur = cur.replace( QRegExp( "%" ), "" ); cur = cur.simplifyWhiteSpace(); bool ok = false; double z = cur.toDouble(&ok); if ( ok && std::abs( z - zoom * 100.0 ) < 0.1 ) { _zoomTo->setCurrentItem( idx ); return; } ++idx; } /* TODO: * * One should reorder the _zoomTo->items() list here. * This is because any values the user types in himself will get * put at the end of the list, which is not optimal. * * LPC 19 Jun 2003 */ } void KGVPart::updatePageDepActions() { if( !( document() && document()->isOpen() ) ) return; _prevPage->setEnabled( !_docManager->atFirstPage() ); _firstPage->setEnabled( !_docManager->atFirstPage() ); _nextPage->setEnabled( !_docManager->atLastPage() ); _lastPage->setEnabled( !_docManager->atLastPage() ); updateReadUpDownActions(); } void KGVPart::updateReadUpDownActions() { if( !( document() && document()->isOpen() ) ) return; if( _docManager->atFirstPage() && _pageView->atTop() ) _readUp->setEnabled( false ); else _readUp->setEnabled( true ); if( _docManager->atLastPage() && _pageView->atBottom() ) _readDown->setEnabled( false ); else _readDown->setEnabled( true ); } bool KGVPart::openURL( const KURL& url ) { if( !url.isValid() ) return false; if( !closeURL() ) return false; m_url = url; if ( !_stickyOptions ) _options.reset(); emit setWindowCaption( m_url.prettyURL() ); _mimetypeScanner = new KGVRun( m_url, 0, m_url.isLocalFile(), false ); connect( _mimetypeScanner, SIGNAL( finished( const QString& ) ), SLOT( slotMimetypeFinished( const QString& ) ) ); connect( _mimetypeScanner, SIGNAL( error() ), SLOT( slotMimetypeError() ) ); return true; } void KGVPart::openURLContinue() { kdDebug(4500) << "KGVPart::openURLContinue()" << endl; if( m_url.isLocalFile() ) { emit started( 0 ); m_file = m_url.path(); document()->openFile( m_file, _mimetype ); } else { m_bTemp = true; // Use same extension as remote file. This is important for // mimetype-determination (e.g. koffice) QString extension; QString fileName = m_url.fileName(); int extensionPos = fileName.findRev( '.' ); if( extensionPos != -1 ) extension = fileName.mid( extensionPos ); // keep the '.' KTempFile tempFile( QString::null, extension ); m_file = tempFile.name(); _tmpFile.setName( m_file ); _tmpFile.open( IO_ReadWrite ); /* d->m_job = KIO::file_copy( m_url, m_file, 0600, true, false, d->m_showProgressInfo ); emit started( d->m_job ); connect( d->m_job, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotJobFinished ( KIO::Job * ) ) ); */ _job = KIO::get( m_url, false, isProgressInfoEnabled() ); connect( _job, SIGNAL( data( KIO::Job*, const QByteArray& ) ), SLOT( slotData( KIO::Job*, const QByteArray& ) ) ); connect( _job, SIGNAL( result( KIO::Job* ) ), SLOT( slotJobFinished( KIO::Job* ) ) ); emit started( _job ); } } bool KGVPart::openFile() { return false; } void KGVPart::slotOpenFileCompleted() { + _docManager->getThumbnailService()->setEnabled( true ); if( _isFileDirty ) { _docManager->redisplay(); _isFileDirty = false; } else { if ( !_stickyOptions ) setDisplayOptions( DisplayOptions() ); _stickyOptions = false; stateChanged( "documentState" ); if ( !_fileWatcher->contains( m_file ) ) _fileWatcher->addFile( m_file ); slotWatchFile(); emit completed(); } } void KGVPart::slotGhostscriptOutput( char* data, int len ) { _logWindow->append( QString::fromLocal8Bit( data, len ) ); if( _showLogWindow ) _logWindow->show(); } void KGVPart::slotGhostscriptError( const QString& error ) { // FIXME: find a significant error message _logWindow->setLabel( i18n( "An error occurred in rendering.\n%1\n%2\n" ) .arg( error ) .arg( i18n( "You might see some errors in the display or it may work.\n" "The error messages below are from ghostscript (\"gs\") and may " "help identify or correct the problem.\n" ) ), true ); // The true above makes it show a "configure gs" option, but maybe we // should trigger an auto-redetection? // LPC (13 Apr 2003) _logWindow->show(); } void KGVPart::guiActivateEvent( KParts::GUIActivateEvent* event ) { if( event->activated() && !_isGuiInitialized ) { stateChanged( "initState" ); _isGuiInitialized = true; } KParts::ReadOnlyPart::guiActivateEvent( event ); } void KGVPart::slotData( KIO::Job* job, const QByteArray& data ) { Q_ASSERT( _job == job ); kdDebug(4500) << "KGVPart::slotData: received " << data.size() << " bytes." << endl; _tmpFile.writeBlock( data ); } void KGVPart::slotMimetypeFinished( const QString& type ) { kdDebug(4500) << "KGVPart::slotMimetype: type=" << type << endl; _mimetype = type; if ( _mimetype == "application/x-gzip" ) { kdDebug(4500) << "KGVPart::slotMimetype: tranforming URL" << endl; delete _mimetypeScanner; _mimetypeScanner = 0; openURL( KURL( QString::fromLatin1( "gzip:/decompress/" ) + m_url.url() ) ); return; } if( !_mimetypeScanner || _mimetypeScanner->hasError() ) emit canceled( QString::null ); else openURLContinue(); _mimetypeScanner = 0; } void KGVPart::slotMimetypeError() { kdDebug(4500) << "KGVPart::slotMimetypeError()" << endl; _mimetypeScanner = 0; emit started( 0 ); //kapp->processEvents(); emit canceled( QString::null ); } void KGVPart::slotJobFinished( KIO::Job* job ) { Q_ASSERT( _job == job ); kdDebug(4500) << "KGVPart::slotJobFinished" << endl; _job = 0; _tmpFile.close(); if( job->error() ) emit canceled( job->errorString() ); else document()->openFile( m_file, _mimetype ); } void KGVPart::slotFileDirty( const QString& fileName ) { // The beauty of this is that each start cancels the previous one. // This means that timeout() is only fired when there have // no changes to the file for the last 750 milisecs. // This is supposed to ensure that we don't update on every other byte // that gets written to the file. if ( fileName == m_file ) { _dirtyHandler->start( 750, true ); } } void KGVPart::slotDoFileDirty() { kdDebug(4500) << "KGVPart::File changed" << endl; _isFileDirty = true; reloadFile(); } void KGVPart::slotNewPage( int ) { updatePageDepActions(); //media->setCurrentItem (miniWidget()->getSize()-1); //orientation->setCurrentItem (miniWidget()->getOrientation()-1); //TODO -- zoom } void KGVPart::slotPageMoved( int, int ) { updateReadUpDownActions(); } void KGVPart::slotOrientation( int id ) { switch( id ) { case 0: miniWidget()->restoreOverrideOrientation(); break; case 1: miniWidget()->setOverrideOrientation( CDSC_PORTRAIT ); break; case 2: miniWidget()->setOverrideOrientation( CDSC_LANDSCAPE ); break; case 3: miniWidget()->setOverrideOrientation( CDSC_UPSIDEDOWN ); break; case 4: miniWidget()->setOverrideOrientation( CDSC_SEASCAPE ); break; default: ; } } void KGVPart::slotMedia( int id ) { if( id == 0 ) miniWidget()->restoreOverridePageMedia(); else miniWidget()->setOverridePageMedia( _document->mediaNames()[id-1] ); } void KGVPart::showScrollBars( bool show ) { _pageView->enableScrollBars( show ); } void KGVPart::showMarkList( bool show ) { _markList->setShown( show ); _scrollBox->setShown( show ); _divider->setShown( show ); } void KGVPart::showPageLabels( bool show ) { _docManager->enablePageLabels( show ); } void KGVPart::slotZoomIn() { _docManager->zoomIn(); updateZoomActions(); } void KGVPart::slotZoomOut() { _docManager->zoomOut(); updateZoomActions(); } void KGVPart::slotZoom( const QString& nz ) { QString z = nz; double zoom; z.remove( z.find( '%' ), 1 ); zoom = KGlobal::locale()->readNumber( z ) / 100; kdDebug( 4500 ) << "ZOOM = " << nz << ", setting zoom = " << zoom << endl; DisplayOptions options = miniWidget()->displayOptions(); options.setMagnification( zoom ); miniWidget()->setDisplayOptions( options ); miniWidget()->redisplay(); _mainWidget->setFocus(); } void KGVPart::reloadFile() { _psWidget->stopInterpreter(); + _docManager->getThumbnailService()->reset(); document()->openFile( m_file, _mimetype ); } void KGVPart::slotConfigure() { _configDialog->setup(); if( _configDialog->exec() ) { _psWidget->readSettings( _configDialog ); miniWidget()->redisplay(); } } void KGVPart::setDisplayOptions( const DisplayOptions& options ) { kdDebug(4500) << "KGVPart::setDisplayOptions()" << endl; _stickyOptions = true; _markList->select( options.page() ); _docManager->setDisplayOptions( options ); _selectOrientation->setCurrentItem( options.overrideOrientation() ); QStringList medias = document()->mediaNames(); QStringList::Iterator now = medias.find( options.overridePageMedia() ); if ( now != medias.end() ){ // The options are displayed in inverted order. // Therefore, size() - index gets you the display index _selectMedia->setCurrentItem( medias.size() - KGV::distance( medias.begin(), now ) ); } else { _selectMedia->setCurrentItem( 0 ); } } KGVBrowserExtension::KGVBrowserExtension( KGVPart *parent ) : KParts::BrowserExtension( parent, "KGVBrowserExtension" ) { emit enableAction( "print", true ); setURLDropHandlingEnabled( true ); } void KGVBrowserExtension::print() { ((KGVPart *)parent())->document()->print(); } KGVRun::KGVRun( const KURL& url, mode_t mode, bool isLocalFile, bool showProgressInfo ) : KRun( url, mode, isLocalFile, showProgressInfo ) { connect( this, SIGNAL( finished() ), SLOT( emitFinishedWithMimetype() ) ); } KGVRun::~KGVRun() {} void KGVRun::foundMimeType( const QString& mimetype ) { kdDebug(4500) << "KGVRun::foundMimeType( " << mimetype << " )" << endl; if( m_job && m_job->inherits( "KIO::TransferJob" ) ) { KIO::TransferJob *job = static_cast< KIO::TransferJob* >( m_job ); job->putOnHold(); KIO::Scheduler::publishSlaveOnHold(); m_job = 0; } _mimetype = mimetype; m_bFinished = true; m_timer.start( 0, true ); } void KGVPart::setFullScreen( bool fs ) { if ( fs ) { _markList->hide(); _scrollBox->hide(); } else { _markList->show(); _scrollBox->show(); } } void KGVPart::showPopup( int, int, const QPoint& pos ) { _popup->exec( pos ); } #include "kgv_view.moc" // vim:sw=4:sts=4:ts=8:sta:tw=78:noet Index: trunk/kdegraphics/kghostview/thumbnailservice.cpp =================================================================== --- trunk/kdegraphics/kghostview/thumbnailservice.cpp (revision 251917) +++ trunk/kdegraphics/kghostview/thumbnailservice.cpp (revision 251918) @@ -1,117 +1,125 @@ /** * Copyright (C) 1997-2003 the KGhostView authors. See file AUTHORS. * * 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. * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "thumbnailservice.h" #include "kgv_miniwidget.h" #include "kpswidget.h" #include "kgv_view.h" #include #include #include #include ThumbnailService::ThumbnailService( KGVMiniWidget* parent, const char* name ) : QObject( parent, name ), _mini( parent ), - _busy( false ) + _busy( false ), + _enabled( false ) { _thumbnailDrawer = new KPSWidget( parent->_part->widget(), "thumbnail-drawer" ); _thumbnailDrawer->readSettings( _mini->_part->configDialog() ); connect( _thumbnailDrawer, SIGNAL( newPageImage( QPixmap ) ), SLOT( slotDone( QPixmap ) ) ); _thumbnailDrawer->hide(); } ThumbnailService::~ThumbnailService() { } void ThumbnailService::delayedGetThumbnail( const int page, QObject* rec, const char* slot ) { kdDebug( 4500 ) << "ThumbnailService::delayedGetThumbnail: request for page " << page << endl; pending.push_back( Request( page, rec, slot ) ); if ( !_busy ) { _busy = true; // The reason for the code below might not be obvious: // It is much nicer to have the the thumbnails appear from top to bottom. // However, when several are requested at once (or almost), then we cannot control the order // unless we delay a bit the first one to QTimer::singleShot( 150, this, SLOT( processOne() ) ); } } void ThumbnailService::reset() { kdDebug( 4500 ) << "ThumbnailService::reset()" << endl; disconnect( this, SLOT( processOne() ) ); pending.clear(); assert( _thumbnailDrawer ); _thumbnailDrawer->stopInterpreter(); _busy = false; + _enabled = false; } +void ThumbnailService::setEnabled( const bool e ) +{ + _enabled = e; + if ( _enabled && _busy ) processOne(); +} void ThumbnailService::slotDone( QPixmap pix ) { kdDebug( 4500 ) << "ThumbnailService::slotDone(): got page" << endl; pix.detach(); emit relayPixmap( pix ); processOne(); } bool ThumbnailService::pageCmp( ThumbnailService::Request a, ThumbnailService::Request b ) { return a.page < b.page; } void ThumbnailService::processOne() { + if ( !_enabled ) return; assert( _thumbnailDrawer ); if ( pending.empty() ) { _busy = false; return; } _busy = true; FILE* file = _mini->psFile(); std::sort( pending.begin(), pending.end(), pageCmp ); Request req = pending.front(); kdDebug( 4500 ) << "ThumbnailService::processOne(): processing " << req.page << endl; disconnect( SIGNAL( relayPixmap( QPixmap ) ) ); while ( !pending.empty() && req.page == pending.front().page ) { req = pending.front(); connect( this, SIGNAL( relayPixmap( QPixmap ) ), req.receiver, req.slot ); pending.erase( pending.begin() ); } _thumbnailDrawer->setOrientation( _mini->orientation( req.page ) ); _thumbnailDrawer->setBoundingBox( _mini->boundingBox( req.page ) ); _thumbnailDrawer->setMagnification( 0.2 ); if ( !_thumbnailDrawer->isInterpreterRunning() ) { _thumbnailDrawer->setFileName( _mini->_document->fileName(), true ); _thumbnailDrawer->startInterpreter(); _thumbnailDrawer->sendPS( file, _mini->dsc()->beginprolog(), _mini->dsc()->endprolog() ); _thumbnailDrawer->sendPS( file, _mini->dsc()->beginsetup(), _mini->dsc()->endsetup() ); } else { _thumbnailDrawer->nextPage(); } _thumbnailDrawer->sendPS( file, _mini->dsc()->page()[ req.page ].begin, _mini->dsc()->page()[ req.page ].end ); } #include "thumbnailservice.moc"