📄 document.cpp.svn-base
字号:
/*************************************************************************** * Copyright (C) 2004-2005 by Enrico Ros <eros.kde@email.it> * * Copyright (C) 2004-2005 by Albert Astals Cid <tsdgeos@terra.es> * * * * 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/system includes#include <qapplication.h>#include <qdir.h>#include <qfile.h>#include <qfileinfo.h>#include <qimage.h>#include <QtAlgorithms>#include <qtextstream.h>#include <qvector.h>#include <qtimer.h>#include <qmap.h>#include <kconfigdialog.h>#include <kdebug.h>#include <klocale.h>#include <kfinddialog.h>#include <kmessagebox.h>#include <kmimetypetrader.h>#include <ktoolinvocation.h>#include <krun.h>#include <kstandarddirs.h>#include <klibloader.h>#include <qcombobox.h>#include <qlabel.h>// local includes#include "document.h"#include "generator.h"#include "observer.h"#include "page.h"#include "link.h"#include "chooseenginedialog.h"#include "settings.h"// structures used internally by KPDFDocument for local variables storageclass AllocatedPixmap;class RunningSearch;class KPDFDocumentPrivate{ public: // find descriptors, mapped by ID (we handle multiple searches) QMap< int, RunningSearch * > searches; int m_lastSearchID; // needed because for remote documents docFileName is a local file and // we want the remote url when the document refers to relativeNames KUrl url; // cached stuff QString docFileName; QString xmlFileName; // list of the mimetypes 'generator_kimgio' can understand QStringList kimgioMimes; // viewport stuff QLinkedList< DocumentViewport > viewportHistory; QLinkedList< DocumentViewport >::iterator viewportIterator; DocumentViewport nextDocumentViewport; // see KPDFLink::Goto for an explanation // observers / requests / allocator stuff QMap< int, DocumentObserver * > observers; QLinkedList< PixmapRequest * > pixmapRequestsStack; QLinkedList< AllocatedPixmap * > allocatedPixmapsFifo; int allocatedPixmapsTotalMemory; bool warnedOutOfMemory; // the rotation applied to the document, 0,1,2,3 * 90 degrees int rotation; // timers (memory checking / info saver) QTimer * memCheckTimer; QTimer * saveBookmarksTimer;};struct AllocatedPixmap{ // owner of the page int id; int page; int memory; // public constructor: initialize data AllocatedPixmap( int i, int p, int m ) : id( i ), page( p ), memory( m ) {};};struct RunningSearch{ // store search properties int continueOnPage; RegularAreaRect continueOnMatch; QLinkedList< int > highlightedPages; // fields related to previous searches (used for 'continueSearch') QString cachedString; KPDFDocument::SearchType cachedType; bool cachedCaseSensitive; bool cachedViewportMove; bool cachedNoDialogs; QColor cachedColor;};#define foreachObserver( cmd ) {\ QMap< int, DocumentObserver * >::iterator it=d->observers.begin(), end=d->observers.end();\ for ( ; it != end ; ++ it ) { (*it)-> cmd ; } }/** KPDFDocument **/KPDFDocument::KPDFDocument( QHash<QString, Generator*> * genList ) : m_loadedGenerators ( genList ), generator( 0 ), d( new KPDFDocumentPrivate ){ d->allocatedPixmapsTotalMemory = 0; d->memCheckTimer = 0; d->saveBookmarksTimer = 0; d->m_lastSearchID = -1; d->warnedOutOfMemory = false; d->rotation = 0; m_usingCachedGenerator = false;}KPDFDocument::~KPDFDocument(){ // delete generator, pages, and related stuff closeDocument(); // delete the private structure delete d;}static bool kserviceMoreThan( const KService::Ptr &s1, const KService::Ptr &s2 ){ return s1->property( "X-KDE-Priority" ).toInt() > s2->property( "X-KDE-Priority" ).toInt();}bool KPDFDocument::openDocument( const QString & docFile, const KUrl& url, const KMimeType::Ptr &mime ){ // docFile is always local so we can use QFile on it QFile fileReadTest( docFile ); if ( !fileReadTest.open( QIODevice::ReadOnly ) ) { d->docFileName.clear(); return false; } // determine the related "xml document-info" filename d->url = url; d->docFileName = docFile; QString fn = docFile.contains('/') ? docFile.section('/', -1, -1) : docFile; fn = "kpdf/" + QString::number(fileReadTest.size()) + "." + fn + ".xml"; fileReadTest.close(); d->xmlFileName = KStandardDirs::locateLocal( "data", fn ); if (mime.count()<=0) return false; // 0. load Generator // request only valid non-disabled plugins suitable for the mimetype QString constraint("([X-KDE-Priority] > 0) and (exist Library)") ; KService::List offers = KMimeTypeTrader::self()->query(mime->name(),"okular/Generator",constraint); if (offers.isEmpty()) { kWarning() << "No plugin for mimetype '" << mime->name() << "'." << endl; return false; } int hRank=0; // order the offers: the offers with an higher priority come before qStableSort( offers.begin(), offers.end(), kserviceMoreThan ); // best ranked offer search if (offers.count() > 1 && KpdfSettings::chooseGenerators() ) { QStringList list; int count=offers.count(); for (int i=0;i<count;++i) { list << offers.at(i)->name(); } ChooseEngineDialog * choose = new ChooseEngineDialog (list, mime, 0); int retval=choose->exec(); int index=choose->selectedGenerator(); delete choose; switch( retval ) { case QDialog::Accepted: hRank=index; break; case QDialog::Rejected: return false; break; } } QString propName=offers[hRank]->property("Name").toString(); m_usingCachedGenerator=false; generator=m_loadedGenerators->take(propName); if (!generator) { KLibLoader *loader = KLibLoader::self(); if (!loader) { kWarning() << "Could not start library loader: '" << loader->lastErrorMessage() << "'." << endl; return false; } KLibrary *lib = loader->globalLibrary( QFile::encodeName( offers[hRank]->library() ) ); if (!lib) { kWarning() << "Could not load '" << offers[hRank]->library() << "' library." << endl; return false; } Generator* (*create_plugin)(KPDFDocument* doc) = ( Generator* (*)(KPDFDocument* doc) ) lib->symbol( "create_plugin" ); generator=create_plugin(this); if ( !generator ) { kWarning() << "Sth broke." << endl; return false; } if ( offers.at(hRank)->property( "X-KDE-okularHasInternalSettings" ).toBool() ) { m_loadedGenerators->insert(propName,generator); m_usingCachedGenerator=true; } // end } else { generator -> setDocument( this ); m_usingCachedGenerator=true; } // connect error reporting signals connect( generator, SIGNAL( error( const QString&, int ) ), this, SIGNAL( error( const QString&, int ) ) ); connect( generator, SIGNAL( warning( const QString&, int ) ), this, SIGNAL( warning( const QString&, int ) ) ); connect( generator, SIGNAL( notice( const QString&, int ) ), this, SIGNAL( notice( const QString&, int ) ) ); // 1. load Document (and set busy cursor while loading) QApplication::setOverrideCursor( Qt::WaitCursor ); bool openOk = generator->loadDocument( docFile, pages_vector ); QApplication::restoreOverrideCursor(); if ( !openOk || pages_vector.size() <= 0 ) { if (!m_usingCachedGenerator) { delete generator; } generator = 0; return openOk; } // 2. load Additional Data (our bookmarks and metadata) about the document loadDocumentInfo(); // 3. setup observers inernal lists and data foreachObserver( notifySetup( pages_vector, true ) ); // 4. set initial page (restoring the page saved in xml if loaded) DocumentViewport loadedViewport = (*d->viewportIterator); if ( loadedViewport.pageNumber != -1 ) { (*d->viewportIterator) = DocumentViewport(); if ( loadedViewport.pageNumber >= (int)pages_vector.size() ) loadedViewport.pageNumber = pages_vector.size() - 1; } else loadedViewport.pageNumber = 0; setViewport( loadedViewport ); // start bookmark saver timer if ( !d->saveBookmarksTimer ) { d->saveBookmarksTimer = new QTimer( this ); connect( d->saveBookmarksTimer, SIGNAL( timeout() ), this, SLOT( saveDocumentInfo() ) ); } d->saveBookmarksTimer->start( 5 * 60 * 1000 ); // start memory check timer if ( !d->memCheckTimer ) { d->memCheckTimer = new QTimer( this ); connect( d->memCheckTimer, SIGNAL( timeout() ), this, SLOT( slotTimedMemoryCheck() ) ); } d->memCheckTimer->start( 2000 ); if (d->nextDocumentViewport.pageNumber != -1) { setViewport(d->nextDocumentViewport); d->nextDocumentViewport = DocumentViewport(); } return true;}QString KPDFDocument::getXMLFile(){ if (generator) return generator->getXMLFile(); return QString::null;}void KPDFDocument::setupGUI(KActionCollection* ac, QToolBox* tBox ){ if (generator) generator->setupGUI(ac,tBox);}void KPDFDocument::closeDocument(){ // close the current document and save document info if a document is still opened if ( generator && pages_vector.size() > 0 ) { generator->closeDocument(); saveDocumentInfo(); } // stop timers if ( d->memCheckTimer ) d->memCheckTimer->stop(); if ( d->saveBookmarksTimer ) d->saveBookmarksTimer->stop(); if (generator) generator->freeGUI(); if (!m_usingCachedGenerator) { // delete contents generator delete generator; } generator = 0; d->url = KUrl(); // remove requests left in queue QLinkedList< PixmapRequest * >::iterator sIt = d->pixmapRequestsStack.begin(); QLinkedList< PixmapRequest * >::iterator sEnd = d->pixmapRequestsStack.end(); for ( ; sIt != sEnd; ++sIt ) delete *sIt; d->pixmapRequestsStack.clear(); // send an empty list to observers (to free their data) foreachObserver( notifySetup( QVector< KPDFPage * >(), true ) ); // delete pages and clear 'pages_vector' container QVector< KPDFPage * >::iterator pIt = pages_vector.begin(); QVector< KPDFPage * >::iterator pEnd = pages_vector.end(); for ( ; pIt != pEnd; ++pIt ) delete *pIt; pages_vector.clear(); // clear 'memory allocation' descriptors QLinkedList< AllocatedPixmap * >::iterator aIt = d->allocatedPixmapsFifo.begin(); QLinkedList< AllocatedPixmap * >::iterator aEnd = d->allocatedPixmapsFifo.end(); for ( ; aIt != aEnd; ++aIt ) delete *aIt; d->allocatedPixmapsFifo.clear(); // clear 'running searches' descriptors QMap< int, RunningSearch * >::iterator rIt = d->searches.begin(); QMap< int, RunningSearch * >::iterator rEnd = d->searches.end(); for ( ; rIt != rEnd; ++rIt ) delete *rIt; d->searches.clear(); // clear the visible areas and notify the observers QVector< VisiblePageRect * >::iterator vIt = page_rects.begin(); QVector< VisiblePageRect * >::iterator vEnd = page_rects.end(); for ( ; vIt != vEnd; ++vIt ) delete *vIt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -