summaryrefslogtreecommitdiffstats
path: root/kpdf/part.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kpdf/part.cpp')
-rw-r--r--kpdf/part.cpp1100
1 files changed, 1100 insertions, 0 deletions
diff --git a/kpdf/part.cpp b/kpdf/part.cpp
new file mode 100644
index 00000000..69ad7f00
--- /dev/null
+++ b/kpdf/part.cpp
@@ -0,0 +1,1100 @@
+/***************************************************************************
+ * Copyright (C) 2002 by Wilco Greven <[email protected]> *
+ * Copyright (C) 2002 by Chris Cheney <[email protected]> *
+ * Copyright (C) 2002 by Malcolm Hunter <[email protected]> *
+ * Copyright (C) 2003-2004 by Christophe Devriese *
+ * Copyright (C) 2003 by Daniel Molkentin <[email protected]> *
+ * Copyright (C) 2003 by Andy Goossens <[email protected]> *
+ * Copyright (C) 2003 by Dirk Mueller <[email protected]> *
+ * Copyright (C) 2003 by Laurent Montel <[email protected]> *
+ * Copyright (C) 2004 by Dominique Devriese <[email protected]> *
+ * Copyright (C) 2004 by Christoph Cullmann <[email protected]> *
+ * Copyright (C) 2004 by Henrique Pinto <[email protected]> *
+ * Copyright (C) 2004 by Waldo Bastian <[email protected]> *
+ * Copyright (C) 2004-2006 by Albert Astals Cid <[email protected]> *
+ * Copyright (C) 2004 by Antti Markus <[email protected]> *
+ * *
+ * 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. *
+ ***************************************************************************/
+
+// qt/kde includes
+#include <qcheckbox.h>
+#include <qsplitter.h>
+#include <qpainter.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qvbox.h>
+#include <qtoolbox.h>
+#include <qtooltip.h>
+#include <qpushbutton.h>
+#include <qwhatsthis.h>
+#include <dcopobject.h>
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kaction.h>
+#include <kdirwatch.h>
+#include <kinstance.h>
+#include <kprinter.h>
+#include <kdeprint/kprintdialogpage.h>
+#include <kstdaction.h>
+#include <kdeversion.h>
+#include <kparts/genericfactory.h>
+#include <kurldrag.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <kfinddialog.h>
+#include <knuminput.h>
+#include <kiconloader.h>
+#include <kio/netaccess.h>
+#include <kio/job.h>
+#include <kpopupmenu.h>
+#include <kprocess.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <ktrader.h>
+#include <kxmlguiclient.h>
+#include <kxmlguifactory.h>
+
+// local includes
+#include "xpdf/GlobalParams.h"
+#include "part.h"
+#include "ui/pageview.h"
+#include "ui/thumbnaillist.h"
+#include "ui/searchwidget.h"
+#include "ui/toc.h"
+#include "ui/minibar.h"
+#include "ui/propertiesdialog.h"
+#include "ui/presentationwidget.h"
+#include "conf/preferencesdialog.h"
+#include "conf/settings.h"
+#include "core/document.h"
+#include "core/page.h"
+
+class PDFOptionsPage : public KPrintDialogPage
+{
+ public:
+ PDFOptionsPage()
+ {
+ setTitle( i18n( "PDF Options" ) );
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ m_forceRaster = new QCheckBox(i18n("Force rasterization"), this);
+ QToolTip::add(m_forceRaster, i18n("Rasterize into an image before printing"));
+ QWhatsThis::add(m_forceRaster, i18n("Forces the rasterization of each page into an image before printing it. This usually gives somewhat worse results, but is useful when printing documents that appear to print incorrectly."));
+ layout->addWidget(m_forceRaster);
+ layout->addStretch(1);
+ }
+
+ void getOptions( QMap<QString,QString>& opts, bool incldef = false )
+ {
+ Q_UNUSED(incldef);
+ opts[ "kde-kpdf-forceRaster" ] = QString::number( m_forceRaster->isChecked() );
+ }
+
+ void setOptions( const QMap<QString,QString>& opts )
+ {
+ m_forceRaster->setChecked( opts[ "kde-kpdf-forceRaster" ].toInt() );
+ }
+
+ private:
+ QCheckBox *m_forceRaster;
+};
+
+// definition of searchID for this class
+#define PART_SEARCH_ID 1
+
+typedef KParts::GenericFactory<KPDF::Part> KPDFPartFactory;
+K_EXPORT_COMPONENT_FACTORY(libkpdfpart, KPDFPartFactory)
+
+using namespace KPDF;
+
+unsigned int Part::m_count = 0;
+
+Part::Part(QWidget *parentWidget, const char *widgetName,
+ QObject *parent, const char *name,
+ const QStringList & /*args*/ )
+ : DCOPObject("kpdf"), KParts::ReadOnlyPart(parent, name), m_showMenuBarAction(0), m_showFullScreenAction(0),
+ m_actionsSearched(false), m_searchStarted(false)
+{
+ // connect the started signal to tell the job the mimetypes we like
+ connect(this, SIGNAL(started(KIO::Job *)), this, SLOT(setMimeTypes(KIO::Job *)));
+
+ // connect the completed signal so we can put the window caption when loading remote files
+ connect(this, SIGNAL(completed()), this, SLOT(emitWindowCaption()));
+ connect(this, SIGNAL(canceled(const QString &)), this, SLOT(emitWindowCaption()));
+
+ // load catalog for translation
+ KGlobal::locale()->insertCatalogue("kpdf");
+
+ // create browser extension (for printing when embedded into browser)
+ m_bExtension = new BrowserExtension(this);
+
+ // xpdf 'extern' global class (m_count is a static instance counter)
+ //if ( m_count ) TODO check if we need to insert these lines..
+ // delete globalParams;
+ globalParams = new GlobalParams("");
+ globalParams->setupBaseFonts(NULL);
+ m_count++;
+
+ // we need an instance
+ setInstance(KPDFPartFactory::instance());
+
+ // build the document
+ m_document = new KPDFDocument(widget());
+ connect( m_document, SIGNAL( linkFind() ), this, SLOT( slotFind() ) );
+ connect( m_document, SIGNAL( linkGoToPage() ), this, SLOT( slotGoToPage() ) );
+ connect( m_document, SIGNAL( linkPresentation() ), this, SLOT( slotShowPresentation() ) );
+ connect( m_document, SIGNAL( linkEndPresentation() ), this, SLOT( slotHidePresentation() ) );
+ connect( m_document, SIGNAL( openURL(const KURL &) ), this, SLOT( openURLFromDocument(const KURL &) ) );
+ connect( m_document, SIGNAL( close() ), this, SLOT( close() ) );
+
+ if (parent && parent->metaObject()->slotNames(true).contains("slotQuit()"))
+ connect( m_document, SIGNAL( quit() ), parent, SLOT( slotQuit() ) );
+ else
+ connect( m_document, SIGNAL( quit() ), this, SLOT( cannotQuit() ) );
+
+ // widgets: ^searchbar (toolbar containing label and SearchWidget)
+// m_searchToolBar = new KToolBar( parentWidget, "searchBar" );
+// m_searchToolBar->boxLayout()->setSpacing( KDialog::spacingHint() );
+// QLabel * sLabel = new QLabel( i18n( "&Search:" ), m_searchToolBar, "kde toolbar widget" );
+// m_searchWidget = new SearchWidget( m_searchToolBar, m_document );
+// sLabel->setBuddy( m_searchWidget );
+// m_searchToolBar->setStretchableWidget( m_searchWidget );
+
+ // widgets: [] splitter []
+ m_splitter = new QSplitter( parentWidget, widgetName );
+ m_splitter->setOpaqueResize( true );
+ setWidget( m_splitter );
+
+ m_showLeftPanel = new KToggleAction( i18n( "Show &Navigation Panel"), "show_side_panel", 0, this, SLOT( slotShowLeftPanel() ), actionCollection(), "show_leftpanel" );
+ m_showLeftPanel->setCheckedState( i18n( "Hide &Navigation Panel") );
+ m_showLeftPanel->setShortcut( "CTRL+L" );
+ m_showLeftPanel->setChecked( KpdfSettings::showLeftPanel() );
+
+ // widgets: [left panel] | []
+ m_leftPanel = new QWidget( m_splitter );
+ m_leftPanel->setMinimumWidth( 90 );
+ m_leftPanel->setMaximumWidth( 300 );
+ QVBoxLayout * leftPanelLayout = new QVBoxLayout( m_leftPanel );
+
+ // widgets: [left toolbox/..] | []
+ m_toolBox = new QToolBox( m_leftPanel );
+ leftPanelLayout->addWidget( m_toolBox );
+
+ int index;
+ // [left toolbox: Table of Contents] | []
+ // dummy wrapper with layout to enable horizontal scroll bars (bug: 147233)
+ QWidget *tocWrapper = new QWidget(m_toolBox);
+ QVBoxLayout *tocWrapperLayout = new QVBoxLayout(tocWrapper);
+ m_tocFrame = new TOC( tocWrapper, m_document );
+ tocWrapperLayout->add(m_tocFrame);
+ connect(m_tocFrame, SIGNAL(hasTOC(bool)), this, SLOT(enableTOC(bool)));
+ index = m_toolBox->addItem( tocWrapper, QIconSet(SmallIcon("text_left")), i18n("Contents") );
+ m_toolBox->setItemToolTip(index, i18n("Contents"));
+ enableTOC( false );
+
+ // [left toolbox: Thumbnails and Bookmarks] | []
+ QVBox * thumbsBox = new ThumbnailsBox( m_toolBox );
+ m_searchWidget = new SearchWidget( thumbsBox, m_document );
+ m_thumbnailList = new ThumbnailList( thumbsBox, m_document );
+// ThumbnailController * m_tc = new ThumbnailController( thumbsBox, m_thumbnailList );
+ connect( m_thumbnailList, SIGNAL( urlDropped( const KURL& ) ), SLOT( openURLFromDocument( const KURL & )) );
+ connect( m_thumbnailList, SIGNAL( rightClick(const KPDFPage *, const QPoint &) ), this, SLOT( slotShowMenu(const KPDFPage *, const QPoint &) ) );
+ // shrink the bottom controller toolbar (too hackish..)
+ thumbsBox->setStretchFactor( m_searchWidget, 100 );
+ thumbsBox->setStretchFactor( m_thumbnailList, 100 );
+// thumbsBox->setStretchFactor( m_tc, 1 );
+ index = m_toolBox->addItem( thumbsBox, QIconSet(SmallIcon("thumbnail")), i18n("Thumbnails") );
+ m_toolBox->setItemToolTip(index, i18n("Thumbnails"));
+ m_toolBox->setCurrentItem( thumbsBox );
+
+ slotShowLeftPanel();
+
+/* // [left toolbox: Annotations] | []
+ QFrame * editFrame = new QFrame( m_toolBox );
+ int iIdx = m_toolBox->addItem( editFrame, QIconSet(SmallIcon("pencil")), i18n("Annotations") );
+ m_toolBox->setItemEnabled( iIdx, false );*/
+
+ // widgets: [../miniBarContainer] | []
+ QWidget * miniBarContainer = new QWidget( m_leftPanel );
+ leftPanelLayout->addWidget( miniBarContainer );
+ QVBoxLayout * miniBarLayout = new QVBoxLayout( miniBarContainer );
+ // widgets: [../[spacer/..]] | []
+ QWidget * miniSpacer = new QWidget( miniBarContainer );
+ miniSpacer->setFixedHeight( 6 );
+ miniBarLayout->addWidget( miniSpacer );
+ // widgets: [../[../MiniBar]] | []
+ m_miniBar = new MiniBar( miniBarContainer, m_document );
+ miniBarLayout->addWidget( m_miniBar );
+
+ // widgets: [] | [right 'pageView']
+ m_pageView = new PageView( m_splitter, m_document );
+ m_pageView->setFocus(); //usability setting
+ m_splitter->setFocusProxy(m_pageView);
+ connect( m_pageView, SIGNAL( urlDropped( const KURL& ) ), SLOT( openURLFromDocument( const KURL & )));
+ connect( m_pageView, SIGNAL( rightClick(const KPDFPage *, const QPoint &) ), this, SLOT( slotShowMenu(const KPDFPage *, const QPoint &) ) );
+
+ // add document observers
+ m_document->addObserver( this );
+ m_document->addObserver( m_thumbnailList );
+ m_document->addObserver( m_pageView );
+ m_document->addObserver( m_tocFrame );
+ m_document->addObserver( m_miniBar );
+
+ // ACTIONS
+ KActionCollection * ac = actionCollection();
+
+ // Page Traversal actions
+ m_gotoPage = KStdAction::gotoPage( this, SLOT( slotGoToPage() ), ac, "goto_page" );
+ m_gotoPage->setShortcut( "CTRL+G" );
+ // dirty way to activate gotopage when pressing miniBar's button
+ connect( m_miniBar, SIGNAL( gotoPage() ), m_gotoPage, SLOT( activate() ) );
+
+ m_prevPage = KStdAction::prior(this, SLOT(slotPreviousPage()), ac, "previous_page");
+ m_prevPage->setWhatsThis( i18n( "Moves to the previous page of the document" ) );
+ m_prevPage->setShortcut( 0 );
+ // dirty way to activate prev page when pressing miniBar's button
+ connect( m_miniBar, SIGNAL( prevPage() ), m_prevPage, SLOT( activate() ) );
+
+ m_nextPage = KStdAction::next(this, SLOT(slotNextPage()), ac, "next_page" );
+ m_nextPage->setWhatsThis( i18n( "Moves to the next page of the document" ) );
+ m_nextPage->setShortcut( 0 );
+ // dirty way to activate next page when pressing miniBar's button
+ connect( m_miniBar, SIGNAL( nextPage() ), m_nextPage, SLOT( activate() ) );
+
+ m_firstPage = KStdAction::firstPage( this, SLOT( slotGotoFirst() ), ac, "first_page" );
+ m_firstPage->setWhatsThis( i18n( "Moves to the first page of the document" ) );
+
+ m_lastPage = KStdAction::lastPage( this, SLOT( slotGotoLast() ), ac, "last_page" );
+ m_lastPage->setWhatsThis( i18n( "Moves to the last page of the document" ) );
+
+ m_historyBack = KStdAction::back( this, SLOT( slotHistoryBack() ), ac, "history_back" );
+ m_historyBack->setWhatsThis( i18n( "Go to the place you were before" ) );
+
+ m_historyNext = KStdAction::forward( this, SLOT( slotHistoryNext() ), ac, "history_forward" );
+ m_historyNext->setWhatsThis( i18n( "Go to the place you were after" ) );
+
+ // Find and other actions
+ m_find = KStdAction::find( this, SLOT( slotFind() ), ac, "find" );
+ m_find->setEnabled( false );
+
+ m_findNext = KStdAction::findNext( this, SLOT( slotFindNext() ), ac, "find_next" );
+ m_findNext->setEnabled( false );
+
+ m_saveAs = KStdAction::saveAs( this, SLOT( slotSaveFileAs() ), ac, "save" );
+ m_saveAs->setEnabled( false );
+ KAction * prefs = KStdAction::preferences( this, SLOT( slotPreferences() ), ac, "preferences" );
+ prefs->setText( i18n( "Configure KPDF..." ) );
+ m_printPreview = KStdAction::printPreview( this, SLOT( slotPrintPreview() ), ac );
+ m_printPreview->setEnabled( false );
+
+ m_showProperties = new KAction(i18n("&Properties"), "info", 0, this, SLOT(slotShowProperties()), ac, "properties");
+ m_showProperties->setEnabled( false );
+
+ m_showPresentation = new KAction( i18n("P&resentation"), "kpresenter_kpr", "Ctrl+Shift+P", this, SLOT(slotShowPresentation()), ac, "presentation");
+ m_showPresentation->setEnabled( false );
+
+ // attach the actions of the children widgets too
+ m_pageView->setupActions( ac );
+
+ // apply configuration (both internal settings and GUI configured items)
+ QValueList<int> splitterSizes = KpdfSettings::splitterSizes();
+ if ( !splitterSizes.count() )
+ {
+ // the first time use 1/10 for the panel and 9/10 for the pageView
+ splitterSizes.push_back( 50 );
+ splitterSizes.push_back( 500 );
+ }
+ m_splitter->setSizes( splitterSizes );
+ // get notified about splitter size changes (HACK that will be removed
+ // by connecting to Qt4::QSplitter's sliderMoved())
+ m_pageView->installEventFilter( this );
+ m_watcher = new KDirWatch( this );
+ connect( m_watcher, SIGNAL( dirty( const QString& ) ), this, SLOT( slotFileDirty( const QString& ) ) );
+ m_dirtyHandler = new QTimer( this );
+ connect( m_dirtyHandler, SIGNAL( timeout() ),this, SLOT( slotDoFileDirty() ) );
+ m_saveSplitterSizeTimer = new QTimer( this );
+ connect( m_saveSplitterSizeTimer, SIGNAL( timeout() ),this, SLOT( saveSplitterSize() ) );
+
+ slotNewConfig();
+
+ // [SPEECH] check for KTTSD presence and usability
+ KTrader::OfferList offers = KTrader::self()->query("DCOP/Text-to-Speech", "Name == 'KTTSD'");
+ KpdfSettings::setUseKTTSD( (offers.count() > 0) );
+ KpdfSettings::writeConfig();
+
+ // set our XML-UI resource file
+ setXMLFile("part.rc");
+ updateViewActions();
+}
+
+Part::~Part()
+{
+ delete m_tocFrame;
+ delete m_pageView;
+ delete m_thumbnailList;
+ delete m_miniBar;
+
+ delete m_document;
+ if ( --m_count == 0 )
+ delete globalParams;
+}
+
+void Part::notifyViewportChanged( bool /*smoothMove*/ )
+{
+ // update actions if the page is changed
+ static int lastPage = -1;
+ int viewportPage = m_document->viewport().pageNumber;
+ if ( viewportPage != lastPage )
+ {
+ updateViewActions();
+ lastPage = viewportPage;
+ }
+}
+
+void Part::goToPage(uint i)
+{
+ if ( i <= m_document->pages() )
+ m_document->setViewportPage( i - 1 );
+}
+
+void Part::openDocument(KURL doc)
+{
+ openURL(doc);
+}
+
+uint Part::pages()
+{
+ return m_document->pages();
+}
+
+uint Part::currentPage()
+{
+ if ( m_document->pages() == 0 ) return 0;
+ else return m_document->currentPage()+1;
+}
+
+KURL Part::currentDocument()
+{
+ return m_document->currentDocument();
+}
+
+//this don't go anywhere but is required by genericfactory.h
+KAboutData* Part::createAboutData()
+{
+ // the non-i18n name here must be the same as the directory in
+ // which the part's rc file is installed ('partrcdir' in the
+ // Makefile)
+ KAboutData* aboutData = new KAboutData("kpdfpart", I18N_NOOP("KPDF::Part"), "0.1");
+ aboutData->addAuthor("Wilco Greven", 0, "[email protected]");
+ return aboutData;
+}
+
+bool Part::openFile()
+{
+ KMimeType::Ptr mime;
+ if ( m_bExtension->urlArgs().serviceType.isEmpty() )
+ {
+ if (!m_jobMime.isEmpty())
+ {
+ mime = KMimeType::mimeType(m_jobMime);
+ if ( mime->is( "application/octet-stream" ) )
+ {
+ mime = KMimeType::findByPath( m_file );
+ }
+ }
+ else
+ {
+ mime = KMimeType::findByPath( m_file );
+ }
+ }
+ else
+ {
+ mime = KMimeType::mimeType( m_bExtension->urlArgs().serviceType );
+ }
+ if ( (*mime).is( "application/postscript" ) )
+ {
+ QString app = KStandardDirs::findExe( "ps2pdf" );
+ if ( !app.isNull() )
+ {
+ if ( QFile::exists(m_file) )
+ {
+ KTempFile tf( QString::null, ".pdf" );
+ if ( tf.status() == 0 )
+ {
+ tf.close();
+ m_temporaryLocalFile = tf.name();
+
+ KProcess *p = new KProcess;
+ *p << app;
+ *p << m_file << m_temporaryLocalFile;
+ m_pageView->showText(i18n("Converting from ps to pdf..."), 0);
+ connect(p, SIGNAL(processExited(KProcess *)), this, SLOT(psTransformEnded()));
+ p -> start();
+ return true;
+ }
+ else return false;
+ }
+ else return false;
+ }
+ else
+ {
+ KMessageBox::error(widget(), i18n("You do not have ps2pdf installed, so kpdf cannot open postscript files."));
+ return false;
+ }
+ }
+
+ m_temporaryLocalFile = QString::null;
+
+ bool ok = m_document->openDocument( m_file, url(), mime );
+
+ // update one-time actions
+ m_find->setEnabled( ok && m_document-> supportsSearching());
+ m_findNext->setEnabled( ok && m_document-> supportsSearching());
+ m_saveAs->setEnabled( ok );
+ m_printPreview->setEnabled( ok );
+ m_showProperties->setEnabled( ok );
+ m_showPresentation->setEnabled( ok );
+
+ // update viewing actions
+ updateViewActions();
+
+ if ( !ok )
+ {
+ // if can't open document, update windows so they display blank contents
+ m_pageView->updateContents();
+ m_thumbnailList->updateContents();
+ return false;
+ }
+
+ // set the file to the fileWatcher
+ if ( !m_watcher->contains(m_file) )
+ m_watcher->addFile(m_file);
+
+ // if the 'OpenTOC' flag is set, open the TOC
+ if ( m_document->getMetaData( "OpenTOC" ) == "yes" && m_toolBox->isItemEnabled( 0 ) )
+ {
+ m_toolBox->setCurrentIndex( 0 );
+ }
+ // if the 'StartFullScreen' flag is set, start presentation
+ if ( m_document->getMetaData( "StartFullScreen" ) == "yes" )
+ {
+ KMessageBox::information(m_presentationWidget, i18n("The document is going to be launched on presentation mode because the file requested it."), QString::null, "autoPresentationWarning");
+ slotShowPresentation();
+ }
+
+ return true;
+}
+
+void Part::openURLFromDocument(const KURL &url)
+{
+ m_bExtension->openURLNotify();
+ m_bExtension->setLocationBarURL(url.prettyURL());
+ openURL(url);
+}
+
+bool Part::openURL(const KURL &url)
+{
+ // note: this can be the right place to check the file for gz or bz2 extension
+ // if it matches then: download it (if not local) extract to a temp file using
+ // KTar and proceed with the URL of the temporary file
+
+ m_jobMime = QString::null;
+
+ // this calls the above 'openURL' method
+ bool b = KParts::ReadOnlyPart::openURL(url);
+
+ // these setWindowCaption calls only work for local files
+ if ( !b )
+ {
+ KMessageBox::error( widget(), i18n("Could not open %1").arg( url.prettyURL() ) );
+ emit setWindowCaption("");
+ }
+ else
+ {
+ m_viewportDirty.pageNumber = -1;
+ emit setWindowCaption(url.filename());
+ }
+ emit enablePrintAction(b);
+ return b;
+}
+
+void Part::setMimeTypes(KIO::Job *job)
+{
+ if (job)
+ {
+ job->addMetaData("accept", "application/pdf, */*;q=0.5");
+ connect(job, SIGNAL(mimetype(KIO::Job*,const QString&)), this, SLOT(readMimeType(KIO::Job*,const QString&)));
+ }
+}
+
+void Part::readMimeType(KIO::Job *, const QString &mime)
+{
+ m_jobMime = mime;
+}
+
+void Part::emitWindowCaption()
+{
+ // these setWindowCaption call only works for remote files
+ if (m_document->isOpened()) emit setWindowCaption(url().filename());
+ else emit setWindowCaption("");
+}
+
+bool Part::closeURL()
+{
+ if (!m_temporaryLocalFile.isNull())
+ {
+ QFile::remove( m_temporaryLocalFile );
+ m_temporaryLocalFile = QString::null;
+ }
+
+ slotHidePresentation();
+ m_find->setEnabled( false );
+ m_findNext->setEnabled( false );
+ m_saveAs->setEnabled( false );
+ m_printPreview->setEnabled( false );
+ m_showProperties->setEnabled( false );
+ m_showPresentation->setEnabled( false );
+ emit setWindowCaption("");
+ emit enablePrintAction(false);
+ m_searchStarted = false;
+ if (!m_file.isEmpty()) m_watcher->removeFile(m_file);
+ m_document->closeDocument();
+ updateViewActions();
+ m_searchWidget->clearText();
+ return KParts::ReadOnlyPart::closeURL();
+}
+
+bool Part::eventFilter( QObject * watched, QEvent * e )
+{
+ // if pageView has been resized, save splitter sizes
+ if ( watched == m_pageView && e->type() == QEvent::Resize )
+ m_saveSplitterSizeTimer->start(500, true);
+
+ // only intercept events, don't block them
+ return false;
+}
+
+void Part::slotShowLeftPanel()
+{
+ bool showLeft = m_showLeftPanel->isChecked();
+ KpdfSettings::setShowLeftPanel(showLeft);
+ KpdfSettings::writeConfig();
+ // show/hide left qtoolbox
+ m_leftPanel->setShown( showLeft );
+ // this needs to be hidden explicitly to disable thumbnails gen
+ m_thumbnailList->setShown( showLeft );
+}
+
+void Part::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 )
+ {
+ m_dirtyHandler->start( 750, true );
+ }
+}
+
+void Part::slotDoFileDirty()
+{
+ if (m_viewportDirty.pageNumber == -1)
+ {
+ m_viewportDirty = m_document->viewport();
+ m_dirtyToolboxIndex = m_toolBox->currentIndex();
+ m_wasPresentationOpen = ((PresentationWidget*)m_presentationWidget != 0);
+ m_pageView->showText(i18n("Reloading the document..."), 0);
+ }
+
+ if (KParts::ReadOnlyPart::openURL(KURL::fromPathOrURL(m_file)))
+ {
+ if (m_viewportDirty.pageNumber >= (int)m_document->pages()) m_viewportDirty.pageNumber = (int)m_document->pages() - 1;
+ m_document->setViewport(m_viewportDirty);
+ m_viewportDirty.pageNumber = -1;
+ if ( m_toolBox->currentIndex() != m_dirtyToolboxIndex && m_toolBox->isItemEnabled( m_dirtyToolboxIndex ) )
+ {
+ m_toolBox->setCurrentIndex( m_dirtyToolboxIndex );
+ }
+ if (m_wasPresentationOpen) slotShowPresentation();
+ emit enablePrintAction(true);
+ emit setWindowCaption(url().filename());
+ }
+ else
+ {
+ m_watcher->addFile(m_file);
+ m_dirtyHandler->start( 750, true );
+ }
+}
+
+void Part::close()
+{
+ if (parent() && strcmp(parent()->name(), "KPDF::Shell") == 0)
+ {
+ closeURL();
+ }
+ else KMessageBox::information(widget(), i18n("This link points to a close document action that does not work when using the embedded viewer."), QString::null, "warnNoCloseIfNotInKPDF");
+}
+
+void Part::updateViewActions()
+{
+ bool opened = m_document->pages() > 0;
+ if ( opened )
+ {
+ bool atBegin = m_document->currentPage() < 1;
+ bool atEnd = m_document->currentPage() >= (m_document->pages() - 1);
+ m_gotoPage->setEnabled( m_document->pages() > 1 );
+ m_firstPage->setEnabled( !atBegin );
+ m_prevPage->setEnabled( !atBegin );
+ m_lastPage->setEnabled( !atEnd );
+ m_nextPage->setEnabled( !atEnd );
+ m_historyBack->setEnabled( !m_document->historyAtBegin() );
+ m_historyNext->setEnabled( !m_document->historyAtEnd() );
+ }
+ else
+ {
+ m_gotoPage->setEnabled( false );
+ m_firstPage->setEnabled( false );
+ m_lastPage->setEnabled( false );
+ m_prevPage->setEnabled( false );
+ m_nextPage->setEnabled( false );
+ m_historyBack->setEnabled( false );
+ m_historyNext->setEnabled( false );
+ }
+}
+
+void Part::enableTOC(bool enable)
+{
+ m_toolBox->setItemEnabled(0, enable);
+}
+
+void Part::psTransformEnded()
+{
+ QString aux = m_file;
+ m_file = m_temporaryLocalFile;
+ openFile();
+ m_file = aux; // so watching works, we have to watch the ps file not the autogenerated pdf
+ m_watcher->removeFile(m_temporaryLocalFile);
+ if ( !m_watcher->contains(m_file) )
+ m_watcher->addFile(m_file);
+}
+
+void Part::cannotQuit()
+{
+ KMessageBox::information(widget(), i18n("This link points to a quit application action that does not work when using the embedded viewer."), QString::null, "warnNoQuitIfNotInKPDF");
+}
+
+void Part::saveSplitterSize()
+{
+ KpdfSettings::setSplitterSizes( m_splitter->sizes() );
+ KpdfSettings::writeConfig();
+}
+
+//BEGIN go to page dialog
+class KPDFGotoPageDialog : public KDialogBase
+{
+public:
+ KPDFGotoPageDialog(QWidget *p, int current, int max) : KDialogBase(p, 0L, true, i18n("Go to Page"), Ok | Cancel, Ok) {
+ QWidget *w = new QWidget(this);
+ setMainWidget(w);
+
+ QVBoxLayout *topLayout = new QVBoxLayout( w, 0, spacingHint() );
+ e1 = new KIntNumInput(current, w);
+ e1->setRange(1, max);
+ e1->setEditFocus(true);
+
+ QLabel *label = new QLabel( e1,i18n("&Page:"), w );
+ topLayout->addWidget(label);
+ topLayout->addWidget(e1);
+ topLayout->addSpacing(spacingHint()); // A little bit extra space
+ topLayout->addStretch(10);
+ e1->setFocus();
+ }
+
+ int getPage() {
+ return e1->value();
+ }
+
+ protected:
+ KIntNumInput *e1;
+};
+//END go to page dialog
+
+void Part::slotGoToPage()
+{
+ KPDFGotoPageDialog pageDialog( m_pageView, m_document->currentPage() + 1, m_document->pages() );
+ if ( pageDialog.exec() == QDialog::Accepted )
+ m_document->setViewportPage( pageDialog.getPage() - 1 );
+}
+
+void Part::slotPreviousPage()
+{
+ if ( m_document->isOpened() && !(m_document->currentPage() < 1) )
+ m_document->setViewportPage( m_document->currentPage() - 1 );
+}
+
+void Part::slotNextPage()
+{
+ if ( m_document->isOpened() && m_document->currentPage() < (m_document->pages() - 1) )
+ m_document->setViewportPage( m_document->currentPage() + 1 );
+}
+
+void Part::slotGotoFirst()
+{
+ if ( m_document->isOpened() )
+ m_document->setViewportPage( 0 );
+}
+
+void Part::slotGotoLast()
+{
+ if ( m_document->isOpened() )
+ m_document->setViewportPage( m_document->pages() - 1 );
+}
+
+void Part::slotHistoryBack()
+{
+ m_document->setPrevViewport();
+}
+
+void Part::slotHistoryNext()
+{
+ m_document->setNextViewport();
+}
+
+void Part::slotFind()
+{
+ static bool savedCaseSensitive = false;
+ KFindDialog dlg( widget() );
+ dlg.setHasCursor( false );
+ if ( !m_searchHistory.empty() )
+ dlg.setFindHistory( m_searchHistory );
+#if KDE_IS_VERSION(3,3,90)
+ dlg.setSupportsBackwardsFind( false );
+ dlg.setSupportsWholeWordsFind( false );
+ dlg.setSupportsRegularExpressionFind( false );
+#endif
+ if ( savedCaseSensitive )
+ {
+ dlg.setOptions( dlg.options() | KFindDialog::CaseSensitive );
+ }
+ if ( dlg.exec() == QDialog::Accepted )
+ {
+ savedCaseSensitive = dlg.options() & KFindDialog::CaseSensitive;
+ m_searchHistory = dlg.findHistory();
+ m_searchStarted = true;
+ m_document->resetSearch( PART_SEARCH_ID );
+ m_document->searchText( PART_SEARCH_ID, dlg.pattern(), false, savedCaseSensitive,
+ KPDFDocument::NextMatch, true, qRgb( 255, 255, 64 ) );
+ }
+}
+
+void Part::slotFindNext()
+{
+ if (!m_document->continueLastSearch())
+ slotFind();
+}
+
+void Part::slotSaveFileAs()
+{
+ KURL saveURL = KFileDialog::getSaveURL( url().isLocalFile() ? url().url() : url().fileName(), QString::null, widget() );
+ if ( saveURL.isValid() && !saveURL.isEmpty() )
+ {
+ if (saveURL == url())
+ {
+ KMessageBox::information( widget(), i18n("You are trying to overwrite \"%1\" with itself. This is not allowed. Please save it in another location.").arg(saveURL.filename()) );
+ return;
+ }
+ if ( KIO::NetAccess::exists( saveURL, false, widget() ) )
+ {
+ if (KMessageBox::warningContinueCancel( widget(), i18n("A file named \"%1\" already exists. Are you sure you want to overwrite it?").arg(saveURL.filename()), QString::null, i18n("Overwrite")) != KMessageBox::Continue)
+ return;
+ }
+
+ if ( !KIO::NetAccess::file_copy( m_file, saveURL, -1, true ) )
+ KMessageBox::information( 0, i18n("File could not be saved in '%1'. Try to save it to another location.").arg( saveURL.prettyURL() ) );
+ }
+}
+
+void Part::slotPreferences()
+{
+ // an instance the dialog could be already created and could be cached,
+ // in which case you want to display the cached dialog
+ if ( PreferencesDialog::showDialog( "preferences" ) )
+ return;
+
+ // we didn't find an instance of this dialog, so lets create it
+ PreferencesDialog * dialog = new PreferencesDialog( m_pageView, KpdfSettings::self() );
+ // keep us informed when the user changes settings
+ connect( dialog, SIGNAL( settingsChanged() ), this, SLOT( slotNewConfig() ) );
+
+ dialog->show();
+}
+
+void Part::slotNewConfig()
+{
+ // Apply settings here. A good policy is to check wether the setting has
+ // changed before applying changes.
+
+ // Watch File
+ bool watchFile = KpdfSettings::watchFile();
+ if ( watchFile && m_watcher->isStopped() )
+ m_watcher->startScan();
+ if ( !watchFile && !m_watcher->isStopped() )
+ {
+ m_dirtyHandler->stop();
+ m_watcher->stopScan();
+ }
+
+ bool showSearch = KpdfSettings::showSearchBar();
+ if ( m_searchWidget->isShown() != showSearch )
+ m_searchWidget->setShown( showSearch );
+
+ // Main View (pageView)
+ QScrollView::ScrollBarMode scrollBarMode = KpdfSettings::showScrollBars() ?
+ QScrollView::AlwaysOn : QScrollView::AlwaysOff;
+ if ( m_pageView->hScrollBarMode() != scrollBarMode )
+ {
+ m_pageView->setHScrollBarMode( scrollBarMode );
+ m_pageView->setVScrollBarMode( scrollBarMode );
+ }
+
+ // update document settings
+ m_document->reparseConfig();
+
+ // update Main View and ThumbnailList contents
+ // TODO do this only when changing KpdfSettings::renderMode()
+ m_pageView->updateContents();
+ if ( KpdfSettings::showLeftPanel() && m_thumbnailList->isShown() )
+ m_thumbnailList->updateWidgets();
+}
+
+void Part::slotPrintPreview()
+{
+ if (m_document->pages() == 0) return;
+
+ double width, height;
+ int landscape, portrait;
+ KPrinter printer;
+ const KPDFPage *page;
+
+ printer.setMinMax(1, m_document->pages());
+ printer.setPreviewOnly( true );
+
+ // if some pages are landscape and others are not the most common win as kprinter does
+ // not accept a per page setting
+ landscape = 0;
+ portrait = 0;
+ for (uint i = 0; i < m_document->pages(); i++)
+ {
+ page = m_document->page(i);
+ width = page->width();
+ height = page->height();
+ if (page->rotation() == 90 || page->rotation() == 270) qSwap(width, height);
+ if (width > height) landscape++;
+ else portrait++;
+ }
+ if (landscape > portrait) printer.setOption("orientation-requested", "4");
+
+ doPrint(printer);
+}
+
+void Part::slotShowMenu(const KPDFPage *page, const QPoint &point)
+{
+ bool reallyShow = false;
+ if (!m_actionsSearched)
+ {
+ // the quest for options_show_menubar
+ KXMLGUIClient *client;
+ KActionCollection *ac;
+ KActionPtrList::const_iterator it, end, begin;
+ KActionPtrList actions;
+
+ if (factory())
+ {
+ QPtrList<KXMLGUIClient> clients(factory()->clients());
+ QPtrListIterator<KXMLGUIClient> clientsIt( clients );
+ for( ; (!m_showMenuBarAction || !m_showFullScreenAction) && clientsIt.current(); ++clientsIt)
+ {
+ client = clientsIt.current();
+ ac = client->actionCollection();
+ actions = ac->actions();
+ end = actions.end();
+ begin = actions.begin();
+ for ( it = begin; it != end; ++it )
+ {
+ if (QString((*it)->name()) == "options_show_menubar") m_showMenuBarAction = (KToggleAction*)(*it);
+ if (QString((*it)->name()) == "fullscreen") m_showFullScreenAction = (KToggleAction*)(*it);
+ }
+ }
+ }
+ m_actionsSearched = true;
+ }
+
+
+ KPopupMenu *popup = new KPopupMenu( widget(), "rmb popup" );
+ if (page)
+ {
+ popup->insertTitle( i18n( "Page %1" ).arg( page->number() + 1 ) );
+ if ( page->hasBookmark() )
+ popup->insertItem( SmallIcon("bookmark"), i18n("Remove Bookmark"), 1 );
+ else
+ popup->insertItem( SmallIcon("bookmark_add"), i18n("Add Bookmark"), 1 );
+ if ( m_pageView->canFitPageWidth() )
+ popup->insertItem( SmallIcon("viewmagfit"), i18n("Fit Width"), 2 );
+ //popup->insertItem( SmallIcon("pencil"), i18n("Edit"), 3 );
+ //popup->setItemEnabled( 3, false );
+ reallyShow = true;
+ }
+/*
+ //Albert says: I have not ported this as i don't see it does anything
+ if ( d->mouseOnRect ) // and rect->objectType() == ObjectRect::Image ...
+ {
+ m_popup->insertItem( SmallIcon("filesave"), i18n("Save Image..."), 4 );
+ m_popup->setItemEnabled( 4, false );
+}*/
+
+ if ((m_showMenuBarAction && !m_showMenuBarAction->isChecked()) || (m_showFullScreenAction && m_showFullScreenAction->isChecked()))
+ {
+ popup->insertTitle( i18n( "Tools" ) );
+ if (m_showMenuBarAction && !m_showMenuBarAction->isChecked()) m_showMenuBarAction->plug(popup);
+ if (m_showFullScreenAction && m_showFullScreenAction->isChecked()) m_showFullScreenAction->plug(popup);
+ reallyShow = true;
+
+ }
+
+ if (reallyShow)
+ {
+ switch ( popup->exec(point) )
+ {
+ case 1:
+ m_document->toggleBookmark( page->number() );
+ break;
+ case 2:
+ m_pageView->fitPageWidth( page->number() );
+ break;
+ // case 3: // switch to edit mode
+ // break;
+ }
+ }
+ delete popup;
+}
+
+void Part::slotShowProperties()
+{
+ PropertiesDialog *d = new PropertiesDialog(widget(), m_document);
+ d->exec();
+ delete d;
+}
+
+void Part::slotShowPresentation()
+{
+ if ( !m_presentationWidget )
+ {
+ m_presentationWidget = new PresentationWidget( widget(), m_document );
+ m_presentationWidget->setupActions( actionCollection() );
+ }
+}
+
+void Part::slotHidePresentation()
+{
+ if ( m_presentationWidget )
+ delete (PresentationWidget*) m_presentationWidget;
+}
+
+void Part::slotTogglePresentation()
+{
+ if ( m_document->isOpened() )
+ {
+ if ( !m_presentationWidget )
+ {
+ m_presentationWidget = new PresentationWidget( widget(), m_document );
+ m_presentationWidget->setupActions( actionCollection() );
+ }
+ else delete (PresentationWidget*) m_presentationWidget;
+ }
+}
+
+void Part::slotPrint()
+{
+ if (m_document->pages() == 0) return;
+
+ double width, height;
+ int landscape, portrait;
+ KPrinter printer;
+ const KPDFPage *page;
+
+ printer.setPageSelection(KPrinter::ApplicationSide);
+ printer.setMinMax(1, m_document->pages());
+ printer.setCurrentPage(m_document->currentPage()+1);
+
+ // if some pages are landscape and others are not the most common win as kprinter does
+ // not accept a per page setting
+ landscape = 0;
+ portrait = 0;
+ for (uint i = 0; i < m_document->pages(); i++)
+ {
+ page = m_document->page(i);
+ width = page->width();
+ height = page->height();
+ if (page->rotation() == 90 || page->rotation() == 270) qSwap(width, height);
+ if (width > height) landscape++;
+ else portrait++;
+ }
+ if (landscape > portrait) printer.setOrientation(KPrinter::Landscape);
+
+ KPrinter::addDialogPage(new PDFOptionsPage());
+ if (printer.setup(widget())) doPrint( printer );
+}
+
+void Part::doPrint(KPrinter &printer)
+{
+ if (!m_document->isAllowed(KPDFDocument::AllowPrint))
+ {
+ KMessageBox::error(widget(), i18n("Printing this document is not allowed."));
+ return;
+ }
+
+ if (!m_document->print(printer))
+ {
+ KMessageBox::error(widget(), i18n("Could not print the document. Please report to bugs.kde.org"));
+ }
+}
+
+void Part::restoreDocument(KConfig* config)
+{
+ KURL url ( config->readPathEntry( "URL" ) );
+ if ( url.isValid() )
+ {
+ QString viewport = config->readEntry( "Viewport" );
+ if (!viewport.isEmpty()) m_document->setNextDocumentViewport( DocumentViewport( viewport ) );
+ openURL( url );
+ }
+}
+
+void Part::saveDocumentRestoreInfo(KConfig* config)
+{
+ config->writePathEntry( "URL", url().url() );
+ config->writeEntry( "Viewport", m_document->viewport().toString() );
+}
+
+/*
+* BrowserExtension class
+*/
+BrowserExtension::BrowserExtension(Part* parent)
+ : KParts::BrowserExtension( parent, "KPDF::BrowserExtension" )
+{
+ emit enableAction("print", true);
+ setURLDropHandlingEnabled(true);
+}
+
+void BrowserExtension::print()
+{
+ static_cast<Part*>(parent())->slotPrint();
+}
+
+#include "part.moc"