Index: trunk/kdegraphics/kghostview/kgv_view.cpp =================================================================== --- trunk/kdegraphics/kghostview/kgv_view.cpp (revision 251903) +++ trunk/kdegraphics/kghostview/kgv_view.cpp (revision 251904) @@ -1,978 +1,983 @@ /** * 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() { 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; - _psWidget->stopInterpreter(); - document()->openFile( m_file, _mimetype ); + 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(); + 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/kgvshell.cpp =================================================================== --- trunk/kdegraphics/kghostview/kgvshell.cpp (revision 251903) +++ trunk/kdegraphics/kghostview/kgvshell.cpp (revision 251904) @@ -1,370 +1,373 @@ /** * 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 #include "kgv_miniwidget.h" #include "kgv_view.h" #include "kgvpageview.h" #include "displayoptions.h" #include "fullscreenfilter.h" #undef Always // avoid X11/Qt namespace clash #include "kgvshell.moc" //TODO -- disable GUI when no file //TODO -- don't stay open when no file, go directly to KFileDialog KGVShell::KGVShell() : m_isFullScreen( false ), _tmpFile( 0 ) { m_gvpart = KParts::ComponentFactory::createPartInstanceFromLibrary< KGVPart >( "libkghostviewpart", this, "kgvpart", this, "kgvpart" ); /*---- File -----------------------------------------------------------*/ openact = KStdAction::open( this, SLOT( slotFileOpen() ), actionCollection() ); recent = KStdAction::openRecent( this, SLOT( openURL( const KURL& ) ), actionCollection() ); KStdAction::print( m_gvpart->document(), SLOT( print() ), actionCollection() ); (void) KStdAction::quit( this, SLOT( slotQuit() ), actionCollection() ); /*---- View -----------------------------------------------------------*/ - KStdAction::redisplay( m_gvpart->miniWidget(), SLOT( redisplay() ), - actionCollection()); + new KAction( i18n( "&Reload" ), "reload", + KStdAccel::shortcut( KStdAccel::Reload ), + m_gvpart, SLOT( reloadFile() ), + actionCollection(), "reload" ); new KAction( i18n( "&Fit to Page Width" ), 0, this, SLOT( slotFitToPage() ), actionCollection(), "fit_to_page"); new KAction( i18n( "&Fit to Screen" ), Key_S, this, SLOT( slotFitToScreen() ), actionCollection(), "fit_to_page"); new KAction( i18n( "&Maximize" ), Key_M, this, SLOT( slotMaximize() ), actionCollection(), "maximize"); _showMenuBarAction = KStdAction::showMenubar( this, SLOT( slotShowMenubar() ), actionCollection(), "showmenubar" ); /*---- Settings -------------------------------------------------------*/ #if KDE_VERSION >= KDE_MAKE_VERSION(3,1,90) createStandardStatusBarAction(); #endif setAutoSaveSettings(); setStandardToolBarMenuEnabled(true); #if KDE_VERSION >= KDE_MAKE_VERSION(3,1,90) m_fullScreenAction = KStdAction::fullScreen( this, SLOT( slotToggleFullScreen() ), actionCollection() ); #else m_fullScreenAction = new KToggleAction( this, SLOT( slotToggleFullScreen() ) ); #endif //_popup = new KPopupMenu( i18n( "Full Screen Options" ), this, "rmb popup" ); _popup = new KPopupMenu( this, "rmb popup" ); _popup->insertTitle( i18n( "Full Screen Options" ) ); m_fullScreenAction->plug( _popup ); m_fsFilter = new FullScreenFilter( *this ); // Just save them automatically is destructor. (TODO: of kgv_view!) //KStdAction::saveOptions ( this, SLOT (slotWriteSettings()), actionCollection()); setXMLFile( "kghostviewui.rc" ); // We could, at the user's option, make this connection and kghostview // will always resize to fit the width of the page. But, for now, // let's not. // connect ( m_gvpart->widget(), SIGNAL (sizeHintChanged()), this, SLOT (slotResize ()) ); setCentralWidget( m_gvpart->widget() ); createGUI( m_gvpart ); connect( m_gvpart->pageView(), SIGNAL( rightClick() ),SLOT( slotRMBClick() ) ); connect( m_gvpart, SIGNAL( canceled(const QString&) ),SLOT( slotReset() ) ); mFitTimer = new QTimer( this ); if (!initialGeometrySet()) resize(640,400); readSettings(); stateChanged( "initState" ); // Make sure the view has the keyboard focus. m_gvpart->widget()->setFocus(); } KGVShell::~KGVShell() { writeSettings(); if( _tmpFile ) { _tmpFile->setAutoDelete( true ); delete _tmpFile; _tmpFile = 0; } // delete m_gvpart; } void KGVShell::slotQuit() { kapp->closeAllWindows(); } void KGVShell::slotShowMenubar() { if ( _showMenuBarAction->isChecked() ) menuBar()->show(); else menuBar()->hide(); } void KGVShell::setDisplayOptions( const DisplayOptions& options ) { m_gvpart->setDisplayOptions( options ); } void KGVShell::slotReset() { kdDebug( 4500 ) << "KGVShell::slotReset()" << endl; stateChanged( "initState" ); } void KGVShell::readProperties( KConfig *config ) { KURL url = config->readPathEntry( "URL" ); if ( url.isValid() ) { openURL( url ); DisplayOptions options; if ( DisplayOptions::fromString( options, config->readEntry( "Display Options" ) ) ) m_gvpart->setDisplayOptions( options ); } } void KGVShell::saveProperties( KConfig* config ) { config->writePathEntry( "URL", m_gvpart->url().prettyURL() ); config->writeEntry( "Display Options", DisplayOptions::toString( m_gvpart->miniWidget()->displayOptions() ) ); } void KGVShell::readSettings() { recent->loadEntries( KGlobal::config() ); applyMainWindowSettings(KGlobal::config(), "MainWindow"); KGlobal::config()->setDesktopGroup(); bool fullScreen = KGlobal::config()->readBoolEntry( "FullScreen", false ); m_fullScreenAction->setChecked( fullScreen ); setFullScreen( fullScreen ); } void KGVShell::writeSettings() { saveMainWindowSettings(KGlobal::config(), "MainWindow"); recent->saveEntries( KGlobal::config() ); KGlobal::config()->setDesktopGroup(); KGlobal::config()->writeEntry( "FullScreen", m_isFullScreen ); KGlobal::config()->sync(); } void KGVShell::openURL( const KURL & url ) { if( m_gvpart->openURL( url ) ) { recent->addURL (url); stateChanged( "documentState" ); } } void KGVShell::openStdin() { if( _tmpFile ) { _tmpFile->setAutoDelete( true ); delete _tmpFile; } _tmpFile = new KTempFile; _tmpFile->setAutoDelete( true ); if( _tmpFile->status() != 0 ) { KMessageBox::error( this, i18n( "Could not create temporary file: %1" ) .arg( strerror( _tmpFile->status() ) ) ); return; } QByteArray buf( BUFSIZ ); int read = 0, wrtn = 0; while( ( read = fread( buf.data(), sizeof(char), buf.size(), stdin ) ) > 0 ) { wrtn = _tmpFile->file()->writeBlock( buf.data(), read ); if( read != wrtn ) break; kapp->processEvents(); } if( read != 0 ) { KMessageBox::error( this, i18n( "Could not open standard input stream: %1" ) .arg( strerror( errno ) ) ); return; } _tmpFile->close(); if( m_gvpart->openURL( _tmpFile->name() ) ) { setCaption( "stdin" ); stateChanged( "documentState" ); } } void KGVShell::slotFileOpen() { KURL url = KFileDialog::getOpenURL( cwd, i18n( "*.ps *.ps.bz2 *.ps.gz *.eps *.eps.gz *.pdf|All Document Files\n" "*.ps *.ps.bz2 *.ps.gz|PostScript Files\n" "*.pdf *.pdf.gz *.pdf.bz2|Portable Document Format (PDF) Files\n" "*.eps *.eps.gz *.eps.bz2|Encapsulated PostScript Files\n" "*|All Files" ) ); if( !url.isEmpty() ) { openURL( url ); } } void KGVShell::slotFitToPage() { kdDebug(4500) << "KGVShell::slotFitToPage()" << endl; if( m_gvpart->pageView()->page() ) m_gvpart->miniWidget()->fitWidth( m_gvpart->pageView()->viewport()->width() - 16 ); // We subtract 16 pixels because of the page decoration. } void KGVShell::slotFitToScreen() { kdDebug(4500) << "KGVShell::slotFitToScreen()" << endl; if ( mFitTimer->isActive() ) { disconnect( mFitTimer, SIGNAL( timeout() ), this, 0 ); connect( mFitTimer, SIGNAL( timeout() ), SLOT( slotDoFitToScreen() ) ); } else slotDoFitToScreen(); } void KGVShell::slotDoFitToScreen() { kdDebug(4500) << "KGVShell::slotDoFitToScreen()" << endl; if( m_gvpart->pageView()->page() ) m_gvpart->miniWidget()->fitWidthHeight( m_gvpart->pageView()->viewport()->width() - 16, m_gvpart->pageView()->viewport()->height() - 16 ); } void KGVShell::slotMaximize() { kdDebug(4500) << "KGVShell::slotMaximize()" << endl; KWin::setState( winId(), NET::MaxHoriz | NET::MaxVert ); // If we do it now, it comes to nothing since it would work // on the current (non-maximized) size disconnect( mFitTimer, SIGNAL( timeout() ), this, 0 ); connect( mFitTimer, SIGNAL( timeout() ), SLOT( slotFitToPage() ) ); mFitTimer->start( 800, true ); } void KGVShell::slotResize() { resize( m_gvpart->pageView()->sizeHint().width(), height() ); } void KGVShell::slotToggleFullScreen() { setFullScreen(m_fullScreenAction->isChecked()); } void KGVShell::setFullScreen( bool useFullScreen ) { m_isFullScreen = useFullScreen; if( m_isFullScreen ) { menuBar()->hide(); statusBar()->hide(); toolBar()->hide(); m_gvpart->setFullScreen( true ); showFullScreen(); kapp->installEventFilter( m_fsFilter ); if ( m_gvpart->document()->isOpen() ) slotFitToPage(); } else { kapp->removeEventFilter( m_fsFilter ); m_gvpart->setFullScreen( false ); menuBar()->show(); #if KDE_VERSION >= KDE_MAKE_VERSION(3,1,90) KToggleAction *statusbarAction = dynamic_cast(actionCollection()->action(KStdAction::name(KStdAction::ShowStatusbar))); assert( statusbarAction ); if (statusbarAction->isChecked()) statusBar()->show(); #endif toolBar()->show(); showNormal(); } } void KGVShell::slotRMBClick() { _popup->exec( QCursor::pos() ); } // vim:sw=4:sts=4:ts=8:noet Index: trunk/kdegraphics/kghostview/kghostviewui.rc =================================================================== --- trunk/kdegraphics/kghostview/kghostviewui.rc (revision 251903) +++ trunk/kdegraphics/kghostview/kghostviewui.rc (revision 251904) @@ -1,45 +1,46 @@ - + - + - + + Index: trunk/kdegraphics/kghostview/kgv_view.h =================================================================== --- trunk/kdegraphics/kghostview/kgv_view.h (revision 251903) +++ trunk/kdegraphics/kghostview/kgv_view.h (revision 251904) @@ -1,254 +1,259 @@ /** * 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. */ #ifndef __KGV_VIEW_H #define __KGV_VIEW_H #include // QByteArray #include #include #include #include #include "displayoptions.h" class QFrame; class QWidget; class KAboutData; class KAction; class KActionCollection; class KDirWatch; class KInstance; class KPopupMenu; class KSelectAction; class KToggleAction; class KGVBrowserExtension; class KGVConfigDialog; class KGVDocument; class KGVMiniWidget; class KGVPageView; class KGVPageDecorator; class KGVRun; class KPSWidget; class LogWindow; class MarkList; class ScrollBox; class KGVPart: public KParts::ReadOnlyPart { Q_OBJECT public: KGVPart( QWidget* parentWidget, const char* widgetName, QObject* parent, const char* name, const QStringList& args = QStringList() ); virtual ~KGVPart(); KGVMiniWidget* miniWidget() const { return _docManager; } MarkList* markList() const { return _markList; } ScrollBox* scrollBox() { return _scrollBox; } KGVPageView* pageView() const { return _pageView; } KGVPageDecorator* pageDecorator() const { return _pageDecorator; } KGVDocument* document() const { return _document; } const KGVConfigDialog* configDialog() { return _configDialog; } /** * Reimplemented from ReadOnlyPart in order to delete the file from * KDirWatch's list. */ virtual bool closeURL(); static KAboutData* createAboutData(); public slots: /** * Reimplemented from ReadOnlyPart so that incoming data can be sent * through the DSC parser immediately on arrival. */ virtual bool openURL( const KURL& ); virtual void openURLContinue(); + /** + * Reloads the current file. + * No action if no file is loaded + */ + void reloadFile(); void setFullScreen( bool ); void showPopup( int, int, const QPoint &pos ); void slotScrollLeft(); void slotScrollRight(); void slotScrollUp(); void slotScrollDown(); void slotReadDown(); void slotReadUp(); void slotPrevPage(); void slotNextPage(); void slotGotoStart(); void slotGotoEnd(); // void slotFitWidth(); void showScrollBars( bool ); void slotCancelWatch(); void showMarkList( bool ); void showPageLabels( bool ); void slotZoomIn(); void slotZoomOut(); void slotZoom( const QString& ); void slotConfigure(); /** * Sets the display options in a sticky way. * This means that the file being opened or the next one to be open will * get these options. This is useful for session management or commandline * arguments */ void setDisplayOptions( const DisplayOptions& opts ); protected slots: void slotData( KIO::Job*, const QByteArray& ); void slotJobFinished( KIO::Job* ); void slotMimetypeFinished( const QString& ); void slotMimetypeError(); void slotFileDirty( const QString& ); void slotDoFileDirty(); void slotOrientation (int); void slotMedia (int); void slotNewPage( int ); void slotPageMoved( int, int ); void slotWatchFile(); void slotOpenFileCompleted(); void slotConfigureKeys(); protected: virtual void guiActivateEvent( KParts::GUIActivateEvent* ); // reimplemented from ReadOnlyPart virtual bool openFile(); void updatePageDepActions(); void updateZoomActions(); void updateReadUpDownActions(); void readSettings(); void writeSettings(); private slots: void slotGhostscriptOutput( char* data, int len ); void slotGhostscriptError( const QString& ); private: KGVBrowserExtension* _extension; KGVDocument* _document; QWidget* _mainWidget; KGVPageView* _pageView; KGVPageDecorator* _pageDecorator; KPSWidget* _psWidget; ScrollBox* _scrollBox; QFrame* _divider; MarkList* _markList; KGVMiniWidget* _docManager; KGVConfigDialog* _configDialog; LogWindow* _logWindow; KSelectAction* _selectOrientation; KSelectAction* _selectMedia; KAction* _zoomIn; KAction* _zoomOut; KSelectAction* _zoomTo; // KAction* _fitWidth; KAction* _prevPage; KAction* _nextPage; KAction* _firstPage; KAction* _lastPage; KAction* _readUp; KAction* _readDown; KAction* _gotoPage; KToggleAction* _showScrollBars; KToggleAction* _watchFile; KToggleAction* _showPageList; KToggleAction* _showPageLabels; KPopupMenu* _popup; QFile _tmpFile; KIO::TransferJob* _job; KDirWatch* _fileWatcher; KGVRun* _mimetypeScanner; QTimer* _dirtyHandler; QString _mimetype; bool _isGuiInitialized : 1; bool _isFileDirty : 1; bool _showLogWindow : 1; bool _stickyOptions : 1; DisplayOptions _options; }; class KGVBrowserExtension : public KParts::BrowserExtension { Q_OBJECT friend class KGVPart; // emits our signals public: KGVBrowserExtension( KGVPart* parent ); virtual ~KGVBrowserExtension() {} public slots: // Automatically detected by konqueror void print(); }; class KGVRun : public KRun { Q_OBJECT public: KGVRun( const KURL& url, mode_t mode = 0, bool isLocalFile = false, bool showProgressInfo = true ); virtual ~KGVRun(); signals: void finished( const QString& mimetype ); protected: void foundMimeType( const QString& mimetype ); protected slots: void emitFinishedWithMimetype() { emit finished( _mimetype ); } private: QString _mimetype; }; #endif // vim:sw=4:sts=4:ts=8:sta:tw=78:noet