/*************************************************************************** * Copyright (C) 2002 by Wilco Greven * * Copyright (C) 2002 by Chris Cheney * * Copyright (C) 2002 by Malcolm Hunter * * Copyright (C) 2003-2004 by Christophe Devriese * * * * Copyright (C) 2003 by Daniel Molkentin * * Copyright (C) 2003 by Andy Goossens * * Copyright (C) 2003 by Dirk Mueller * * Copyright (C) 2003 by Laurent Montel * * Copyright (C) 2004 by Dominique Devriese * * Copyright (C) 2004 by Christoph Cullmann * * Copyright (C) 2004 by Henrique Pinto * * Copyright (C) 2004 by Waldo Bastian * * Copyright (C) 2004-2006 by Albert Astals Cid * * Copyright (C) 2004 by Antti Markus * * * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 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" ) ); TQVBoxLayout *layout = new TQVBoxLayout(this); m_forceRaster = new TQCheckBox(i18n("Force rasterization"), this); TQToolTip::add(m_forceRaster, i18n("Rasterize into an image before printing")); TQWhatsThis::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( TQMap& opts, bool incldef = false ) { Q_UNUSED(incldef); opts[ "kde-kpdf-forceRaster" ] = TQString::number( m_forceRaster->isChecked() ); } void setOptions( const TQMap& opts ) { m_forceRaster->setChecked( opts[ "kde-kpdf-forceRaster" ].toInt() ); } private: TQCheckBox *m_forceRaster; }; // definition of searchID for this class #define PART_SEARCH_ID 1 typedef KParts::GenericFactory KPDFPartFactory; K_EXPORT_COMPONENT_FACTORY(libkpdfpart, KPDFPartFactory) using namespace KPDF; unsigned int Part::m_count = 0; Part::Part(TQWidget *parentWidget, const char *widgetName, TQObject *parent, const char *name, const TQStringList & /*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, TQT_SIGNAL(started(TDEIO::Job *)), this, TQT_SLOT(setMimeTypes(TDEIO::Job *))); // connect the completed signal so we can put the window caption when loading remote files connect(this, TQT_SIGNAL(completed()), this, TQT_SLOT(emitWindowCaption())); connect(this, TQT_SIGNAL(canceled(const TQString &)), this, TQT_SLOT(emitWindowCaption())); // load catalog for translation TDEGlobal::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, TQT_SIGNAL( linkFind() ), this, TQT_SLOT( slotFind() ) ); connect( m_document, TQT_SIGNAL( linkGoToPage() ), this, TQT_SLOT( slotGoToPage() ) ); connect( m_document, TQT_SIGNAL( linkPresentation() ), this, TQT_SLOT( slotShowPresentation() ) ); connect( m_document, TQT_SIGNAL( linkEndPresentation() ), this, TQT_SLOT( slotHidePresentation() ) ); connect( m_document, TQT_SIGNAL( openURL(const KURL &) ), this, TQT_SLOT( openURLFromDocument(const KURL &) ) ); connect( m_document, TQT_SIGNAL( close() ), this, TQT_SLOT( close() ) ); if (parent && parent->metaObject()->slotNames(true).contains("slotQuit()")) connect( m_document, TQT_SIGNAL( quit() ), parent, TQT_SLOT( slotQuit() ) ); else connect( m_document, TQT_SIGNAL( quit() ), this, TQT_SLOT( cannotQuit() ) ); // widgets: ^searchbar (toolbar containing label and SearchWidget) // m_searchToolBar = new TDEToolBar( parentWidget, "searchBar" ); // m_searchToolBar->boxLayout()->setSpacing( KDialog::spacingHint() ); // TQLabel * sLabel = new TQLabel( i18n( "&Search:" ), m_searchToolBar, "tde toolbar widget" ); // m_searchWidget = new SearchWidget( m_searchToolBar, m_document ); // sLabel->setBuddy( m_searchWidget ); // m_searchToolBar->setStretchableWidget( m_searchWidget ); // widgets: [] splitter [] m_splitter = new TQSplitter( parentWidget, widgetName ); m_splitter->setOpaqueResize( true ); setWidget( m_splitter ); m_showLeftPanel = new TDEToggleAction( i18n( "Show &Navigation Panel"), "show_side_panel", 0, this, TQT_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 TQWidget( m_splitter ); m_leftPanel->setMinimumWidth( 90 ); m_leftPanel->setMaximumWidth( 300 ); TQVBoxLayout * leftPanelLayout = new TQVBoxLayout( m_leftPanel ); // widgets: [left toolbox/..] | [] m_toolBox = new TQToolBox( m_leftPanel ); leftPanelLayout->addWidget( m_toolBox ); int index; // [left toolbox: Table of Contents] | [] // dummy wrapper with layout to enable horizontal scroll bars (bug: 147233) TQWidget *tocWrapper = new TQWidget(m_toolBox); TQVBoxLayout *tocWrapperLayout = new TQVBoxLayout(tocWrapper); m_tocFrame = new TOC( tocWrapper, m_document ); tocWrapperLayout->add(m_tocFrame); connect(m_tocFrame, TQT_SIGNAL(hasTOC(bool)), this, TQT_SLOT(enableTOC(bool))); index = m_toolBox->addItem( tocWrapper, TQIconSet(SmallIcon("format-text-direction-ltr")), i18n("Contents") ); m_toolBox->setItemToolTip(index, i18n("Contents")); enableTOC( false ); // [left toolbox: Thumbnails and Bookmarks] | [] TQVBox * 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, TQT_SIGNAL( urlDropped( const KURL& ) ), TQT_SLOT( openURLFromDocument( const KURL & )) ); connect( m_thumbnailList, TQT_SIGNAL( rightClick(const KPDFPage *, const TQPoint &) ), this, TQT_SLOT( slotShowMenu(const KPDFPage *, const TQPoint &) ) ); // 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, TQIconSet(SmallIcon("thumbnail")), i18n("Thumbnails") ); m_toolBox->setItemToolTip(index, i18n("Thumbnails")); m_toolBox->setCurrentItem( thumbsBox ); slotShowLeftPanel(); /* // [left toolbox: Annotations] | [] TQFrame * editFrame = new TQFrame( m_toolBox ); int iIdx = m_toolBox->addItem( editFrame, TQIconSet(SmallIcon("pencil")), i18n("Annotations") ); m_toolBox->setItemEnabled( iIdx, false );*/ // widgets: [../miniBarContainer] | [] TQWidget * miniBarContainer = new TQWidget( m_leftPanel ); leftPanelLayout->addWidget( miniBarContainer ); TQVBoxLayout * miniBarLayout = new TQVBoxLayout( miniBarContainer ); // widgets: [../[spacer/..]] | [] TQWidget * miniSpacer = new TQWidget( 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, TQT_SIGNAL( urlDropped( const KURL& ) ), TQT_SLOT( openURLFromDocument( const KURL & ))); connect( m_pageView, TQT_SIGNAL( rightClick(const KPDFPage *, const TQPoint &) ), this, TQT_SLOT( slotShowMenu(const KPDFPage *, const TQPoint &) ) ); // 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 TDEActionCollection * ac = actionCollection(); // Page Traversal actions m_gotoPage = KStdAction::gotoPage( this, TQT_SLOT( slotGoToPage() ), ac, "goto_page" ); m_gotoPage->setShortcut( "CTRL+G" ); // dirty way to activate gotopage when pressing miniBar's button connect( m_miniBar, TQT_SIGNAL( gotoPage() ), m_gotoPage, TQT_SLOT( activate() ) ); m_prevPage = KStdAction::prior(this, TQT_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, TQT_SIGNAL( prevPage() ), m_prevPage, TQT_SLOT( activate() ) ); m_nextPage = KStdAction::next(this, TQT_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, TQT_SIGNAL( nextPage() ), m_nextPage, TQT_SLOT( activate() ) ); m_firstPage = KStdAction::firstPage( this, TQT_SLOT( slotGotoFirst() ), ac, "first_page" ); m_firstPage->setWhatsThis( i18n( "Moves to the first page of the document" ) ); m_lastPage = KStdAction::lastPage( this, TQT_SLOT( slotGotoLast() ), ac, "last_page" ); m_lastPage->setWhatsThis( i18n( "Moves to the last page of the document" ) ); m_historyBack = KStdAction::back( this, TQT_SLOT( slotHistoryBack() ), ac, "history_back" ); m_historyBack->setWhatsThis( i18n( "Go to the place you were before" ) ); m_historyNext = KStdAction::forward( this, TQT_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, TQT_SLOT( slotFind() ), ac, "find" ); m_find->setEnabled( false ); m_findNext = KStdAction::findNext( this, TQT_SLOT( slotFindNext() ), ac, "find_next" ); m_findNext->setEnabled( false ); m_saveAs = KStdAction::saveAs( this, TQT_SLOT( slotSaveFileAs() ), ac, "save" ); m_saveAs->setEnabled( false ); TDEAction * prefs = KStdAction::preferences( this, TQT_SLOT( slotPreferences() ), ac, "preferences" ); prefs->setText( i18n( "Configure KPDF..." ) ); m_printPreview = KStdAction::printPreview( this, TQT_SLOT( slotPrintPreview() ), ac ); m_printPreview->setEnabled( false ); m_showProperties = new TDEAction(i18n("&Properties"), "application-vnd.tde.info", 0, this, TQT_SLOT(slotShowProperties()), ac, "properties"); m_showProperties->setEnabled( false ); m_showPresentation = new TDEAction( i18n("P&resentation"), "application-x-kpresenter", "Ctrl+Shift+P", this, TQT_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) TQValueList 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 TQt4::TQSplitter's sliderMoved()) m_pageView->installEventFilter( this ); m_watcher = new KDirWatch( this ); connect( m_watcher, TQT_SIGNAL( dirty( const TQString& ) ), this, TQT_SLOT( slotFileDirty( const TQString& ) ) ); m_dirtyHandler = new TQTimer( this ); connect( m_dirtyHandler, TQT_SIGNAL( timeout() ),this, TQT_SLOT( slotDoFileDirty() ) ); m_saveSplitterSizeTimer = new TQTimer( this ); connect( m_saveSplitterSizeTimer, TQT_SIGNAL( timeout() ),this, TQT_SLOT( saveSplitterSize() ) ); slotNewConfig(); // [SPEECH] check for KTTSD presence and usability TDETrader::OfferList offers = TDETrader::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 TDEAboutData* 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) TDEAboutData* aboutData = new TDEAboutData("kpdfpart", I18N_NOOP("KPDF::Part"), "0.1"); aboutData->addAuthor("Wilco Greven", 0, "greven@kde.org"); 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" ) ) { TQString app = TDEStandardDirs::findExe( "ps2pdf" ); if ( !app.isNull() ) { if ( TQFile::exists(m_file) ) { KTempFile tf( TQString(), ".pdf" ); if ( tf.status() == 0 ) { tf.close(); m_temporaryLocalFile = tf.name(); TDEProcess *p = new TDEProcess; *p << app; *p << m_file << m_temporaryLocalFile; m_pageView->showText(i18n("Converting from ps to pdf..."), 0); connect(p, TQT_SIGNAL(processExited(TDEProcess *)), this, TQT_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 = TQString(); 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."), TQString(), "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 = TQString(); // 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(TDEIO::Job *job) { if (job) { job->addMetaData("accept", "application/pdf, */*;q=0.5"); connect(job, TQT_SIGNAL(mimetype(TDEIO::Job*,const TQString&)), this, TQT_SLOT(readMimeType(TDEIO::Job*,const TQString&))); } } void Part::readMimeType(TDEIO::Job *, const TQString &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()) { TQFile::remove( m_temporaryLocalFile ); m_temporaryLocalFile = TQString(); } 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( TQObject * watched, TQEvent * e ) { // if pageView has been resized, save splitter sizes if ( TQT_BASE_OBJECT(watched) == TQT_BASE_OBJECT(m_pageView) && e->type() == TQEvent::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 TQString& 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."), TQString(), "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() { TQString 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."), TQString(), "warnNoQuitIfNotInKPDF"); } void Part::saveSplitterSize() { KpdfSettings::setSplitterSizes( m_splitter->sizes() ); KpdfSettings::writeConfig(); } //BEGIN go to page dialog class KPDFGotoPageDialog : public KDialogBase { public: KPDFGotoPageDialog(TQWidget *p, int current, int max) : KDialogBase(p, 0L, true, i18n("Go to Page"), Ok | Cancel, Ok) { TQWidget *w = new TQWidget(this); setMainWidget(w); TQVBoxLayout *topLayout = new TQVBoxLayout( w, 0, spacingHint() ); e1 = new KIntNumInput(current, w); e1->setRange(1, max); e1->setEditFocus(true); TQLabel *label = new TQLabel( 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() == TQDialog::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() == TQDialog::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, tqRgb( 255, 255, 64 ) ); } } void Part::slotFindNext() { if (!m_document->continueLastSearch()) slotFind(); } void Part::slotSaveFileAs() { KURL saveURL = KFileDialog::getSaveURL( url().isLocalFile() ? url().url() : url().fileName(), TQString(), 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 ( TDEIO::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()), TQString(), i18n("Overwrite")) != KMessageBox::Continue) return; } if ( !TDEIO::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, TQT_SIGNAL( settingsChanged() ), this, TQT_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) TQScrollView::ScrollBarMode scrollBarMode = KpdfSettings::showScrollBars() ? TQScrollView::AlwaysOn : TQScrollView::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) tqSwap(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 TQPoint &point) { bool reallyShow = false; if (!m_actionsSearched) { // the quest for options_show_menubar KXMLGUIClient *client; TDEActionCollection *ac; TDEActionPtrList::const_iterator it, end, begin; TDEActionPtrList actions; if (factory()) { TQPtrList clients(factory()->clients()); TQPtrListIterator 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 (TQString((*it)->name()) == "options_show_menubar") m_showMenuBarAction = (TDEToggleAction*)(*it); if (TQString((*it)->name()) == "fullscreen") m_showFullScreenAction = (TDEToggleAction*)(*it); } } } m_actionsSearched = true; } TDEPopupMenu *popup = new TDEPopupMenu( 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("zoom-fit-best"), 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("document-save"), 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) tqSwap(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.trinitydesktop.org")); } } void Part::restoreDocument(TDEConfig* config) { KURL url ( config->readPathEntry( "URL" ) ); if ( url.isValid() ) { TQString viewport = config->readEntry( "Viewport" ); if (!viewport.isEmpty()) m_document->setNextDocumentViewport( DocumentViewport( viewport ) ); openURL( url ); } } void Part::saveDocumentRestoreInfo(TDEConfig* config) { if ( url().isValid() ) { 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(parent())->slotPrint(); } #include "part.moc"