2004-09-08 12:41:14 +00:00
/***************************************************************************
2005-02-20 16:04:40 +00:00
* Copyright ( C ) 2004 - 2005 by Enrico Ros < eros . kde @ email . it > *
2005-01-15 01:08:35 +00:00
* Copyright ( C ) 2004 - 2005 by Albert Astals Cid < tsdgeos @ terra . es > *
2004-09-08 12:41:14 +00:00
* *
* 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 . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-04-19 18:30:20 +00:00
# include "document.h"
2004-10-06 00:05:49 +00:00
// qt/kde/system includes
2006-09-21 08:45:36 +00:00
# include <QtCore/QtAlgorithms>
# include <QtCore/QFile>
# include <QtCore/QFileInfo>
2007-01-28 15:46:10 +00:00
# include <QtCore/QHash>
2006-09-21 08:45:36 +00:00
# include <QtCore/QMap>
2006-11-17 22:15:15 +00:00
# include <QtCore/QProcess>
2006-09-21 08:45:36 +00:00
# include <QtCore/QTextStream>
# include <QtCore/QTimer>
# include <QtGui/QApplication>
2007-03-11 22:35:14 +00:00
# include <kaboutdata.h>
2007-01-29 14:28:58 +00:00
# include <kauthorized.h>
2007-03-11 22:35:14 +00:00
# include <kcomponentdata.h>
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
# include <kconfigdialog.h>
2004-09-12 23:19:18 +00:00
# include <kdebug.h>
2006-09-21 08:45:36 +00:00
# include <klibloader.h>
# include <klocale.h>
2004-09-16 21:04:49 +00:00
# include <kmessagebox.h>
2006-05-22 14:02:24 +00:00
# include <kmimetypetrader.h>
2004-12-10 16:04:45 +00:00
# include <krun.h>
2007-01-28 15:46:10 +00:00
# include <kservicetypetrader.h>
2005-01-03 00:28:46 +00:00
# include <kstandarddirs.h>
2007-01-12 22:49:14 +00:00
# include <ktemporaryfile.h>
2006-09-21 08:45:36 +00:00
# include <ktoolinvocation.h>
2004-09-08 12:41:14 +00:00
// local includes
2007-04-20 11:26:05 +00:00
# include "action.h"
2007-02-05 00:49:40 +00:00
# include "audioplayer.h"
2006-12-27 16:04:49 +00:00
# include "bookmarkmanager.h"
2006-09-21 08:45:36 +00:00
# include "chooseenginedialog.h"
2005-07-15 18:20:57 +00:00
# include "generator.h"
2007-01-03 14:30:48 +00:00
# include "interfaces/configinterface.h"
# include "interfaces/guiinterface.h"
# include "interfaces/printinterface.h"
2005-01-02 14:55:14 +00:00
# include "observer.h"
2004-09-08 12:41:14 +00:00
# include "page.h"
2007-04-14 19:58:17 +00:00
# include "page_p.h"
2007-03-24 10:47:22 +00:00
# include "pagecontroller_p.h"
2007-01-02 17:45:32 +00:00
# include "settings.h"
# include "sourcereference.h"
2004-09-09 13:25:40 +00:00
2007-01-29 14:28:58 +00:00
# include <config-okular.h>
2006-09-21 08:45:36 +00:00
using namespace Okular ;
2007-03-10 11:52:12 +00:00
static int OkularDebug = 4650 ;
2005-01-20 17:33:05 +00:00
struct AllocatedPixmap
2004-12-21 12:38:52 +00:00
{
2005-01-20 17:33:05 +00:00
// owner of the page
int id ;
int page ;
int memory ;
2004-12-21 12:38:52 +00:00
// public constructor: initialize data
2005-01-20 17:33:05 +00:00
AllocatedPixmap ( int i , int p , int m ) : id ( i ) , page ( p ) , memory ( m ) { } ;
2004-09-08 12:41:14 +00:00
} ;
2005-02-01 18:26:56 +00:00
struct RunningSearch
{
2005-02-02 18:18:26 +00:00
// store search properties
int continueOnPage ;
2005-07-15 18:20:57 +00:00
RegularAreaRect continueOnMatch ;
2006-03-20 22:51:56 +00:00
QLinkedList < int > highlightedPages ;
2005-02-02 18:18:26 +00:00
// fields related to previous searches (used for 'continueSearch')
QString cachedString ;
2006-09-21 08:45:36 +00:00
Document : : SearchType cachedType ;
2006-11-23 16:54:28 +00:00
Qt : : CaseSensitivity cachedCaseSensitivity ;
2005-02-02 18:18:26 +00:00
bool cachedViewportMove ;
bool cachedNoDialogs ;
QColor cachedColor ;
2005-02-01 18:26:56 +00:00
} ;
2007-01-28 15:46:10 +00:00
struct GeneratorInfo
{
GeneratorInfo ( )
2007-01-30 12:43:43 +00:00
: generator ( 0 ) , library ( 0 )
2007-01-28 15:46:10 +00:00
{ }
Generator * generator ;
2007-01-30 12:43:43 +00:00
KLibrary * library ;
2007-03-11 22:35:14 +00:00
QString appName ;
2007-01-28 15:46:10 +00:00
} ;
2004-09-08 12:41:14 +00:00
# define foreachObserver( cmd ) {\
2007-01-02 19:05:49 +00:00
QMap < int , DocumentObserver * > : : const_iterator it = d - > m_observers . begin ( ) , end = d - > m_observers . end ( ) ; \
2005-01-20 17:33:05 +00:00
for ( ; it ! = end ; + + it ) { ( * it ) - > cmd ; } }
2004-09-08 12:41:14 +00:00
2007-01-02 19:05:49 +00:00
/***** Document ******/
2005-01-26 10:42:07 +00:00
2007-04-14 19:44:07 +00:00
class Okular : : DocumentPrivate
2004-09-08 12:41:14 +00:00
{
2007-01-02 19:05:49 +00:00
public :
2007-04-14 19:44:07 +00:00
DocumentPrivate ( Document * parent )
2007-01-02 19:05:49 +00:00
: m_parent ( parent ) ,
m_lastSearchID ( - 1 ) ,
2007-01-12 22:49:14 +00:00
m_tempFile ( 0 ) ,
2007-01-02 19:05:49 +00:00
m_allocatedPixmapsTotalMemory ( 0 ) ,
m_warnedOutOfMemory ( false ) ,
2007-01-05 17:09:47 +00:00
m_rotation ( Rotation0 ) ,
2007-03-10 20:51:50 +00:00
m_exportCached ( false ) ,
2007-01-02 19:05:49 +00:00
m_bookmarkManager ( 0 ) ,
m_memCheckTimer ( 0 ) ,
m_saveBookmarksTimer ( 0 ) ,
m_generator ( 0 ) ,
2007-01-28 15:46:10 +00:00
m_generatorsLoaded ( false )
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
{
}
2007-01-02 19:05:49 +00:00
// private methods
QString pagesSizeString ( ) const ;
QString localizedSize ( const QSizeF & size ) const ;
void cleanupPixmapMemory ( int bytesOffset = 0 ) ;
int getTotalMemory ( ) ;
int getFreeMemory ( ) ;
void loadDocumentInfo ( ) ;
QString giveAbsolutePath ( const QString & fileName ) ;
bool openRelativeFile ( const QString & fileName ) ;
2007-01-28 15:46:10 +00:00
Generator * loadGeneratorLibrary ( const QString & name , const QString & libname ) ;
void loadAllGeneratorLibraries ( ) ;
2007-01-28 16:10:12 +00:00
void loadServiceList ( const KService : : List & offers ) ;
2007-02-03 23:09:40 +00:00
void unloadGenerator ( const GeneratorInfo & info ) ;
2007-03-10 20:51:50 +00:00
void cacheExportFormats ( ) ;
2007-01-02 19:05:49 +00:00
// private slots
void saveDocumentInfo ( ) const ;
void slotTimedMemoryCheck ( ) ;
void sendGeneratorRequest ( ) ;
void rotationFinished ( int page ) ;
// member variables
Document * m_parent ;
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
2007-01-02 19:05:49 +00:00
// find descriptors, mapped by ID (we handle multiple searches)
QMap < int , RunningSearch * > m_searches ;
int m_lastSearchID ;
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
2007-01-02 19:05:49 +00:00
// needed because for remote documents docFileName is a local file and
// we want the remote url when the document refers to relativeNames
KUrl m_url ;
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
2007-01-02 19:05:49 +00:00
// cached stuff
QString m_docFileName ;
QString m_xmlFileName ;
2007-01-12 22:49:14 +00:00
KTemporaryFile * m_tempFile ;
2006-10-22 11:25:08 +00:00
2007-01-02 19:05:49 +00:00
// viewport stuff
QLinkedList < DocumentViewport > m_viewportHistory ;
QLinkedList < DocumentViewport > : : iterator m_viewportIterator ;
DocumentViewport m_nextDocumentViewport ; // see Link::Goto for an explanation
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
2007-01-02 19:05:49 +00:00
// observers / requests / allocator stuff
QMap < int , DocumentObserver * > m_observers ;
QLinkedList < PixmapRequest * > m_pixmapRequestsStack ;
QLinkedList < AllocatedPixmap * > m_allocatedPixmapsFifo ;
int m_allocatedPixmapsTotalMemory ;
bool m_warnedOutOfMemory ;
2006-11-20 07:53:32 +00:00
2007-01-05 17:09:47 +00:00
// the rotation applied to the document
Rotation m_rotation ;
2006-11-20 07:53:32 +00:00
2007-01-05 23:12:06 +00:00
// the current size of the pages (if available), and the cache of the
// available page sizes
PageSize m_pageSize ;
PageSize : : List m_pageSizes ;
2007-03-10 20:51:50 +00:00
// cache of the export formats
bool m_exportCached ;
ExportFormat : : List m_exportFormats ;
ExportFormat m_exportToText ;
2007-01-02 19:05:49 +00:00
// our bookmark manager
BookmarkManager * m_bookmarkManager ;
// timers (memory checking / info saver)
QTimer * m_memCheckTimer ;
QTimer * m_saveBookmarksTimer ;
2007-01-28 15:46:10 +00:00
QHash < QString , GeneratorInfo > m_loadedGenerators ;
2007-01-02 19:05:49 +00:00
Generator * m_generator ;
2007-03-11 22:35:14 +00:00
QString m_generatorName ;
2007-01-28 15:46:10 +00:00
bool m_generatorsLoaded ;
2007-01-02 19:05:49 +00:00
QVector < Page * > m_pagesVector ;
QVector < VisiblePageRect * > m_pageRects ;
2007-01-28 15:46:10 +00:00
// cache of the mimetype we support
QStringList m_supportedMimeTypes ;
2007-01-02 19:05:49 +00:00
} ;
2007-04-14 19:44:07 +00:00
QString DocumentPrivate : : pagesSizeString ( ) const
2007-01-02 19:05:49 +00:00
{
if ( m_generator )
2005-01-15 01:08:35 +00:00
{
2007-01-02 19:05:49 +00:00
if ( m_generator - > pagesSizeMetric ( ) ! = Generator : : None )
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
{
2007-01-02 19:05:49 +00:00
QSizeF size = m_parent - > allPagesSize ( ) ;
if ( size . isValid ( ) ) return localizedSize ( size ) ;
else return QString ( ) ;
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
}
2007-01-02 19:05:49 +00:00
else return QString ( ) ;
2005-01-15 01:08:35 +00:00
}
2007-01-02 19:05:49 +00:00
else return QString ( ) ;
}
2005-01-03 00:45:47 +00:00
2007-04-14 19:44:07 +00:00
QString DocumentPrivate : : localizedSize ( const QSizeF & size ) const
2007-01-02 19:05:49 +00:00
{
double inchesWidth = 0 , inchesHeight = 0 ;
switch ( m_generator - > pagesSizeMetric ( ) )
2005-06-24 16:39:57 +00:00
{
2007-01-02 19:05:49 +00:00
case Generator : : Points :
inchesWidth = size . width ( ) / 72.0 ;
inchesHeight = size . height ( ) / 72.0 ;
break ;
2005-01-03 15:51:05 +00:00
2007-01-02 19:05:49 +00:00
case Generator : : None :
break ;
2005-01-21 20:05:36 +00:00
}
2007-01-02 19:05:49 +00:00
if ( KGlobal : : locale ( ) - > measureSystem ( ) = = KLocale : : Imperial )
2005-01-21 20:05:36 +00:00
{
2007-01-02 19:05:49 +00:00
return i18n ( " %1 x %2 in " , inchesWidth , inchesHeight ) ;
2005-01-21 20:05:36 +00:00
}
2007-01-02 19:05:49 +00:00
else
2005-02-04 22:35:44 +00:00
{
2007-01-02 19:05:49 +00:00
return i18n ( " %1 x %2 mm " , inchesWidth * 25.4 , inchesHeight * 25.4 ) ;
2005-02-04 22:35:44 +00:00
}
2004-09-08 12:41:14 +00:00
}
2007-04-14 19:44:07 +00:00
void DocumentPrivate : : cleanupPixmapMemory ( int /*sure? bytesOffset*/ )
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
{
2007-01-02 19:05:49 +00:00
// [MEM] choose memory parameters based on configuration profile
int clipValue = - 1 ;
int memoryToFree = - 1 ;
switch ( Settings : : memoryLevel ( ) )
2007-01-02 16:40:22 +00:00
{
2007-01-02 19:05:49 +00:00
case Settings : : EnumMemoryLevel : : Low :
memoryToFree = m_allocatedPixmapsTotalMemory ;
break ;
case Settings : : EnumMemoryLevel : : Normal :
memoryToFree = m_allocatedPixmapsTotalMemory - getTotalMemory ( ) / 3 ;
clipValue = ( m_allocatedPixmapsTotalMemory - getFreeMemory ( ) ) / 2 ;
break ;
case Settings : : EnumMemoryLevel : : Aggressive :
clipValue = ( m_allocatedPixmapsTotalMemory - getFreeMemory ( ) ) / 2 ;
break ;
2007-01-02 16:40:22 +00:00
}
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
2007-01-02 19:05:49 +00:00
if ( clipValue > memoryToFree )
memoryToFree = clipValue ;
if ( memoryToFree > 0 )
2007-01-02 16:40:22 +00:00
{
2007-01-02 19:05:49 +00:00
// [MEM] free memory starting from older pixmaps
int pagesFreed = 0 ;
QLinkedList < AllocatedPixmap * > : : iterator pIt = m_allocatedPixmapsFifo . begin ( ) ;
QLinkedList < AllocatedPixmap * > : : iterator pEnd = m_allocatedPixmapsFifo . end ( ) ;
while ( ( pIt ! = pEnd ) & & ( memoryToFree > 0 ) )
{
AllocatedPixmap * p = * pIt ;
if ( m_observers . value ( p - > id ) - > canUnloadPixmap ( p - > page ) )
{
// update internal variables
pIt = m_allocatedPixmapsFifo . erase ( pIt ) ;
m_allocatedPixmapsTotalMemory - = p - > memory ;
memoryToFree - = p - > memory ;
pagesFreed + + ;
// delete pixmap
m_pagesVector . at ( p - > page ) - > deletePixmap ( p - > id ) ;
// delete allocation descriptor
delete p ;
} else
+ + pIt ;
}
//p--rintf("freeMemory A:[%d -%d = %d] \n", m_allocatedPixmapsFifo.count() + pagesFreed, pagesFreed, m_allocatedPixmapsFifo.count() );
2007-01-02 16:40:22 +00:00
}
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
}
2007-04-14 19:44:07 +00:00
int DocumentPrivate : : getTotalMemory ( )
2004-09-08 12:41:14 +00:00
{
2007-01-02 19:05:49 +00:00
static int cachedValue = 0 ;
if ( cachedValue )
return cachedValue ;
2005-01-03 00:28:46 +00:00
2007-01-02 19:05:49 +00:00
# ifdef __linux__
// if /proc/meminfo doesn't exist, return 128MB
QFile memFile ( " /proc/meminfo " ) ;
if ( ! memFile . open ( QIODevice : : ReadOnly ) )
return ( cachedValue = 134217728 ) ;
2004-12-24 10:24:10 +00:00
2007-01-02 19:05:49 +00:00
// read /proc/meminfo and sum up the contents of 'MemFree', 'Buffers'
// and 'Cached' fields. consider swapped memory as used memory.
QTextStream readStream ( & memFile ) ;
while ( true )
2005-08-31 18:13:59 +00:00
{
2007-01-02 19:05:49 +00:00
QString entry = readStream . readLine ( ) ;
2007-03-10 05:38:23 +00:00
if ( entry . isNull ( ) ) break ;
2007-01-02 19:05:49 +00:00
if ( entry . startsWith ( " MemTotal: " ) )
return ( cachedValue = ( 1024 * entry . section ( ' ' , - 2 , - 2 ) . toInt ( ) ) ) ;
2005-08-31 18:13:59 +00:00
}
2007-01-02 19:05:49 +00:00
# endif
return ( cachedValue = 134217728 ) ;
}
2005-01-18 16:43:36 +00:00
2007-04-14 19:44:07 +00:00
int DocumentPrivate : : getFreeMemory ( )
2007-01-02 19:05:49 +00:00
{
static QTime lastUpdate = QTime : : currentTime ( ) ;
static int cachedValue = 0 ;
2005-01-03 00:24:59 +00:00
2007-01-02 19:05:49 +00:00
if ( lastUpdate . secsTo ( QTime : : currentTime ( ) ) < = 2 )
return cachedValue ;
2004-12-10 16:04:45 +00:00
2007-01-02 19:05:49 +00:00
# ifdef __linux__
// if /proc/meminfo doesn't exist, return MEMORY FULL
QFile memFile ( " /proc/meminfo " ) ;
if ( ! memFile . open ( QIODevice : : ReadOnly ) )
return 0 ;
2005-02-01 18:26:56 +00:00
2007-01-02 19:05:49 +00:00
// read /proc/meminfo and sum up the contents of 'MemFree', 'Buffers'
// and 'Cached' fields. consider swapped memory as used memory.
int memoryFree = 0 ;
QString entry ;
QTextStream readStream ( & memFile ) ;
while ( true )
{
entry = readStream . readLine ( ) ;
2007-03-10 05:38:23 +00:00
if ( entry . isNull ( ) ) break ;
2007-01-02 19:05:49 +00:00
if ( entry . startsWith ( " MemFree: " ) | |
entry . startsWith ( " Buffers: " ) | |
entry . startsWith ( " Cached: " ) | |
entry . startsWith ( " SwapFree: " ) )
memoryFree + = entry . section ( ' ' , - 2 , - 2 ) . toInt ( ) ;
if ( entry . startsWith ( " SwapTotal: " ) )
memoryFree - = entry . section ( ' ' , - 2 , - 2 ) . toInt ( ) ;
}
memFile . close ( ) ;
2006-06-24 10:03:12 +00:00
2007-01-02 19:05:49 +00:00
lastUpdate = QTime : : currentTime ( ) ;
2005-07-15 18:20:57 +00:00
2007-01-02 19:05:49 +00:00
return ( cachedValue = ( 1024 * memoryFree ) ) ;
# else
// tell the memory is full.. will act as in LOW profile
return 0 ;
# endif
2004-09-08 12:41:14 +00:00
}
2007-04-14 19:44:07 +00:00
void DocumentPrivate : : loadDocumentInfo ( )
2007-01-02 19:05:49 +00:00
// note: load data and stores it internally (document or pages). observers
// are still uninitialized at this point so don't access them
2004-09-08 12:41:14 +00:00
{
2007-03-10 05:38:23 +00:00
//kDebug(OkularDebug) << "Using '" << d->m_xmlFileName << "' as document info file." << endl;
2007-01-12 22:49:14 +00:00
if ( m_xmlFileName . isEmpty ( ) )
return ;
2007-01-02 19:05:49 +00:00
QFile infoFile ( m_xmlFileName ) ;
if ( ! infoFile . exists ( ) | | ! infoFile . open ( QIODevice : : ReadOnly ) )
return ;
2004-12-17 17:14:46 +00:00
2007-01-02 19:05:49 +00:00
// Load DOM from XML file
QDomDocument doc ( " documentInfo " ) ;
if ( ! doc . setContent ( & infoFile ) )
2005-02-12 17:42:54 +00:00
{
2007-03-10 05:38:23 +00:00
kDebug ( OkularDebug ) < < " Can't load XML pair! Check for broken xml. " < < endl ;
2007-01-02 19:05:49 +00:00
infoFile . close ( ) ;
return ;
2005-02-12 17:42:54 +00:00
}
2007-01-02 19:05:49 +00:00
infoFile . close ( ) ;
2004-12-17 17:14:46 +00:00
2007-01-02 19:05:49 +00:00
QDomElement root = doc . documentElement ( ) ;
if ( root . tagName ( ) ! = " documentInfo " )
return ;
// Parse the DOM tree
QDomNode topLevelNode = root . firstChild ( ) ;
while ( topLevelNode . isElement ( ) )
2004-12-21 12:38:52 +00:00
{
2007-01-02 19:05:49 +00:00
QString catName = topLevelNode . toElement ( ) . tagName ( ) ;
2004-12-24 10:24:10 +00:00
2007-01-02 19:05:49 +00:00
// Restore page attributes (bookmark, annotations, ...) from the DOM
if ( catName = = " pageList " )
2005-01-28 18:18:48 +00:00
{
2007-01-02 19:05:49 +00:00
QDomNode pageNode = topLevelNode . firstChild ( ) ;
while ( pageNode . isElement ( ) )
2005-01-28 18:18:48 +00:00
{
2007-01-02 19:05:49 +00:00
QDomElement pageElement = pageNode . toElement ( ) ;
if ( pageElement . hasAttribute ( " number " ) )
{
// get page number (node's attribute)
bool ok ;
int pageNumber = pageElement . attribute ( " number " ) . toInt ( & ok ) ;
// pass the domElement to the right page, to read config data from
if ( ok & & pageNumber > = 0 & & pageNumber < ( int ) m_pagesVector . count ( ) )
2007-04-14 19:58:17 +00:00
m_pagesVector [ pageNumber ] - > d - > restoreLocalContents ( pageElement ) ;
2007-01-02 19:05:49 +00:00
}
pageNode = pageNode . nextSibling ( ) ;
2005-01-28 18:18:48 +00:00
}
}
2007-01-02 19:05:49 +00:00
// Restore 'general info' from the DOM
else if ( catName = = " generalInfo " )
{
QDomNode infoNode = topLevelNode . firstChild ( ) ;
while ( infoNode . isElement ( ) )
{
QDomElement infoElement = infoNode . toElement ( ) ;
2005-01-21 20:05:36 +00:00
2007-01-02 19:05:49 +00:00
// compatibility: [pre-3.4 viewport storage] @remove after 3.4 relase
if ( infoElement . tagName ( ) = = " activePage " )
{
if ( infoElement . hasAttribute ( " viewport " ) )
* m_viewportIterator = DocumentViewport ( infoElement . attribute ( " viewport " ) ) ;
}
2005-01-21 20:05:36 +00:00
2007-01-02 19:05:49 +00:00
// restore viewports history
if ( infoElement . tagName ( ) = = " history " )
{
// clear history
m_viewportHistory . clear ( ) ;
// append old viewports
QDomNode historyNode = infoNode . firstChild ( ) ;
while ( historyNode . isElement ( ) )
{
QDomElement historyElement = historyNode . toElement ( ) ;
if ( historyElement . hasAttribute ( " viewport " ) )
{
QString vpString = historyElement . attribute ( " viewport " ) ;
m_viewportIterator = m_viewportHistory . insert ( m_viewportHistory . end ( ) ,
DocumentViewport ( vpString ) ) ;
}
historyNode = historyNode . nextSibling ( ) ;
}
// consistancy check
if ( m_viewportHistory . isEmpty ( ) )
m_viewportIterator = m_viewportHistory . insert ( m_viewportHistory . end ( ) , DocumentViewport ( ) ) ;
}
infoNode = infoNode . nextSibling ( ) ;
}
}
2005-01-21 20:05:36 +00:00
2007-01-02 19:05:49 +00:00
topLevelNode = topLevelNode . nextSibling ( ) ;
} // </documentInfo>
2004-09-08 12:41:14 +00:00
}
2007-04-14 19:44:07 +00:00
QString DocumentPrivate : : giveAbsolutePath ( const QString & fileName )
2005-01-15 01:08:35 +00:00
{
2007-01-02 19:05:49 +00:00
if ( ! m_url . isValid ( ) )
return QString ( ) ;
2005-01-15 01:08:35 +00:00
2007-01-02 19:05:49 +00:00
return m_url . upUrl ( ) . url ( ) + fileName ;
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
}
2007-04-14 19:44:07 +00:00
bool DocumentPrivate : : openRelativeFile ( const QString & fileName )
2004-12-05 22:47:32 +00:00
{
2007-01-02 19:05:49 +00:00
QString absFileName = giveAbsolutePath ( fileName ) ;
if ( absFileName . isEmpty ( ) )
return false ;
2004-12-11 17:25:03 +00:00
2007-03-10 05:38:23 +00:00
kDebug ( OkularDebug ) < < " openDocument: ' " < < absFileName < < " ' " < < endl ;
2004-12-05 22:47:32 +00:00
2007-01-02 19:05:49 +00:00
emit m_parent - > openUrl ( absFileName ) ;
return true ;
2005-06-13 15:46:23 +00:00
}
2007-04-14 19:44:07 +00:00
Generator * DocumentPrivate : : loadGeneratorLibrary ( const QString & name , const QString & libname )
2007-01-28 15:46:10 +00:00
{
KLibrary * lib = KLibLoader : : self ( ) - > globalLibrary ( QFile : : encodeName ( libname ) ) ;
if ( ! lib )
{
kWarning ( ) < < " Could not load ' " < < libname < < " ' library. " < < endl ;
2007-02-27 12:56:16 +00:00
kWarning ( ) < < KLibLoader : : self ( ) - > lastErrorMessage ( ) < < endl ;
2007-01-29 08:17:45 +00:00
emit m_parent - > error ( i18n ( " Could not load the necessary plugin to view the document " ) , - 1 ) ;
2007-01-28 15:46:10 +00:00
return 0 ;
}
2007-04-02 13:50:40 +00:00
Generator * ( * create_plugin ) ( ) = ( Generator * ( * ) ( ) ) lib - > resolveFunction ( " create_plugin " ) ;
2007-01-28 15:46:10 +00:00
Generator * generator = create_plugin ( ) ;
if ( ! generator )
{
kWarning ( ) < < " Broken generator " < < libname < < " ! " < < endl ;
return 0 ;
}
GeneratorInfo info ;
info . generator = generator ;
2007-01-30 12:43:43 +00:00
info . library = lib ;
2007-03-11 22:35:14 +00:00
if ( generator - > componentData ( ) & & generator - > componentData ( ) - > aboutData ( ) )
info . appName = QLatin1String ( generator - > componentData ( ) - > aboutData ( ) - > appName ( ) ) ;
2007-02-12 14:15:51 +00:00
m_loadedGenerators . insert ( name , info ) ;
2007-01-28 15:46:10 +00:00
return generator ;
}
2007-04-14 19:44:07 +00:00
void DocumentPrivate : : loadAllGeneratorLibraries ( )
2007-01-28 15:46:10 +00:00
{
if ( m_generatorsLoaded )
return ;
m_generatorsLoaded = true ;
QString constraint ( " ([X-KDE-Priority] > 0) and ( exist Library ) " ) ;
KService : : List offers = KServiceTypeTrader : : self ( ) - > query ( " okular/Generator " , constraint ) ;
2007-01-28 16:10:12 +00:00
loadServiceList ( offers ) ;
}
2007-04-14 19:44:07 +00:00
void DocumentPrivate : : loadServiceList ( const KService : : List & offers )
2007-01-28 16:10:12 +00:00
{
2007-01-28 15:46:10 +00:00
int count = offers . count ( ) ;
if ( count < = 0 )
return ;
for ( int i = 0 ; i < count ; + + i )
{
QString propName = offers . at ( i ) - > name ( ) ;
// don't load already loaded generators
2007-02-03 23:09:40 +00:00
QHash < QString , GeneratorInfo > : : const_iterator genIt = m_loadedGenerators . constFind ( propName ) ;
2007-01-28 15:46:10 +00:00
if ( genIt ! = m_loadedGenerators . end ( ) )
continue ;
Generator * g = loadGeneratorLibrary ( propName , offers . at ( i ) - > library ( ) ) ;
( void ) g ;
}
}
2007-04-14 19:44:07 +00:00
void DocumentPrivate : : unloadGenerator ( const GeneratorInfo & info )
2007-01-30 12:43:43 +00:00
{
delete info . generator ;
info . library - > unload ( ) ;
}
2007-04-14 19:44:07 +00:00
void DocumentPrivate : : cacheExportFormats ( )
2007-03-10 20:51:50 +00:00
{
if ( m_exportCached )
return ;
const ExportFormat : : List formats = m_generator - > exportFormats ( ) ;
for ( int i = 0 ; i < formats . count ( ) ; + + i )
{
if ( formats . at ( i ) . mimeType ( ) - > name ( ) = = QLatin1String ( " text/plain " ) )
m_exportToText = formats . at ( i ) ;
else
m_exportFormats . append ( formats . at ( i ) ) ;
}
m_exportCached = true ;
}
2007-04-14 19:44:07 +00:00
void DocumentPrivate : : saveDocumentInfo ( ) const
2006-05-28 16:54:54 +00:00
{
2007-01-02 19:05:49 +00:00
if ( m_docFileName . isEmpty ( ) )
return ;
2006-05-28 16:54:54 +00:00
2007-01-02 19:05:49 +00:00
QFile infoFile ( m_xmlFileName ) ;
if ( infoFile . open ( QIODevice : : WriteOnly | QIODevice : : Truncate ) )
{
// 1. Create DOM
QDomDocument doc ( " documentInfo " ) ;
QDomElement root = doc . createElement ( " documentInfo " ) ;
doc . appendChild ( root ) ;
2004-12-05 22:47:32 +00:00
2007-01-02 19:05:49 +00:00
// 2.1. Save page attributes (bookmark state, annotations, ... ) to DOM
QDomElement pageList = doc . createElement ( " pageList " ) ;
root . appendChild ( pageList ) ;
// <page list><page number='x'>.... </page> save pages that hold data
QVector < Page * > : : const_iterator pIt = m_pagesVector . begin ( ) , pEnd = m_pagesVector . end ( ) ;
for ( ; pIt ! = pEnd ; + + pIt )
2007-04-14 19:58:17 +00:00
( * pIt ) - > d - > saveLocalContents ( pageList , doc ) ;
2005-01-09 23:37:07 +00:00
2007-01-02 19:05:49 +00:00
// 2.2. Save document info (current viewport, history, ... ) to DOM
QDomElement generalInfo = doc . createElement ( " generalInfo " ) ;
root . appendChild ( generalInfo ) ;
// <general info><history> ... </history> save history up to 10 viewports
QLinkedList < DocumentViewport > : : const_iterator backIterator = m_viewportIterator ;
if ( backIterator ! = m_viewportHistory . end ( ) )
{
// go back up to 10 steps from the current viewportIterator
int backSteps = 10 ;
while ( backSteps - - & & backIterator ! = m_viewportHistory . begin ( ) )
- - backIterator ;
2006-06-23 21:11:52 +00:00
2007-01-02 19:05:49 +00:00
// create history root node
QDomElement historyNode = doc . createElement ( " history " ) ;
generalInfo . appendChild ( historyNode ) ;
2006-06-23 21:11:52 +00:00
2007-01-02 19:05:49 +00:00
// add old[backIterator] and present[viewportIterator] items
QLinkedList < DocumentViewport > : : const_iterator endIt = m_viewportIterator ;
+ + endIt ;
while ( backIterator ! = endIt )
{
QString name = ( backIterator = = m_viewportIterator ) ? " current " : " oldPage " ;
QDomElement historyEntry = doc . createElement ( name ) ;
historyEntry . setAttribute ( " viewport " , ( * backIterator ) . toString ( ) ) ;
historyNode . appendChild ( historyEntry ) ;
+ + backIterator ;
}
}
2004-12-05 22:47:32 +00:00
2007-01-02 19:05:49 +00:00
// 3. Save DOM to XML file
QString xml = doc . toString ( ) ;
QTextStream os ( & infoFile ) ;
os < < xml ;
}
infoFile . close ( ) ;
2004-12-05 22:47:32 +00:00
}
2007-04-14 19:44:07 +00:00
void DocumentPrivate : : slotTimedMemoryCheck ( )
2005-06-13 17:39:58 +00:00
{
2007-01-02 19:05:49 +00:00
// [MEM] clean memory (for 'free mem dependant' profiles only)
if ( Settings : : memoryLevel ( ) ! = Settings : : EnumMemoryLevel : : Low & &
m_allocatedPixmapsTotalMemory > 1024 * 1024 )
cleanupPixmapMemory ( ) ;
2005-06-13 17:39:58 +00:00
}
2007-04-14 19:44:07 +00:00
void DocumentPrivate : : sendGeneratorRequest ( )
2004-09-09 13:25:40 +00:00
{
2007-01-02 19:05:49 +00:00
// find a request
PixmapRequest * request = 0 ;
while ( ! m_pixmapRequestsStack . isEmpty ( ) & & ! request )
{
PixmapRequest * r = m_pixmapRequestsStack . last ( ) ;
if ( ! r )
m_pixmapRequestsStack . pop_back ( ) ;
2005-06-24 16:45:25 +00:00
2007-01-02 19:05:49 +00:00
// request only if page isn't already present or request has invalid id
else if ( r - > page ( ) - > hasPixmap ( r - > id ( ) , r - > width ( ) , r - > height ( ) ) | | r - > id ( ) < = 0 | | r - > id ( ) > = MAX_OBSERVER_ID )
{
m_pixmapRequestsStack . pop_back ( ) ;
delete r ;
}
else if ( ( long ) r - > width ( ) * ( long ) r - > height ( ) > 20000000L )
{
m_pixmapRequestsStack . pop_back ( ) ;
if ( ! m_warnedOutOfMemory )
{
kWarning ( ) < < " Running out of memory on page " < < r - > pageNumber ( )
< < " ( " < < r - > width ( ) < < " x " < < r - > height ( ) < < " px); " < < endl ;
kWarning ( ) < < " this message will be reported only once. " < < endl ;
m_warnedOutOfMemory = true ;
}
delete r ;
}
else
request = r ;
}
2005-07-20 22:28:23 +00:00
2007-01-02 19:05:49 +00:00
// if no request found (or already generated), return
if ( ! request )
return ;
- GIGANTIC 2700 line diff with LOTS OF FEATURES!
- 1. editor-like text selection, and I do mean it, its not pseudo-editor
(like the ones acroread and kviewshell have) it doesnt intersect the
selection area with words under it, no, it does a lot more, including
work on cursors and searching for the text area closest to the given
cursor
- 2. rotation support, change the orientation of the documents if
you need too :)
- 3. the kfaxview backend works beautifully, porting kviewshell backends
is damn easy ! djvu and dvi will be next!
- 4. Hardware Blending of selection rectangles! We now use XRender
instead of KImageEffect, makes a damn faster blend!
- 5. Overview mode - as seen in Kviewshell, but quite a bit extended,
the kviewshell is only one state, while we support it in both
continous and non-continous form
- BTW. I coded all those features myself, (apart from kfaxview backend library)
it is an impressive bit right? but oKular cant be run by only one person,
join in on the fun! i can introduce you into the code just mail niedakh@gmail.com
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=509871
2006-02-15 18:54:49 +00:00
2007-01-02 19:05:49 +00:00
// [MEM] preventive memory freeing
int pixmapBytes = 4 * request - > width ( ) * request - > height ( ) ;
if ( pixmapBytes > ( 1024 * 1024 ) )
cleanupPixmapMemory ( pixmapBytes ) ;
- GIGANTIC 2700 line diff with LOTS OF FEATURES!
- 1. editor-like text selection, and I do mean it, its not pseudo-editor
(like the ones acroread and kviewshell have) it doesnt intersect the
selection area with words under it, no, it does a lot more, including
work on cursors and searching for the text area closest to the given
cursor
- 2. rotation support, change the orientation of the documents if
you need too :)
- 3. the kfaxview backend works beautifully, porting kviewshell backends
is damn easy ! djvu and dvi will be next!
- 4. Hardware Blending of selection rectangles! We now use XRender
instead of KImageEffect, makes a damn faster blend!
- 5. Overview mode - as seen in Kviewshell, but quite a bit extended,
the kviewshell is only one state, while we support it in both
continous and non-continous form
- BTW. I coded all those features myself, (apart from kfaxview backend library)
it is an impressive bit right? but oKular cant be run by only one person,
join in on the fun! i can introduce you into the code just mail niedakh@gmail.com
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=509871
2006-02-15 18:54:49 +00:00
2007-01-02 19:05:49 +00:00
// submit the request to the generator
2007-01-31 18:31:19 +00:00
if ( m_generator - > canGeneratePixmap ( ) )
2007-01-02 19:05:49 +00:00
{
2007-03-10 05:38:23 +00:00
kDebug ( OkularDebug ) < < " sending request id= " < < request - > id ( ) < < " " < < request - > width ( ) < < " x " < < request - > height ( ) < < " @ " < < request - > pageNumber ( ) < < " async == " < < request - > asynchronous ( ) < < endl ;
2007-01-02 19:05:49 +00:00
m_pixmapRequestsStack . removeAll ( request ) ;
2006-10-25 15:35:53 +00:00
2007-01-05 17:09:47 +00:00
if ( ( int ) m_rotation % 2 )
2007-01-17 16:50:54 +00:00
request - > swap ( ) ;
2006-10-25 15:35:53 +00:00
2007-01-31 18:31:19 +00:00
m_generator - > generatePixmap ( request ) ;
2007-01-02 19:05:49 +00:00
}
else
// pino (7/4/2006): set the polling interval from 10 to 30
QTimer : : singleShot ( 30 , m_parent , SLOT ( sendGeneratorRequest ( ) ) ) ;
2006-07-01 22:17:53 +00:00
}
2007-04-14 19:44:07 +00:00
void DocumentPrivate : : rotationFinished ( int page )
2006-07-01 22:17:53 +00:00
{
2007-01-02 19:05:49 +00:00
QMap < int , DocumentObserver * > : : const_iterator it = m_observers . begin ( ) , end = m_observers . end ( ) ;
for ( ; it ! = end ; + + it ) {
( * it ) - > notifyPageChanged ( page , DocumentObserver : : Pixmap | DocumentObserver : : Annotations ) ;
2006-10-25 15:35:53 +00:00
}
2006-07-01 22:17:53 +00:00
}
2007-03-30 17:46:50 +00:00
Document : : Document ( QWidget * widget )
2007-04-14 19:44:07 +00:00
: QObject ( widget ) , d ( new DocumentPrivate ( this ) )
2006-07-01 22:17:53 +00:00
{
2007-01-02 19:05:49 +00:00
d - > m_bookmarkManager = new BookmarkManager ( this ) ;
2007-03-24 10:47:22 +00:00
connect ( PageController : : self ( ) , SIGNAL ( rotationFinished ( int ) ) ,
this , SLOT ( rotationFinished ( int ) ) ) ;
2006-07-01 22:17:53 +00:00
}
2007-01-02 19:05:49 +00:00
Document : : ~ Document ( )
2005-01-27 17:31:07 +00:00
{
2007-02-05 15:54:19 +00:00
// stop any audio playback
AudioPlayer : : instance ( ) - > stopPlaybacks ( ) ;
2007-01-02 19:05:49 +00:00
// delete generator, pages, and related stuff
closeDocument ( ) ;
2005-01-27 17:31:07 +00:00
2007-02-05 15:54:19 +00:00
// delete the bookmark manager
delete d - > m_bookmarkManager ;
2007-01-28 15:46:10 +00:00
// delete the loaded generators
2007-02-03 23:09:40 +00:00
QHash < QString , GeneratorInfo > : : const_iterator it = d - > m_loadedGenerators . constBegin ( ) , itEnd = d - > m_loadedGenerators . constEnd ( ) ;
2007-01-28 15:46:10 +00:00
for ( ; it ! = itEnd ; + + it )
2007-01-30 12:43:43 +00:00
d - > unloadGenerator ( it . value ( ) ) ;
2007-01-28 15:46:10 +00:00
d - > m_loadedGenerators . clear ( ) ;
2007-01-02 19:05:49 +00:00
// delete the private structure
delete d ;
2005-01-27 17:31:07 +00:00
}
2007-01-02 19:05:49 +00:00
static bool kserviceMoreThan ( const KService : : Ptr & s1 , const KService : : Ptr & s2 )
2005-01-01 15:44:44 +00:00
{
2007-01-02 19:05:49 +00:00
return s1 - > property ( " X-KDE-Priority " ) . toInt ( ) > s2 - > property ( " X-KDE-Priority " ) . toInt ( ) ;
2005-01-01 15:44:44 +00:00
}
2004-11-09 17:20:19 +00:00
2007-01-12 22:49:14 +00:00
bool Document : : openDocument ( const QString & docFile , const KUrl & url , const KMimeType : : Ptr & _mime )
2006-06-02 20:42:57 +00:00
{
2007-01-12 22:49:14 +00:00
KMimeType : : Ptr mime = _mime ;
QByteArray filedata ;
bool isstdin = url . fileName ( KUrl : : ObeyTrailingSlash ) = = QLatin1String ( " - " ) ;
if ( ! isstdin )
2007-01-02 19:05:49 +00:00
{
2007-01-12 22:49:14 +00:00
if ( mime . count ( ) < = 0 )
return false ;
// docFile is always local so we can use QFile on it
QFile fileReadTest ( docFile ) ;
if ( ! fileReadTest . open ( QIODevice : : ReadOnly ) )
{
d - > m_docFileName . clear ( ) ;
return false ;
}
// determine the related "xml document-info" filename
d - > m_url = url ;
d - > m_docFileName = docFile ;
QString fn = docFile . contains ( ' / ' ) ? docFile . section ( ' / ' , - 1 , - 1 ) : docFile ;
fn = " kpdf/ " + QString : : number ( fileReadTest . size ( ) ) + ' . ' + fn + " .xml " ;
fileReadTest . close ( ) ;
d - > m_xmlFileName = KStandardDirs : : locateLocal ( " data " , fn ) ;
}
else
{
QFile qstdin ;
qstdin . open ( stdin , QIODevice : : ReadOnly ) ;
filedata = qstdin . readAll ( ) ;
mime = KMimeType : : findByContent ( filedata ) ;
if ( ! mime | | mime - > name ( ) = = QLatin1String ( " application/octet-stream " ) )
return false ;
2007-01-02 19:05:49 +00:00
}
2007-01-02 22:37:55 +00:00
2007-01-02 19:05:49 +00:00
// 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 ( ) )
2006-10-15 19:37:14 +00:00
{
2007-01-26 18:35:28 +00:00
emit error ( i18n ( " Can not find a plugin which is able to handle the passed document. " ) , - 1 ) ;
2007-01-02 19:05:49 +00:00
kWarning ( ) < < " No plugin for mimetype ' " < < mime - > name ( ) < < " '. " < < endl ;
2007-01-02 22:37:55 +00:00
return false ;
2006-10-15 19:37:14 +00:00
}
2007-01-02 19:05:49 +00:00
int hRank = 0 ;
// best ranked offer search
2007-01-28 15:46:10 +00:00
int offercount = offers . count ( ) ;
if ( offercount > 1 )
2006-10-15 19:37:14 +00:00
{
2007-01-28 15:46:10 +00:00
// sort the offers: the offers with an higher priority come before
qStableSort ( offers . begin ( ) , offers . end ( ) , kserviceMoreThan ) ;
2006-10-15 19:37:14 +00:00
2007-01-28 15:46:10 +00:00
if ( Settings : : chooseGenerators ( ) )
2007-01-02 19:05:49 +00:00
{
2007-01-28 15:46:10 +00:00
QStringList list ;
for ( int i = 0 ; i < offercount ; + + i )
{
list < < offers . at ( i ) - > name ( ) ;
}
ChooseEngineDialog choose ( list , mime , 0 ) ;
if ( choose . exec ( ) = = QDialog : : Rejected )
2007-01-02 19:05:49 +00:00
return false ;
2007-01-28 15:46:10 +00:00
hRank = choose . selectedGenerator ( ) ;
2007-01-02 19:05:49 +00:00
}
2005-01-27 17:31:07 +00:00
}
2004-09-15 20:45:00 +00:00
2007-01-02 19:05:49 +00:00
QString propName = offers . at ( hRank ) - > name ( ) ;
2007-02-03 23:09:40 +00:00
QHash < QString , GeneratorInfo > : : const_iterator genIt = d - > m_loadedGenerators . constFind ( propName ) ;
2007-03-11 22:35:14 +00:00
QString appName ;
2007-02-03 23:09:40 +00:00
if ( genIt ! = d - > m_loadedGenerators . constEnd ( ) )
2005-01-18 16:43:36 +00:00
{
2007-01-28 15:46:10 +00:00
d - > m_generator = genIt . value ( ) . generator ;
2007-03-11 22:35:14 +00:00
appName = genIt . value ( ) . appName ;
2007-01-02 19:05:49 +00:00
}
else
{
2007-01-28 15:46:10 +00:00
d - > m_generator = d - > loadGeneratorLibrary ( propName , offers . at ( hRank ) - > library ( ) ) ;
if ( ! d - > m_generator )
return false ;
2007-03-11 22:35:14 +00:00
genIt = d - > m_loadedGenerators . constFind ( propName ) ;
Q_ASSERT ( genIt ! = d - > m_loadedGenerators . constEnd ( ) ) ;
appName = genIt . value ( ) . appName ;
2007-01-02 19:05:49 +00:00
}
2007-01-28 15:46:10 +00:00
Q_ASSERT_X ( d - > m_generator , " Document::load() " , " null generator?! " ) ;
2007-03-11 22:35:14 +00:00
if ( ! appName . isEmpty ( ) )
KGlobal : : locale ( ) - > insertCatalog ( appName ) ;
2007-01-02 19:05:49 +00:00
d - > m_generator - > setDocument ( this ) ;
2004-12-22 18:21:36 +00:00
2007-01-02 19:05:49 +00:00
// connect error reporting signals
connect ( d - > m_generator , SIGNAL ( error ( const QString & , int ) ) , this , SIGNAL ( error ( const QString & , int ) ) ) ;
connect ( d - > m_generator , SIGNAL ( warning ( const QString & , int ) ) , this , SIGNAL ( warning ( const QString & , int ) ) ) ;
connect ( d - > m_generator , SIGNAL ( notice ( const QString & , int ) ) , this , SIGNAL ( notice ( const QString & , int ) ) ) ;
2006-06-02 20:42:57 +00:00
2007-01-02 19:05:49 +00:00
// 1. load Document (and set busy cursor while loading)
QApplication : : setOverrideCursor ( Qt : : WaitCursor ) ;
2007-01-12 22:49:14 +00:00
bool openOk = false ;
if ( ! isstdin )
{
openOk = d - > m_generator - > loadDocument ( docFile , d - > m_pagesVector ) ;
}
else if ( ! filedata . isEmpty ( ) )
{
if ( d - > m_generator - > hasFeature ( Generator : : ReadRawData ) )
{
openOk = d - > m_generator - > loadDocumentFromData ( filedata , d - > m_pagesVector ) ;
}
else
{
d - > m_tempFile = new KTemporaryFile ( ) ;
if ( ! d - > m_tempFile - > open ( ) )
{
delete d - > m_tempFile ;
d - > m_tempFile = 0 ;
}
else
{
d - > m_tempFile - > write ( filedata ) ;
QString tmpFileName = d - > m_tempFile - > fileName ( ) ;
d - > m_tempFile - > close ( ) ;
openOk = d - > m_generator - > loadDocument ( tmpFileName , d - > m_pagesVector ) ;
}
}
}
2004-12-22 18:21:36 +00:00
2007-01-02 19:05:49 +00:00
QApplication : : restoreOverrideCursor ( ) ;
if ( ! openOk | | d - > m_pagesVector . size ( ) < = 0 )
{
2007-03-11 22:35:14 +00:00
if ( ! appName . isEmpty ( ) )
KGlobal : : locale ( ) - > removeCatalog ( appName ) ;
2007-01-02 19:05:49 +00:00
d - > m_generator = 0 ;
return openOk ;
2004-12-21 12:38:52 +00:00
}
2005-01-18 16:43:36 +00:00
2007-03-11 22:35:14 +00:00
d - > m_generatorName = propName ;
2007-01-02 19:05:49 +00:00
// 2. load Additional Data (our bookmarks and metadata) about the document
d - > loadDocumentInfo ( ) ;
d - > m_bookmarkManager - > setUrl ( d - > m_url ) ;
2004-09-15 20:45:00 +00:00
2007-01-02 19:05:49 +00:00
// 3. setup observers inernal lists and data
foreachObserver ( notifySetup ( d - > m_pagesVector , true ) ) ;
2004-12-10 16:04:45 +00:00
2007-01-02 19:05:49 +00:00
// 4. set initial page (restoring the page saved in xml if loaded)
DocumentViewport loadedViewport = ( * d - > m_viewportIterator ) ;
if ( loadedViewport . isValid ( ) )
{
( * d - > m_viewportIterator ) = DocumentViewport ( ) ;
if ( loadedViewport . pageNumber > = ( int ) d - > m_pagesVector . size ( ) )
loadedViewport . pageNumber = d - > m_pagesVector . size ( ) - 1 ;
}
else
loadedViewport . pageNumber = 0 ;
setViewport ( loadedViewport ) ;
2004-12-21 12:38:52 +00:00
2007-01-02 19:05:49 +00:00
// start bookmark saver timer
if ( ! d - > m_saveBookmarksTimer )
{
d - > m_saveBookmarksTimer = new QTimer ( this ) ;
connect ( d - > m_saveBookmarksTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( saveDocumentInfo ( ) ) ) ;
}
d - > m_saveBookmarksTimer - > start ( 5 * 60 * 1000 ) ;
2005-02-18 18:24:45 +00:00
2007-01-02 19:05:49 +00:00
// start memory check timer
if ( ! d - > m_memCheckTimer )
{
d - > m_memCheckTimer = new QTimer ( this ) ;
connect ( d - > m_memCheckTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( slotTimedMemoryCheck ( ) ) ) ;
}
d - > m_memCheckTimer - > start ( 2000 ) ;
2005-02-18 18:24:45 +00:00
2007-01-02 19:05:49 +00:00
if ( d - > m_nextDocumentViewport . isValid ( ) )
{
setViewport ( d - > m_nextDocumentViewport ) ;
d - > m_nextDocumentViewport = DocumentViewport ( ) ;
}
2005-02-18 18:24:45 +00:00
2007-01-02 19:05:49 +00:00
return true ;
2005-02-18 18:24:45 +00:00
}
2006-08-08 15:31:13 +00:00
2007-01-02 19:05:49 +00:00
2007-03-10 17:25:14 +00:00
QString Document : : xmlFile ( ) const
2006-08-08 15:31:13 +00:00
{
2007-01-02 19:05:49 +00:00
if ( d - > m_generator )
{
Okular : : GuiInterface * iface = qobject_cast < Okular : : GuiInterface * > ( d - > m_generator ) ;
return iface ? iface - > xmlFile ( ) : QString ( ) ;
}
else
return QString ( ) ;
2006-08-10 06:32:03 +00:00
}
2007-01-02 19:05:49 +00:00
void Document : : setupGui ( KActionCollection * ac , QToolBox * tBox )
2006-08-10 06:32:03 +00:00
{
2007-01-02 19:05:49 +00:00
if ( d - > m_generator & & ac & & tBox )
2006-09-14 18:42:28 +00:00
{
2007-01-02 19:05:49 +00:00
Okular : : GuiInterface * iface = qobject_cast < Okular : : GuiInterface * > ( d - > m_generator ) ;
if ( iface )
iface - > setupGui ( ac , tBox ) ;
2006-09-14 18:42:28 +00:00
}
2006-08-08 15:31:13 +00:00
}
2006-11-01 15:17:22 +00:00
2007-01-02 19:05:49 +00:00
void Document : : closeDocument ( )
2006-11-01 15:17:22 +00:00
{
2007-01-02 19:05:49 +00:00
// close the current document and save document info if a document is still opened
if ( d - > m_generator & & d - > m_pagesVector . size ( ) > 0 )
{
d - > m_generator - > closeDocument ( ) ;
d - > saveDocumentInfo ( ) ;
}
2006-11-01 15:17:22 +00:00
2007-01-02 19:05:49 +00:00
// stop timers
if ( d - > m_memCheckTimer )
d - > m_memCheckTimer - > stop ( ) ;
if ( d - > m_saveBookmarksTimer )
d - > m_saveBookmarksTimer - > stop ( ) ;
if ( d - > m_generator )
2006-11-01 15:17:22 +00:00
{
2007-01-02 19:05:49 +00:00
Okular : : GuiInterface * iface = qobject_cast < Okular : : GuiInterface * > ( d - > m_generator ) ;
if ( iface )
iface - > freeGui ( ) ;
2007-01-28 15:46:10 +00:00
// disconnect the generator from this document ...
d - > m_generator - > setDocument ( 0 ) ;
// .. and this document from the generator signals
disconnect ( d - > m_generator , 0 , this , 0 ) ;
2007-03-11 22:35:14 +00:00
QHash < QString , GeneratorInfo > : : const_iterator genIt = d - > m_loadedGenerators . constFind ( d - > m_generatorName ) ;
Q_ASSERT ( genIt ! = d - > m_loadedGenerators . constEnd ( ) ) ;
if ( ! genIt . value ( ) . appName . isEmpty ( ) )
KGlobal : : locale ( ) - > removeCatalog ( genIt . value ( ) . appName ) ;
2006-11-01 15:17:22 +00:00
}
2007-01-02 19:05:49 +00:00
d - > m_generator = 0 ;
2007-03-11 22:35:14 +00:00
d - > m_generatorName = QString ( ) ;
2007-01-02 19:05:49 +00:00
d - > m_url = KUrl ( ) ;
2007-01-12 22:49:14 +00:00
d - > m_docFileName = QString ( ) ;
d - > m_xmlFileName = QString ( ) ;
delete d - > m_tempFile ;
d - > m_tempFile = 0 ;
2007-03-10 20:51:50 +00:00
d - > m_exportCached = false ;
d - > m_exportFormats . clear ( ) ;
d - > m_exportToText = ExportFormat ( ) ;
2007-01-02 19:05:49 +00:00
// remove requests left in queue
QLinkedList < PixmapRequest * > : : const_iterator sIt = d - > m_pixmapRequestsStack . begin ( ) ;
QLinkedList < PixmapRequest * > : : const_iterator sEnd = d - > m_pixmapRequestsStack . end ( ) ;
for ( ; sIt ! = sEnd ; + + sIt )
delete * sIt ;
d - > m_pixmapRequestsStack . clear ( ) ;
2006-09-26 22:22:01 +00:00
2007-01-02 19:05:49 +00:00
// send an empty list to observers (to free their data)
foreachObserver ( notifySetup ( QVector < Page * > ( ) , true ) ) ;
2006-09-26 22:22:01 +00:00
2007-01-02 19:05:49 +00:00
// delete pages and clear 'd->m_pagesVector' container
QVector < Page * > : : const_iterator pIt = d - > m_pagesVector . begin ( ) ;
QVector < Page * > : : const_iterator pEnd = d - > m_pagesVector . end ( ) ;
for ( ; pIt ! = pEnd ; + + pIt )
delete * pIt ;
d - > m_pagesVector . clear ( ) ;
2006-09-26 22:22:01 +00:00
2007-01-02 19:05:49 +00:00
// clear 'memory allocation' descriptors
QLinkedList < AllocatedPixmap * > : : const_iterator aIt = d - > m_allocatedPixmapsFifo . begin ( ) ;
QLinkedList < AllocatedPixmap * > : : const_iterator aEnd = d - > m_allocatedPixmapsFifo . end ( ) ;
for ( ; aIt ! = aEnd ; + + aIt )
delete * aIt ;
d - > m_allocatedPixmapsFifo . clear ( ) ;
2006-09-26 22:22:01 +00:00
2007-01-02 19:05:49 +00:00
// clear 'running searches' descriptors
QMap < int , RunningSearch * > : : const_iterator rIt = d - > m_searches . begin ( ) ;
QMap < int , RunningSearch * > : : const_iterator rEnd = d - > m_searches . end ( ) ;
for ( ; rIt ! = rEnd ; + + rIt )
delete * rIt ;
d - > m_searches . clear ( ) ;
2004-10-09 08:10:56 +00:00
2007-01-02 19:05:49 +00:00
// clear the visible areas and notify the observers
QVector < VisiblePageRect * > : : const_iterator vIt = d - > m_pageRects . begin ( ) ;
QVector < VisiblePageRect * > : : const_iterator vEnd = d - > m_pageRects . end ( ) ;
for ( ; vIt ! = vEnd ; + + vIt )
delete * vIt ;
d - > m_pageRects . clear ( ) ;
foreachObserver ( notifyVisibleRectsChanged ( ) ) ;
2005-01-09 23:37:07 +00:00
2007-01-02 19:05:49 +00:00
// reset internal variables
d - > m_viewportHistory . clear ( ) ;
d - > m_viewportHistory . append ( DocumentViewport ( ) ) ;
d - > m_viewportIterator = d - > m_viewportHistory . begin ( ) ;
d - > m_allocatedPixmapsTotalMemory = 0 ;
2007-01-05 23:12:06 +00:00
d - > m_pageSize = PageSize ( ) ;
d - > m_pageSizes . clear ( ) ;
2005-01-09 23:37:07 +00:00
}
2007-01-02 19:05:49 +00:00
void Document : : addObserver ( DocumentObserver * pObserver )
2005-01-09 23:37:07 +00:00
{
2007-01-02 19:05:49 +00:00
// keep the pointer to the observer in a map
2007-02-12 14:15:51 +00:00
d - > m_observers . insert ( pObserver - > observerId ( ) , pObserver ) ;
2005-01-09 23:37:07 +00:00
2007-01-02 19:05:49 +00:00
// if the observer is added while a document is already opened, tell it
if ( ! d - > m_pagesVector . isEmpty ( ) )
2005-01-27 17:31:07 +00:00
{
2007-01-02 19:05:49 +00:00
pObserver - > notifySetup ( d - > m_pagesVector , true ) ;
pObserver - > notifyViewportChanged ( false /*disables smoothMove*/ ) ;
2005-01-27 17:31:07 +00:00
}
2007-01-02 19:05:49 +00:00
}
2005-01-27 17:31:07 +00:00
2007-01-02 19:05:49 +00:00
void Document : : removeObserver ( DocumentObserver * pObserver )
{
// remove observer from the map. it won't receive notifications anymore
if ( d - > m_observers . contains ( pObserver - > observerId ( ) ) )
2005-01-20 17:33:05 +00:00
{
2007-01-02 19:05:49 +00:00
// free observer's pixmap data
int observerId = pObserver - > observerId ( ) ;
QVector < Page * > : : const_iterator it = d - > m_pagesVector . begin ( ) , end = d - > m_pagesVector . end ( ) ;
for ( ; it ! = end ; + + it )
( * it ) - > deletePixmap ( observerId ) ;
// [MEM] free observer's allocation descriptors
QLinkedList < AllocatedPixmap * > : : iterator aIt = d - > m_allocatedPixmapsFifo . begin ( ) ;
QLinkedList < AllocatedPixmap * > : : iterator aEnd = d - > m_allocatedPixmapsFifo . end ( ) ;
2005-01-26 10:42:07 +00:00
while ( aIt ! = aEnd )
2005-01-20 17:33:05 +00:00
{
2007-01-02 19:05:49 +00:00
AllocatedPixmap * p = * aIt ;
if ( p - > id = = observerId )
2005-01-20 17:33:05 +00:00
{
2007-01-02 19:05:49 +00:00
aIt = d - > m_allocatedPixmapsFifo . erase ( aIt ) ;
delete p ;
2005-01-20 17:33:05 +00:00
}
2007-01-02 19:05:49 +00:00
else
+ + aIt ;
2005-01-20 17:33:05 +00:00
}
2007-01-02 19:05:49 +00:00
// delete observer entry from the map
d - > m_observers . remove ( observerId ) ;
2005-01-26 10:42:07 +00:00
}
2004-09-08 12:41:14 +00:00
}
2007-01-02 19:05:49 +00:00
void Document : : reparseConfig ( )
2005-01-27 17:31:07 +00:00
{
2007-01-02 19:05:49 +00:00
// reparse generator config and if something changed clear Pages
bool configchanged = false ;
if ( d - > m_generator )
2005-01-27 17:31:07 +00:00
{
2007-01-02 19:05:49 +00:00
Okular : : ConfigInterface * iface = qobject_cast < Okular : : ConfigInterface * > ( d - > m_generator ) ;
if ( iface )
configchanged = iface - > reparseConfig ( ) ;
2005-01-27 17:31:07 +00:00
}
2007-01-02 19:05:49 +00:00
if ( configchanged )
2005-01-27 17:31:07 +00:00
{
2007-01-02 19:05:49 +00:00
// invalidate pixmaps
QVector < Page * > : : const_iterator it = d - > m_pagesVector . begin ( ) , end = d - > m_pagesVector . end ( ) ;
for ( ; it ! = end ; + + it ) {
( * it ) - > deletePixmaps ( ) ;
( * it ) - > deleteRects ( ) ;
}
// [MEM] remove allocation descriptors
QLinkedList < AllocatedPixmap * > : : const_iterator aIt = d - > m_allocatedPixmapsFifo . begin ( ) ;
QLinkedList < AllocatedPixmap * > : : const_iterator aEnd = d - > m_allocatedPixmapsFifo . end ( ) ;
for ( ; aIt ! = aEnd ; + + aIt )
delete * aIt ;
d - > m_allocatedPixmapsFifo . clear ( ) ;
d - > m_allocatedPixmapsTotalMemory = 0 ;
// send reload signals to observers
foreachObserver ( notifyContentsCleared ( DocumentObserver : : Pixmap ) ) ;
2005-01-27 17:31:07 +00:00
}
2007-01-02 19:05:49 +00:00
// free memory if in 'low' profile
if ( Settings : : memoryLevel ( ) = = Settings : : EnumMemoryLevel : : Low & &
! d - > m_allocatedPixmapsFifo . isEmpty ( ) & & ! d - > m_pagesVector . isEmpty ( ) )
d - > cleanupPixmapMemory ( ) ;
2005-01-27 17:31:07 +00:00
}
2007-01-02 19:05:49 +00:00
2007-03-30 17:46:50 +00:00
QWidget * Document : : widget ( ) const
{
return static_cast < QWidget * > ( parent ( ) ) ;
}
2007-01-02 19:05:49 +00:00
bool Document : : isOpened ( ) const
2006-09-15 21:08:48 +00:00
{
2007-01-02 19:05:49 +00:00
return d - > m_generator ;
2006-09-15 21:08:48 +00:00
}
2005-02-01 18:26:56 +00:00
2007-01-02 19:05:49 +00:00
bool Document : : canConfigurePrinter ( ) const
2004-09-16 21:04:49 +00:00
{
2007-01-02 19:05:49 +00:00
if ( d - > m_generator )
2005-02-01 18:26:56 +00:00
{
2007-01-02 19:05:49 +00:00
Okular : : PrintInterface * iface = qobject_cast < Okular : : PrintInterface * > ( d - > m_generator ) ;
return iface ? true : false ;
2005-02-01 18:26:56 +00:00
}
2007-01-02 19:05:49 +00:00
else
return 0 ;
}
const DocumentInfo * Document : : documentInfo ( ) const
{
if ( d - > m_generator )
2006-07-11 19:57:17 +00:00
{
2007-01-02 19:05:49 +00:00
DocumentInfo * info = const_cast < DocumentInfo * > ( d - > m_generator - > generateDocumentInfo ( ) ) ;
QString pagesSize = d - > pagesSizeString ( ) ;
if ( ! pagesSize . isEmpty ( ) )
{
info - > set ( " pagesSize " , pagesSize , i18n ( " Pages Size " ) ) ;
}
return info ;
2006-07-11 19:57:17 +00:00
}
2007-01-02 19:05:49 +00:00
else return NULL ;
}
2005-02-01 18:26:56 +00:00
2007-01-02 19:05:49 +00:00
const DocumentSynopsis * Document : : documentSynopsis ( ) const
{
return d - > m_generator ? d - > m_generator - > generateDocumentSynopsis ( ) : NULL ;
}
2005-02-01 18:26:56 +00:00
2007-01-02 19:05:49 +00:00
const DocumentFonts * Document : : documentFonts ( ) const
{
return d - > m_generator ? d - > m_generator - > generateDocumentFonts ( ) : NULL ;
}
2005-02-02 18:18:26 +00:00
2007-01-02 19:05:49 +00:00
const QList < EmbeddedFile * > * Document : : embeddedFiles ( ) const
{
return d - > m_generator ? d - > m_generator - > embeddedFiles ( ) : NULL ;
}
2005-02-01 18:26:56 +00:00
2007-01-02 19:05:49 +00:00
const Page * Document : : page ( int n ) const
{
2007-02-03 23:09:40 +00:00
return ( n < d - > m_pagesVector . count ( ) ) ? d - > m_pagesVector . at ( n ) : 0 ;
2007-01-02 19:05:49 +00:00
}
2005-02-01 18:26:56 +00:00
2007-01-02 19:05:49 +00:00
const DocumentViewport & Document : : viewport ( ) const
{
return ( * d - > m_viewportIterator ) ;
}
2005-02-02 18:18:26 +00:00
2007-01-02 19:05:49 +00:00
const QVector < VisiblePageRect * > & Document : : visiblePageRects ( ) const
{
return d - > m_pageRects ;
}
2004-09-08 12:41:14 +00:00
2007-01-02 19:05:49 +00:00
void Document : : setVisiblePageRects ( const QVector < VisiblePageRect * > & visiblePageRects , int excludeId )
{
QVector < VisiblePageRect * > : : const_iterator vIt = d - > m_pageRects . begin ( ) ;
QVector < VisiblePageRect * > : : const_iterator vEnd = d - > m_pageRects . end ( ) ;
for ( ; vIt ! = vEnd ; + + vIt )
delete * vIt ;
d - > m_pageRects = visiblePageRects ;
// notify change to all other (different from id) observers
QMap < int , DocumentObserver * > : : const_iterator it = d - > m_observers . begin ( ) , end = d - > m_observers . end ( ) ;
for ( ; it ! = end ; + + it )
if ( it . key ( ) ! = excludeId )
( * it ) - > notifyVisibleRectsChanged ( ) ;
}
2005-02-01 18:26:56 +00:00
2007-01-02 19:05:49 +00:00
uint Document : : currentPage ( ) const
{
return ( * d - > m_viewportIterator ) . pageNumber ;
}
2005-02-01 18:26:56 +00:00
2007-01-02 19:05:49 +00:00
uint Document : : pages ( ) const
{
return d - > m_pagesVector . size ( ) ;
}
2005-02-02 18:18:26 +00:00
2007-01-02 19:05:49 +00:00
KUrl Document : : currentDocument ( ) const
{
return d - > m_url ;
}
2005-02-02 18:18:26 +00:00
2007-03-10 23:59:11 +00:00
bool Document : : isAllowed ( Permission action ) const
2007-01-02 19:05:49 +00:00
{
2007-01-29 14:28:58 +00:00
# if !OKULAR_FORCE_DRM
if ( KAuthorized : : authorize ( " skip_drm " ) & & ! Okular : : Settings : : obeyDRM ( ) )
return true ;
# endif
2007-03-10 23:59:11 +00:00
return d - > m_generator ? d - > m_generator - > isAllowed ( action ) : false ;
2007-01-02 19:05:49 +00:00
}
2005-02-01 18:26:56 +00:00
2007-01-02 19:05:49 +00:00
bool Document : : supportsSearching ( ) const
{
2007-01-17 11:58:20 +00:00
return d - > m_generator ? d - > m_generator - > hasFeature ( Generator : : TextExtraction ) : false ;
2007-01-02 19:05:49 +00:00
}
2004-09-13 08:51:36 +00:00
2007-01-05 23:12:06 +00:00
bool Document : : supportsPageSizes ( ) const
2007-01-02 19:05:49 +00:00
{
2007-01-17 18:02:53 +00:00
return d - > m_generator ? d - > m_generator - > hasFeature ( Generator : : PageSizes ) : false ;
2007-01-02 19:05:49 +00:00
}
2005-02-02 18:18:26 +00:00
2007-01-05 23:12:06 +00:00
PageSize : : List Document : : pageSizes ( ) const
2007-01-02 19:05:49 +00:00
{
2007-01-05 23:12:06 +00:00
if ( d - > m_generator )
{
if ( d - > m_pageSizes . isEmpty ( ) )
d - > m_pageSizes = d - > m_generator - > pageSizes ( ) ;
return d - > m_pageSizes ;
}
return PageSize : : List ( ) ;
2007-01-02 19:05:49 +00:00
}
2005-02-01 18:26:56 +00:00
2007-01-02 19:05:49 +00:00
bool Document : : canExportToText ( ) const
{
if ( ! d - > m_generator )
return false ;
2005-02-01 18:26:56 +00:00
2007-03-10 20:51:50 +00:00
d - > cacheExportFormats ( ) ;
return ! d - > m_exportToText . isNull ( ) ;
2007-01-02 19:05:49 +00:00
}
2005-02-20 16:04:40 +00:00
2007-01-02 19:05:49 +00:00
bool Document : : exportToText ( const QString & fileName ) const
{
if ( ! d - > m_generator )
return false ;
2005-02-20 16:04:40 +00:00
2007-03-10 20:51:50 +00:00
d - > cacheExportFormats ( ) ;
if ( d - > m_exportToText . isNull ( ) )
return false ;
2005-02-01 18:26:56 +00:00
2007-03-10 20:51:50 +00:00
return d - > m_generator - > exportTo ( fileName , d - > m_exportToText ) ;
2004-09-08 12:41:14 +00:00
}
2007-01-02 19:05:49 +00:00
ExportFormat : : List Document : : exportFormats ( ) const
2004-11-09 17:20:19 +00:00
{
2007-03-10 20:51:50 +00:00
if ( ! d - > m_generator )
return ExportFormat : : List ( ) ;
d - > cacheExportFormats ( ) ;
return d - > m_exportFormats ;
2004-11-09 17:20:19 +00:00
}
2007-01-02 19:05:49 +00:00
bool Document : : exportTo ( const QString & fileName , const ExportFormat & format ) const
2005-02-01 18:26:56 +00:00
{
2007-01-02 19:05:49 +00:00
return d - > m_generator ? d - > m_generator - > exportTo ( fileName , format ) : false ;
2005-02-01 18:26:56 +00:00
}
2007-01-02 19:05:49 +00:00
bool Document : : historyAtBegin ( ) const
2006-07-11 19:57:17 +00:00
{
2007-01-02 19:05:49 +00:00
return d - > m_viewportIterator = = d - > m_viewportHistory . begin ( ) ;
2006-07-11 19:57:17 +00:00
}
2005-02-01 18:26:56 +00:00
2007-01-02 19:05:49 +00:00
bool Document : : historyAtEnd ( ) const
2004-11-09 17:20:19 +00:00
{
2007-01-02 19:05:49 +00:00
return d - > m_viewportIterator = = - - ( d - > m_viewportHistory . end ( ) ) ;
2004-11-09 17:20:19 +00:00
}
2007-01-02 22:37:55 +00:00
QVariant Document : : metaData ( const QString & key , const QVariant & option ) const
2006-12-27 16:04:49 +00:00
{
2007-01-02 19:05:49 +00:00
return d - > m_generator ? d - > m_generator - > metaData ( key , option ) : QVariant ( ) ;
2006-12-27 16:04:49 +00:00
}
2007-01-05 17:09:47 +00:00
Rotation Document : : rotation ( ) const
2006-12-27 16:04:49 +00:00
{
2007-01-02 19:05:49 +00:00
return d - > m_rotation ;
2006-12-27 16:04:49 +00:00
}
2007-01-02 19:05:49 +00:00
QSizeF Document : : allPagesSize ( ) const
2006-12-27 16:04:49 +00:00
{
2007-01-02 19:05:49 +00:00
bool allPagesSameSize = true ;
QSizeF size ;
for ( int i = 0 ; allPagesSameSize & & i < d - > m_pagesVector . count ( ) ; + + i )
{
2007-02-12 14:15:51 +00:00
const Page * p = d - > m_pagesVector . at ( i ) ;
2007-01-02 19:05:49 +00:00
if ( i = = 0 ) size = QSizeF ( p - > width ( ) , p - > height ( ) ) ;
else
{
allPagesSameSize = ( size = = QSizeF ( p - > width ( ) , p - > height ( ) ) ) ;
}
}
if ( allPagesSameSize ) return size ;
else return QSizeF ( ) ;
2006-12-27 16:04:49 +00:00
}
2007-01-02 19:05:49 +00:00
QString Document : : pageSizeString ( int page ) const
2006-12-27 16:04:49 +00:00
{
2007-01-02 19:05:49 +00:00
if ( d - > m_generator )
{
if ( d - > m_generator - > pagesSizeMetric ( ) ! = Generator : : None )
{
2007-02-12 14:15:51 +00:00
const Page * p = d - > m_pagesVector . at ( page ) ;
2007-01-02 19:05:49 +00:00
return d - > localizedSize ( QSizeF ( p - > width ( ) , p - > height ( ) ) ) ;
}
}
return QString ( ) ;
2006-12-27 16:04:49 +00:00
}
2007-01-02 19:05:49 +00:00
void Document : : requestPixmaps ( const QLinkedList < PixmapRequest * > & requests )
2004-09-08 12:41:14 +00:00
{
2007-01-02 19:05:49 +00:00
if ( ! d - > m_generator )
{
// delete requests..
QLinkedList < PixmapRequest * > : : const_iterator rIt = requests . begin ( ) , rEnd = requests . end ( ) ;
for ( ; rIt ! = rEnd ; + + rIt )
delete * rIt ;
// ..and return
2004-10-06 00:05:49 +00:00
return ;
2007-01-02 19:05:49 +00:00
}
2004-10-06 00:05:49 +00:00
2007-01-02 19:05:49 +00:00
// 1. [CLEAN STACK] remove previous requests of requesterID
int requesterID = requests . first ( ) - > id ( ) ;
QLinkedList < PixmapRequest * > : : iterator sIt = d - > m_pixmapRequestsStack . begin ( ) , sEnd = d - > m_pixmapRequestsStack . end ( ) ;
while ( sIt ! = sEnd )
2004-10-06 00:05:49 +00:00
{
2007-01-02 19:05:49 +00:00
if ( ( * sIt ) - > id ( ) = = requesterID )
{
// delete request and remove it from stack
delete * sIt ;
sIt = d - > m_pixmapRequestsStack . erase ( sIt ) ;
}
else
+ + sIt ;
}
2005-02-04 22:35:44 +00:00
2007-01-02 19:05:49 +00:00
// 2. [ADD TO STACK] add requests to stack
bool threadingDisabled = ! Settings : : enableThreading ( ) ;
QLinkedList < PixmapRequest * > : : const_iterator rIt = requests . begin ( ) , rEnd = requests . end ( ) ;
for ( ; rIt ! = rEnd ; + + rIt )
{
// set the 'page field' (see PixmapRequest) and check if it is valid
PixmapRequest * request = * rIt ;
2007-03-10 05:38:23 +00:00
kDebug ( OkularDebug ) < < " request id= " < < request - > id ( ) < < " " < < request - > width ( ) < < " x " < < request - > height ( ) < < " @ " < < request - > pageNumber ( ) < < endl ;
2007-01-02 19:05:49 +00:00
if ( d - > m_pagesVector . value ( request - > pageNumber ( ) ) = = 0 )
{
// skip requests referencing an invalid page (must not happen)
delete request ;
continue ;
}
2004-12-10 16:04:45 +00:00
2007-01-02 19:05:49 +00:00
request - > setPage ( d - > m_pagesVector . value ( request - > pageNumber ( ) ) ) ;
2005-06-13 17:44:33 +00:00
2007-01-02 19:05:49 +00:00
if ( ! request - > asynchronous ( ) )
request - > setPriority ( 0 ) ;
2004-10-06 00:05:49 +00:00
2007-01-02 19:05:49 +00:00
if ( request - > asynchronous ( ) & & threadingDisabled )
request - > setAsynchronous ( false ) ;
2004-12-10 16:04:45 +00:00
2007-01-02 19:05:49 +00:00
// add request to the 'stack' at the right place
if ( ! request - > priority ( ) )
// add priority zero requests to the top of the stack
d - > m_pixmapRequestsStack . append ( request ) ;
else
{
// insert in stack sorted by priority
sIt = d - > m_pixmapRequestsStack . begin ( ) ;
sEnd = d - > m_pixmapRequestsStack . end ( ) ;
2007-01-04 14:28:54 +00:00
while ( sIt ! = sEnd & & ( * sIt ) - > priority ( ) > request - > priority ( ) )
2007-01-02 19:05:49 +00:00
+ + sIt ;
d - > m_pixmapRequestsStack . insert ( sIt , request ) ;
}
}
2004-12-10 16:04:45 +00:00
2007-01-02 19:05:49 +00:00
// 3. [START FIRST GENERATION] if <NO>generator is ready, start a new generation,
// or else (if gen is running) it will be started when the new contents will
//come from generator (in requestDone())</NO>
// all handling of requests put into sendGeneratorRequest
2007-01-24 15:06:45 +00:00
// if ( generator->canRequestPixmap() )
2007-01-02 19:05:49 +00:00
d - > sendGeneratorRequest ( ) ;
}
2004-12-10 16:04:45 +00:00
2007-01-31 21:10:00 +00:00
void Document : : requestTextPage ( uint page , enum GenerationType type )
2007-01-02 19:05:49 +00:00
{
Page * kp = d - > m_pagesVector [ page ] ;
if ( ! d - > m_generator | | ! kp )
return ;
2004-12-10 16:04:45 +00:00
2007-01-02 19:05:49 +00:00
// Memory management for TextPages
2004-12-10 16:04:45 +00:00
2007-01-31 21:10:00 +00:00
d - > m_generator - > generateTextPage ( kp , type ) ;
2007-01-02 19:05:49 +00:00
}
2005-03-05 15:59:15 +00:00
2007-01-02 19:05:49 +00:00
void Document : : addPageAnnotation ( int page , Annotation * annotation )
{
// find out the page to attach annotation
Page * kp = d - > m_pagesVector [ page ] ;
if ( ! d - > m_generator | | ! kp )
return ;
2006-07-09 14:38:35 +00:00
2007-01-02 19:05:49 +00:00
// add annotation to the page
kp - > addAnnotation ( annotation ) ;
2004-12-10 16:04:45 +00:00
2007-01-02 19:05:49 +00:00
// notify observers about the change
foreachObserver ( notifyPageChanged ( page , DocumentObserver : : Annotations ) ) ;
2004-09-09 13:25:40 +00:00
}
2004-11-09 17:20:19 +00:00
2007-01-02 19:05:49 +00:00
void Document : : modifyPageAnnotation ( int page , Annotation * newannotation )
2006-11-17 22:15:15 +00:00
{
2007-01-02 19:05:49 +00:00
//TODO: modify annotations
2007-03-10 05:38:23 +00:00
2007-01-02 19:05:49 +00:00
// find out the page
Page * kp = d - > m_pagesVector [ page ] ;
if ( ! d - > m_generator | | ! kp )
2006-11-17 22:15:15 +00:00
return ;
2007-03-10 05:38:23 +00:00
2007-04-17 19:55:18 +00:00
kp - > d - > modifyAnnotation ( newannotation ) ;
2007-01-02 19:05:49 +00:00
// notify observers about the change
foreachObserver ( notifyPageChanged ( page , DocumentObserver : : Annotations ) ) ;
}
2006-11-17 22:15:15 +00:00
2007-01-02 19:05:49 +00:00
void Document : : removePageAnnotation ( int page , Annotation * annotation )
{
// find out the page
Page * kp = d - > m_pagesVector [ page ] ;
if ( ! d - > m_generator | | ! kp )
2006-11-18 15:16:16 +00:00
return ;
2007-01-02 19:05:49 +00:00
// try to remove the annotation
if ( kp - > removeAnnotation ( annotation ) )
2006-11-17 22:15:15 +00:00
{
2007-01-02 19:05:49 +00:00
// in case of success, notify observers about the change
foreachObserver ( notifyPageChanged ( page , DocumentObserver : : Annotations ) ) ;
2006-11-17 22:15:15 +00:00
}
2007-01-02 19:05:49 +00:00
}
2006-11-17 22:15:15 +00:00
2007-01-02 19:05:49 +00:00
void Document : : removePageAnnotations ( int page , QList < Annotation * > annotations )
{
// find out the page
Page * kp = d - > m_pagesVector [ page ] ;
if ( ! d - > m_generator | | ! kp )
2006-11-17 22:15:15 +00:00
return ;
2007-01-02 19:05:49 +00:00
bool changed = false ;
foreach ( Annotation * annotation , annotations )
{
// try to remove the annotation
if ( kp - > removeAnnotation ( annotation ) )
{
changed = true ;
}
}
if ( changed )
{
// in case we removed even only one annotation, notify observers about the change
foreachObserver ( notifyPageChanged ( page , DocumentObserver : : Annotations ) ) ;
}
}
2006-11-17 22:15:15 +00:00
2007-01-02 19:05:49 +00:00
void Document : : setPageTextSelection ( int page , RegularAreaRect * rect , const QColor & color )
{
Page * kp = d - > m_pagesVector [ page ] ;
if ( ! d - > m_generator | | ! kp )
2006-11-17 22:15:15 +00:00
return ;
2007-01-02 19:05:49 +00:00
// add or remove the selection basing whether rect is null or not
if ( rect )
kp - > setTextSelections ( rect , color ) ;
else
kp - > deleteTextSelections ( ) ;
// notify observers about the change
foreachObserver ( notifyPageChanged ( page , DocumentObserver : : TextSelection ) ) ;
2006-11-17 22:15:15 +00:00
}
2007-01-02 19:05:49 +00:00
/* REFERENCE IMPLEMENTATION: better calling setViewport from other code
void Document : : setNextPage ( )
2004-11-09 17:20:19 +00:00
{
2007-01-02 19:05:49 +00:00
// advance page and set viewport on observers
if ( ( * d - > m_viewportIterator ) . pageNumber < ( int ) d - > m_pagesVector . count ( ) - 1 )
setViewport ( DocumentViewport ( ( * d - > m_viewportIterator ) . pageNumber + 1 ) ) ;
2004-11-09 17:20:19 +00:00
}
2004-12-10 16:04:45 +00:00
2007-01-02 19:05:49 +00:00
void Document : : setPrevPage ( )
2007-01-02 16:11:40 +00:00
{
2007-01-02 19:05:49 +00:00
// go to previous page and set viewport on observers
if ( ( * d - > m_viewportIterator ) . pageNumber > 0 )
setViewport ( DocumentViewport ( ( * d - > m_viewportIterator ) . pageNumber - 1 ) ) ;
}
*/
void Document : : setViewportPage ( int page , int excludeId , bool smoothMove )
{
// clamp page in range [0 ... numPages-1]
if ( page < 0 )
page = 0 ;
else if ( page > ( int ) d - > m_pagesVector . count ( ) )
page = d - > m_pagesVector . count ( ) - 1 ;
// make a viewport from the page and broadcast it
setViewport ( DocumentViewport ( page ) , excludeId , smoothMove ) ;
}
void Document : : setViewport ( const DocumentViewport & viewport , int excludeId , bool smoothMove )
{
// if already broadcasted, don't redo it
DocumentViewport & oldViewport = * d - > m_viewportIterator ;
// disabled by enrico on 2005-03-18 (less debug output)
//if ( viewport == oldViewport )
2007-03-10 05:38:23 +00:00
// kDebug(OkularDebug) << "setViewport with the same viewport." << endl;
2007-01-02 19:05:49 +00:00
// set internal viewport taking care of history
if ( oldViewport . pageNumber = = viewport . pageNumber | | ! oldViewport . isValid ( ) )
2007-01-02 16:11:40 +00:00
{
2007-01-02 19:05:49 +00:00
// if page is unchanged save the viewport at current position in queue
oldViewport = viewport ;
2007-01-02 16:11:40 +00:00
}
else
2007-01-02 19:05:49 +00:00
{
// remove elements after viewportIterator in queue
d - > m_viewportHistory . erase ( + + d - > m_viewportIterator , d - > m_viewportHistory . end ( ) ) ;
// keep the list to a reasonable size by removing head when needed
if ( d - > m_viewportHistory . count ( ) > = 100 )
d - > m_viewportHistory . pop_front ( ) ;
// add the item at the end of the queue
d - > m_viewportIterator = d - > m_viewportHistory . insert ( d - > m_viewportHistory . end ( ) , viewport ) ;
}
// notify change to all other (different from id) observers
QMap < int , DocumentObserver * > : : const_iterator it = d - > m_observers . begin ( ) , end = d - > m_observers . end ( ) ;
for ( ; it ! = end ; + + it )
if ( it . key ( ) ! = excludeId )
( * it ) - > notifyViewportChanged ( smoothMove ) ;
// [MEM] raise position of currently viewed page in allocation queue
if ( d - > m_allocatedPixmapsFifo . count ( ) > 1 )
{
const int page = viewport . pageNumber ;
QLinkedList < AllocatedPixmap * > viewportPixmaps ;
QLinkedList < AllocatedPixmap * > : : iterator aIt = d - > m_allocatedPixmapsFifo . begin ( ) ;
QLinkedList < AllocatedPixmap * > : : iterator aEnd = d - > m_allocatedPixmapsFifo . end ( ) ;
while ( aIt ! = aEnd )
{
if ( ( * aIt ) - > page = = page )
{
viewportPixmaps . append ( * aIt ) ;
aIt = d - > m_allocatedPixmapsFifo . erase ( aIt ) ;
continue ;
}
+ + aIt ;
}
if ( ! viewportPixmaps . isEmpty ( ) )
d - > m_allocatedPixmapsFifo + = viewportPixmaps ;
}
2007-01-02 16:11:40 +00:00
}
2007-01-02 19:05:49 +00:00
void Document : : setPrevViewport ( )
// restore viewport from the history
2005-01-18 16:43:36 +00:00
{
2007-01-02 19:05:49 +00:00
if ( d - > m_viewportIterator ! = d - > m_viewportHistory . begin ( ) )
{
// restore previous viewport and notify it to observers
- - d - > m_viewportIterator ;
foreachObserver ( notifyViewportChanged ( true ) ) ;
}
}
2005-01-20 17:33:05 +00:00
2007-01-02 19:05:49 +00:00
void Document : : setNextViewport ( )
// restore next viewport from the history
{
QLinkedList < DocumentViewport > : : const_iterator nextIterator = d - > m_viewportIterator ;
+ + nextIterator ;
if ( nextIterator ! = d - > m_viewportHistory . end ( ) )
{
// restore next viewport and notify it to observers
+ + d - > m_viewportIterator ;
foreachObserver ( notifyViewportChanged ( true ) ) ;
}
}
void Document : : setNextDocumentViewport ( const DocumentViewport & viewport )
{
d - > m_nextDocumentViewport = viewport ;
}
bool Document : : searchText ( int searchID , const QString & text , bool fromStart , Qt : : CaseSensitivity caseSensitivity ,
SearchType type , bool moveViewport , const QColor & color , bool noDialogs )
{
// safety checks: don't perform searches on empty or unsearchable docs
2007-01-17 11:58:20 +00:00
if ( ! d - > m_generator | | ! d - > m_generator - > hasFeature ( Generator : : TextExtraction ) | | d - > m_pagesVector . isEmpty ( ) )
2007-01-02 19:05:49 +00:00
return false ;
// if searchID search not recorded, create new descriptor and init params
2007-02-12 14:15:51 +00:00
QMap < int , RunningSearch * > : : iterator searchIt = d - > m_searches . find ( searchID ) ;
if ( searchIt = = d - > m_searches . end ( ) )
2007-01-02 19:05:49 +00:00
{
RunningSearch * search = new RunningSearch ( ) ;
search - > continueOnPage = - 1 ;
2007-02-12 14:15:51 +00:00
searchIt = d - > m_searches . insert ( searchID , search ) ;
2007-01-02 19:05:49 +00:00
}
if ( d - > m_lastSearchID ! = searchID )
{
resetSearch ( d - > m_lastSearchID ) ;
}
d - > m_lastSearchID = searchID ;
2007-02-12 14:15:51 +00:00
RunningSearch * s = * searchIt ;
2007-01-02 19:05:49 +00:00
// update search stucture
bool newText = text ! = s - > cachedString ;
s - > cachedString = text ;
s - > cachedType = type ;
s - > cachedCaseSensitivity = caseSensitivity ;
s - > cachedViewportMove = moveViewport ;
s - > cachedNoDialogs = noDialogs ;
s - > cachedColor = color ;
// global data for search
bool foundAMatch = false ;
QLinkedList < int > pagesToNotify ;
// remove highlights from pages and queue them for notifying changes
pagesToNotify + = s - > highlightedPages ;
QLinkedList < int > : : const_iterator it = s - > highlightedPages . begin ( ) , end = s - > highlightedPages . end ( ) ;
for ( ; it ! = end ; + + it )
d - > m_pagesVector [ * it ] - > deleteHighlights ( searchID ) ;
s - > highlightedPages . clear ( ) ;
// set hourglass cursor
QApplication : : setOverrideCursor ( Qt : : WaitCursor ) ;
// 1. ALLDOC - proces all document marking pages
2007-01-02 22:37:55 +00:00
if ( type = = AllDocument )
2007-01-02 19:05:49 +00:00
{
// search and highlight 'text' (as a solid phrase) on all pages
QVector < Page * > : : const_iterator it = d - > m_pagesVector . begin ( ) , end = d - > m_pagesVector . end ( ) ;
for ( ; it ! = end ; + + it )
2005-01-20 17:33:05 +00:00
{
2007-01-02 19:05:49 +00:00
// get page (from the first to the last)
Page * page = * it ;
int pageNumber = page - > number ( ) ;
// request search page if needed
if ( ! page - > hasTextPage ( ) )
requestTextPage ( pageNumber ) ;
// loop on a page adding highlights for all found items
bool addedHighlights = false ;
RegularAreaRect * lastMatch = 0 ;
while ( 1 )
{
if ( lastMatch )
2007-01-04 18:13:00 +00:00
{
RegularAreaRect * lastMatchOld = lastMatch ;
2007-01-02 19:05:49 +00:00
lastMatch = page - > findText ( searchID , text , NextResult , caseSensitivity , lastMatch ) ;
2007-01-04 18:13:00 +00:00
delete lastMatchOld ;
}
2007-01-02 19:05:49 +00:00
else
lastMatch = page - > findText ( searchID , text , FromTop , caseSensitivity ) ;
if ( ! lastMatch )
break ;
// add highligh rect to the page
page - > setHighlight ( searchID , lastMatch , color ) ;
addedHighlights = true ;
}
2007-01-04 18:13:00 +00:00
delete lastMatch ;
2007-01-02 19:05:49 +00:00
// if added highlights, udpate internals and queue page for notify
if ( addedHighlights )
{
foundAMatch = true ;
s - > highlightedPages . append ( pageNumber ) ;
if ( ! pagesToNotify . contains ( pageNumber ) )
pagesToNotify . append ( pageNumber ) ;
}
2005-01-20 17:33:05 +00:00
}
2007-01-02 19:05:49 +00:00
// reset cursor to previous shape
QApplication : : restoreOverrideCursor ( ) ;
2005-01-20 17:33:05 +00:00
2007-01-02 19:05:49 +00:00
// send page lists if found anything new
//if ( foundAMatch ) ?maybe?
foreachObserver ( notifySetup ( d - > m_pagesVector , false ) ) ;
}
// 2. NEXTMATCH - find next matching item (or start from top)
else if ( type = = NextMatch )
{
// find out from where to start/resume search from
int viewportPage = ( * d - > m_viewportIterator ) . pageNumber ;
int currentPage = fromStart ? 0 : ( ( s - > continueOnPage ! = - 1 ) ? s - > continueOnPage : viewportPage ) ;
Page * lastPage = fromStart ? 0 : d - > m_pagesVector [ currentPage ] ;
2005-01-20 17:33:05 +00:00
2007-01-02 19:05:49 +00:00
// continue checking last TextPage first (if it is the current page)
RegularAreaRect * match = 0 ;
if ( lastPage & & lastPage - > number ( ) = = s - > continueOnPage )
{
if ( newText )
match = lastPage - > findText ( searchID , text , FromTop , caseSensitivity ) ;
else
match = lastPage - > findText ( searchID , text , NextResult , caseSensitivity , & s - > continueOnMatch ) ;
if ( ! match )
currentPage + + ;
}
2005-01-20 17:33:05 +00:00
2007-01-02 19:05:49 +00:00
// if no match found, loop through the whole doc, starting from currentPage
if ( ! match )
{
const int pageCount = d - > m_pagesVector . count ( ) ;
for ( int i = 0 ; i < pageCount ; i + + )
{
if ( currentPage > = pageCount )
{
2007-03-30 17:46:50 +00:00
if ( noDialogs | | KMessageBox : : questionYesNo ( widget ( ) , i18n ( " End of document reached. \n Continue from the beginning? " ) , QString ( ) , KStandardGuiItem : : cont ( ) , KStandardGuiItem : : cancel ( ) ) = = KMessageBox : : Yes )
2007-01-02 19:05:49 +00:00
currentPage = 0 ;
else
break ;
}
// get page
Page * page = d - > m_pagesVector [ currentPage ] ;
// request search page if needed
if ( ! page - > hasTextPage ( ) )
requestTextPage ( page - > number ( ) ) ;
// if found a match on the current page, end the loop
if ( ( match = page - > findText ( searchID , text , FromTop , caseSensitivity ) ) )
break ;
currentPage + + ;
}
}
// reset cursor to previous shape
QApplication : : restoreOverrideCursor ( ) ;
// if a match has been found..
if ( match )
{
// update the RunningSearch structure adding this match..
foundAMatch = true ;
s - > continueOnPage = currentPage ;
s - > continueOnMatch = * match ;
s - > highlightedPages . append ( currentPage ) ;
// ..add highlight to the page..
d - > m_pagesVector [ currentPage ] - > setHighlight ( searchID , match , color ) ;
// ..queue page for notifying changes..
if ( ! pagesToNotify . contains ( currentPage ) )
pagesToNotify . append ( currentPage ) ;
// ..move the viewport to show the first of the searched word sequence centered
if ( moveViewport )
{
DocumentViewport searchViewport ( currentPage ) ;
searchViewport . rePos . enabled = true ;
searchViewport . rePos . normalizedX = ( match - > first ( ) . left + match - > first ( ) . right ) / 2.0 ;
searchViewport . rePos . normalizedY = ( match - > first ( ) . top + match - > first ( ) . bottom ) / 2.0 ;
setViewport ( searchViewport , - 1 , true ) ;
}
2007-01-04 18:13:00 +00:00
delete match ;
2007-01-02 19:05:49 +00:00
}
else if ( ! noDialogs )
2007-03-30 17:46:50 +00:00
KMessageBox : : information ( widget ( ) , i18n ( " No matches found for '%1'. " , text ) ) ;
2007-01-02 19:05:49 +00:00
}
// 3. PREVMATCH //TODO
2007-01-02 22:37:55 +00:00
else if ( type = = PreviousMatch )
2007-01-02 19:05:49 +00:00
{
}
// 4. GOOGLE* - process all document marking pages
else if ( type = = GoogleAll | | type = = GoogleAny )
{
// search and highlight every word in 'text' on all pages
bool matchAll = type = = GoogleAll ;
QStringList words = text . split ( " " , QString : : SkipEmptyParts ) ;
int wordsCount = words . count ( ) ,
hueStep = ( wordsCount > 1 ) ? ( 60 / ( wordsCount - 1 ) ) : 60 ,
baseHue , baseSat , baseVal ;
color . getHsv ( & baseHue , & baseSat , & baseVal ) ;
QVector < Page * > : : const_iterator it = d - > m_pagesVector . begin ( ) , end = d - > m_pagesVector . end ( ) ;
for ( ; it ! = end ; + + it )
{
// get page (from the first to the last)
Page * page = * it ;
int pageNumber = page - > number ( ) ;
// request search page if needed
if ( ! page - > hasTextPage ( ) )
requestTextPage ( pageNumber ) ;
// loop on a page adding highlights for all found items
bool allMatched = wordsCount > 0 ,
anyMatched = false ;
for ( int w = 0 ; w < wordsCount ; w + + )
{
QString word = words [ w ] ;
int newHue = baseHue - w * hueStep ;
if ( newHue < 0 )
newHue + = 360 ;
QColor wordColor = QColor : : fromHsv ( newHue , baseSat , baseVal ) ;
RegularAreaRect * lastMatch = 0 ;
// add all highlights for current word
bool wordMatched = false ;
while ( 1 )
{
if ( lastMatch )
2007-01-04 18:59:31 +00:00
{
RegularAreaRect * lastMatchOld = lastMatch ;
2007-02-12 14:19:31 +00:00
lastMatch = page - > findText ( searchID , word , NextResult , caseSensitivity , lastMatch ) ;
2007-01-04 18:59:31 +00:00
delete lastMatchOld ;
}
2007-01-02 19:05:49 +00:00
else
lastMatch = page - > findText ( searchID , word , FromTop , caseSensitivity ) ;
if ( ! lastMatch )
break ;
// add highligh rect to the page
page - > setHighlight ( searchID , lastMatch , wordColor ) ;
wordMatched = true ;
}
allMatched = allMatched & & wordMatched ;
anyMatched = anyMatched | | wordMatched ;
}
// if not all words are present in page, remove partial highlights
if ( ! allMatched & & matchAll )
page - > deleteHighlights ( searchID ) ;
// if page contains all words, udpate internals and queue page for notify
if ( ( allMatched & & matchAll ) | | ( anyMatched & & ! matchAll ) )
{
foundAMatch = true ;
s - > highlightedPages . append ( pageNumber ) ;
if ( ! pagesToNotify . contains ( pageNumber ) )
pagesToNotify . append ( pageNumber ) ;
}
}
// reset cursor to previous shape
QApplication : : restoreOverrideCursor ( ) ;
// send page lists to update observers (since some filter on bookmarks)
foreachObserver ( notifySetup ( d - > m_pagesVector , false ) ) ;
}
// notify observers about highlights changes
QLinkedList < int > : : const_iterator nIt = pagesToNotify . begin ( ) , nEnd = pagesToNotify . end ( ) ;
for ( ; nIt ! = nEnd ; + + nIt )
foreachObserver ( notifyPageChanged ( * nIt , DocumentObserver : : Highlights ) ) ;
// return if search has found one or more matches
return foundAMatch ;
}
bool Document : : continueSearch ( int searchID )
{
// check if searchID is present in runningSearches
2007-02-12 14:15:51 +00:00
QMap < int , RunningSearch * > : : const_iterator it = d - > m_searches . constFind ( searchID ) ;
if ( it = = d - > m_searches . constEnd ( ) )
2007-01-02 19:05:49 +00:00
return false ;
// start search with cached parameters from last search by searchID
2007-02-12 14:15:51 +00:00
RunningSearch * p = * it ;
2007-01-02 19:05:49 +00:00
return searchText ( searchID , p - > cachedString , false , p - > cachedCaseSensitivity ,
p - > cachedType , p - > cachedViewportMove , p - > cachedColor ,
p - > cachedNoDialogs ) ;
2005-01-18 16:43:36 +00:00
}
2007-01-02 19:05:49 +00:00
void Document : : resetSearch ( int searchID )
2005-01-18 16:43:36 +00:00
{
2007-01-02 19:05:49 +00:00
// check if searchID is present in runningSearches
2007-02-12 14:15:51 +00:00
QMap < int , RunningSearch * > : : iterator searchIt = d - > m_searches . find ( searchID ) ;
if ( searchIt = = d - > m_searches . end ( ) )
2005-01-18 16:43:36 +00:00
return ;
2007-01-02 19:05:49 +00:00
// get previous parameters for search
2007-02-12 14:15:51 +00:00
RunningSearch * s = * searchIt ;
2005-01-18 16:43:36 +00:00
2007-01-02 19:05:49 +00:00
// unhighlight pages and inform observers about that
QLinkedList < int > : : const_iterator it = s - > highlightedPages . begin ( ) , end = s - > highlightedPages . end ( ) ;
for ( ; it ! = end ; + + it )
- Page/Link: tooltips for links backported
- Page: rotation does not switch height and width
- Document/Part/Generator:
1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel
also add possibility to merge an XML .rc file with menu layout. Relevant functions are:
QString Generator::getXMLFile(), returns a QString with your .rc file name.
void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface
2. Supporting backend settings:
If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings]
set to true) are found, a menu item: configure backends is created, clicking on it results in
loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg)
function should be overloaded by a generator and dlg->addPage should be used to add pages.
If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another.
3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration)
to the generator class, and sending a message to the user is as simple as emitting a signal!
4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your
event and return true if pageview is to proceed with its handling or false if not.
5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your
Generator::print()
6. PixmapRequest handling update:
a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async)
b.) Document::sendGeneratorRequests is a slot now
c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving)
is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is
run in three places:
1. in requestPixmaps when we receive a request
2. in requestDone if pixmapStack is not empty
3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async)
it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request
7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime
- TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks.
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
{
2007-01-02 19:05:49 +00:00
int pageNumber = * it ;
d - > m_pagesVector [ pageNumber ] - > deleteHighlights ( searchID ) ;
foreachObserver ( notifyPageChanged ( pageNumber , DocumentObserver : : Highlights ) ) ;
}
2006-11-20 07:53:32 +00:00
2007-01-02 19:05:49 +00:00
// send the setup signal too (to update views that filter on matches)
foreachObserver ( notifySetup ( d - > m_pagesVector , false ) ) ;
2006-11-20 07:53:32 +00:00
2007-01-02 19:05:49 +00:00
// remove serch from the runningSearches list and delete it
2007-02-12 14:15:51 +00:00
d - > m_searches . erase ( searchIt ) ;
2007-01-02 19:05:49 +00:00
delete s ;
}
bool Document : : continueLastSearch ( )
{
return continueSearch ( d - > m_lastSearchID ) ;
2005-01-18 16:43:36 +00:00
}
2004-09-08 12:41:14 +00:00
2007-01-02 19:05:49 +00:00
void Document : : addBookmark ( int n )
2006-10-15 19:37:14 +00:00
{
2007-01-02 19:05:49 +00:00
if ( n > = 0 & & n < ( int ) d - > m_pagesVector . count ( ) )
2006-10-15 19:37:14 +00:00
{
2007-01-02 19:05:49 +00:00
if ( d - > m_bookmarkManager - > setPageBookmark ( n ) )
foreachObserver ( notifyPageChanged ( n , DocumentObserver : : Bookmark ) ) ;
2006-10-15 19:37:14 +00:00
}
}
2007-01-02 19:05:49 +00:00
void Document : : addBookmark ( const KUrl & referurl , const Okular : : DocumentViewport & vp , const QString & title )
2006-10-15 19:37:14 +00:00
{
2007-01-02 19:05:49 +00:00
if ( ! vp . isValid ( ) )
return ;
2006-10-15 19:37:14 +00:00
2007-01-02 19:05:49 +00:00
if ( d - > m_bookmarkManager - > addBookmark ( referurl , vp , title ) )
foreachObserver ( notifyPageChanged ( vp . pageNumber , DocumentObserver : : Bookmark ) ) ;
2006-10-15 19:37:14 +00:00
}
2007-01-02 19:05:49 +00:00
bool Document : : isBookmarked ( int page ) const
2004-12-22 18:21:36 +00:00
{
2007-01-02 19:05:49 +00:00
return d - > m_bookmarkManager - > isPageBookmarked ( page ) ;
}
2004-12-22 18:21:36 +00:00
2007-01-13 14:45:51 +00:00
void Document : : removeBookmark ( int n )
{
if ( n > = 0 & & n < ( int ) d - > m_pagesVector . count ( ) )
{
if ( d - > m_bookmarkManager - > removePageBookmark ( n ) )
foreachObserver ( notifyPageChanged ( n , DocumentObserver : : Bookmark ) ) ;
}
}
2007-01-02 19:05:49 +00:00
void Document : : removeBookmark ( const KUrl & referurl , const KBookmark & bm )
{
int changedpage = d - > m_bookmarkManager - > removeBookmark ( referurl , bm ) ;
if ( changedpage ! = - 1 )
foreachObserver ( notifyPageChanged ( changedpage , DocumentObserver : : Bookmark ) ) ;
}
2004-12-22 18:21:36 +00:00
2007-01-02 19:05:49 +00:00
const BookmarkManager * Document : : bookmarkManager ( ) const
{
return d - > m_bookmarkManager ;
}
2004-12-22 18:21:36 +00:00
2007-01-02 19:05:49 +00:00
void Document : : processLink ( const Link * link )
{
if ( ! link )
return ;
2004-12-24 10:24:10 +00:00
2007-01-02 19:05:49 +00:00
switch ( link - > linkType ( ) )
2004-12-22 18:21:36 +00:00
{
2007-01-02 19:05:49 +00:00
case Link : : Goto : {
const LinkGoto * go = static_cast < const LinkGoto * > ( link ) ;
d - > m_nextDocumentViewport = go - > destViewport ( ) ;
// Explanation of why d->m_nextDocumentViewport is needed:
// all openRelativeFile does is launch a signal telling we
2007-03-10 05:38:23 +00:00
// want to open another URL, the problem is that when the file is
2007-01-02 19:05:49 +00:00
// non local, the loading is done assynchronously so you can't
// do a setViewport after the if as it was because you are doing the setViewport
// on the old file and when the new arrives there is no setViewport for it and
// it does not show anything
// first open filename if link is pointing outside this document
if ( go - > isExternal ( ) & & ! d - > openRelativeFile ( go - > fileName ( ) ) )
2005-01-21 20:05:36 +00:00
{
2007-01-02 19:05:49 +00:00
kWarning ( ) < < " Link: Error opening ' " < < go - > fileName ( ) < < " '. " < < endl ;
return ;
}
else
{
// skip local links that point to nowhere (broken ones)
if ( ! d - > m_nextDocumentViewport . isValid ( ) )
return ;
2004-12-22 18:21:36 +00:00
2007-01-02 19:05:49 +00:00
setViewport ( d - > m_nextDocumentViewport , - 1 , true ) ;
d - > m_nextDocumentViewport = DocumentViewport ( ) ;
}
2004-12-22 18:21:36 +00:00
2007-01-02 19:05:49 +00:00
} break ;
2004-12-21 12:38:52 +00:00
2007-01-02 19:05:49 +00:00
case Link : : Execute : {
const LinkExecute * exe = static_cast < const LinkExecute * > ( link ) ;
QString fileName = exe - > fileName ( ) ;
if ( fileName . endsWith ( " .pdf " ) | | fileName . endsWith ( " .PDF " ) )
{
d - > openRelativeFile ( fileName ) ;
return ;
}
2004-12-21 12:38:52 +00:00
2007-01-02 19:05:49 +00:00
// Albert: the only pdf i have that has that kind of link don't define
// an application and use the fileName as the file to open
fileName = d - > giveAbsolutePath ( fileName ) ;
KMimeType : : Ptr mime = KMimeType : : findByPath ( fileName ) ;
// Check executables
if ( KRun : : isExecutableFile ( fileName , mime - > name ( ) ) )
{
// Don't have any pdf that uses this code path, just a guess on how it should work
if ( ! exe - > parameters ( ) . isEmpty ( ) )
{
fileName = d - > giveAbsolutePath ( exe - > parameters ( ) ) ;
mime = KMimeType : : findByPath ( fileName ) ;
if ( KRun : : isExecutableFile ( fileName , mime - > name ( ) ) )
{
// this case is a link pointing to an executable with a parameter
// that also is an executable, possibly a hand-crafted pdf
2007-03-30 17:46:50 +00:00
KMessageBox : : information ( widget ( ) , i18n ( " The pdf file is trying to execute an external application and for your safety okular does not allow that. " ) ) ;
2007-01-02 19:05:49 +00:00
return ;
}
}
else
{
// this case is a link pointing to an executable with no parameters
// core developers find unacceptable executing it even after asking the user
2007-03-30 17:46:50 +00:00
KMessageBox : : information ( widget ( ) , i18n ( " The pdf file is trying to execute an external application and for your safety okular does not allow that. " ) ) ;
2007-01-02 19:05:49 +00:00
return ;
}
}
2006-11-15 19:39:39 +00:00
2007-01-02 19:05:49 +00:00
KService : : Ptr ptr = KMimeTypeTrader : : self ( ) - > preferredService ( mime - > name ( ) , " Application " ) ;
if ( ptr )
{
KUrl : : List lst ;
lst . append ( fileName ) ;
KRun : : run ( * ptr , lst , 0 ) ;
}
else
2007-03-30 17:46:50 +00:00
KMessageBox : : information ( widget ( ) , i18n ( " No application found for opening file of mimetype %1. " , mime - > name ( ) ) ) ;
2007-01-02 19:05:49 +00:00
} break ;
case Link : : Action : {
const LinkAction * action = static_cast < const LinkAction * > ( link ) ;
switch ( action - > actionType ( ) )
{
case LinkAction : : PageFirst :
setViewportPage ( 0 ) ;
break ;
case LinkAction : : PagePrev :
if ( ( * d - > m_viewportIterator ) . pageNumber > 0 )
setViewportPage ( ( * d - > m_viewportIterator ) . pageNumber - 1 ) ;
break ;
case LinkAction : : PageNext :
if ( ( * d - > m_viewportIterator ) . pageNumber < ( int ) d - > m_pagesVector . count ( ) - 1 )
setViewportPage ( ( * d - > m_viewportIterator ) . pageNumber + 1 ) ;
break ;
case LinkAction : : PageLast :
setViewportPage ( d - > m_pagesVector . count ( ) - 1 ) ;
break ;
case LinkAction : : HistoryBack :
setPrevViewport ( ) ;
break ;
case LinkAction : : HistoryForward :
setNextViewport ( ) ;
break ;
case LinkAction : : Quit :
emit quit ( ) ;
break ;
case LinkAction : : Presentation :
emit linkPresentation ( ) ;
break ;
case LinkAction : : EndPresentation :
emit linkEndPresentation ( ) ;
break ;
case LinkAction : : Find :
emit linkFind ( ) ;
break ;
case LinkAction : : GoToPage :
emit linkGoToPage ( ) ;
break ;
case LinkAction : : Close :
emit close ( ) ;
break ;
}
} break ;
2006-11-15 19:39:39 +00:00
2007-01-02 19:05:49 +00:00
case Link : : Browse : {
const LinkBrowse * browse = static_cast < const LinkBrowse * > ( link ) ;
// if the url is a mailto one, invoke mailer
if ( browse - > url ( ) . startsWith ( " mailto: " , Qt : : CaseInsensitive ) )
KToolInvocation : : invokeMailer ( browse - > url ( ) ) ;
else
{
QString url = browse - > url ( ) ;
2004-12-21 12:38:52 +00:00
2007-01-02 19:05:49 +00:00
// fix for #100366, documents with relative links that are the form of http:foo.pdf
if ( url . indexOf ( " http: " ) = = 0 & & url . indexOf ( " http:// " ) = = - 1 & & url . right ( 4 ) = = " .pdf " )
{
d - > openRelativeFile ( url . mid ( 5 ) ) ;
return ;
}
2006-11-15 19:39:39 +00:00
2007-03-10 05:38:23 +00:00
// Albert: this is not a leak!
2007-01-02 19:05:49 +00:00
// TODO: find a widget to pass as second parameter
2007-03-10 05:38:23 +00:00
new KRun ( KUrl ( url ) , 0 ) ;
2007-01-02 19:05:49 +00:00
}
} break ;
2006-11-15 19:39:39 +00:00
2007-02-05 00:49:40 +00:00
case Link : : Sound : {
const LinkSound * linksound = static_cast < const LinkSound * > ( link ) ;
AudioPlayer : : instance ( ) - > playSound ( linksound - > sound ( ) , linksound ) ;
} break ;
2007-01-02 19:05:49 +00:00
case Link : : Movie :
//const LinkMovie * browse = static_cast< const LinkMovie * >( link );
// TODO this (Movie link)
break ;
}
2004-12-21 12:38:52 +00:00
}
2007-01-02 19:05:49 +00:00
void Document : : processSourceReference ( const SourceReference * ref )
2005-01-03 00:28:46 +00:00
{
2007-01-02 19:05:49 +00:00
if ( ! ref )
2005-01-28 17:21:51 +00:00
return ;
2007-01-02 19:05:49 +00:00
if ( ! QFile : : exists ( ref - > fileName ( ) ) )
2005-01-03 00:28:46 +00:00
{
2007-03-10 05:38:23 +00:00
kDebug ( OkularDebug ) < < " No such file: ' " < < ref - > fileName ( ) < < " ' " < < endl ;
2005-01-28 17:21:51 +00:00
return ;
}
2005-01-03 00:28:46 +00:00
2007-01-02 19:05:49 +00:00
static QHash < int , QString > editors ;
// init the editors table if empty (on first run, usually)
if ( editors . isEmpty ( ) )
2005-01-28 17:21:51 +00:00
{
2007-01-02 19:05:49 +00:00
editors [ Settings : : EnumExternalEditor : : Kate ] =
QLatin1String ( " kate --use --line %l --column %c " ) ;
editors [ Settings : : EnumExternalEditor : : Scite ] =
QLatin1String ( " scite %f \" -goto:%l,%c \" " ) ;
}
2005-03-13 13:14:44 +00:00
2007-02-03 23:09:40 +00:00
QHash < int , QString > : : const_iterator it = editors . constFind ( Settings : : externalEditor ( ) ) ;
2007-01-02 19:05:49 +00:00
QString p ;
if ( it ! = editors . end ( ) )
p = * it ;
else
p = Settings : : externalEditorCommand ( ) ;
// custom editor not yet configured
if ( p . isEmpty ( ) )
return ;
2005-01-28 17:21:51 +00:00
2007-01-02 19:05:49 +00:00
// replacing the placeholders
p . replace ( QLatin1String ( " %l " ) , QString : : number ( ref - > row ( ) ) ) ;
p . replace ( QLatin1String ( " %c " ) , QString : : number ( ref - > column ( ) ) ) ;
if ( p . indexOf ( QLatin1String ( " %f " ) ) > - 1 )
p . replace ( QLatin1String ( " %f " ) , ref - > fileName ( ) ) ;
else
p . append ( QLatin1String ( " " ) + ref - > fileName ( ) ) ;
2005-01-28 17:21:51 +00:00
2007-01-02 19:05:49 +00:00
// paranoic checks
if ( p . isEmpty ( ) | | p . trimmed ( ) = = ref - > fileName ( ) )
return ;
2005-03-13 13:14:44 +00:00
2007-01-02 19:05:49 +00:00
QProcess : : startDetached ( p ) ;
2005-01-03 00:28:46 +00:00
}
2007-01-02 19:05:49 +00:00
bool Document : : print ( KPrinter & printer )
2004-10-17 18:40:02 +00:00
{
2007-01-02 19:05:49 +00:00
return d - > m_generator ? d - > m_generator - > print ( printer ) : false ;
2004-10-17 18:40:02 +00:00
}
2007-01-12 23:48:29 +00:00
KPrintDialogPage * Document : : printConfigurationWidget ( ) const
2004-10-06 00:05:49 +00:00
{
2007-01-02 19:05:49 +00:00
if ( d - > m_generator )
{
PrintInterface * iface = qobject_cast < Okular : : PrintInterface * > ( d - > m_generator ) ;
2007-01-12 23:48:29 +00:00
return iface ? iface - > printConfigurationWidget ( ) : 0 ;
2007-01-02 19:05:49 +00:00
}
else
return 0 ;
2004-10-06 00:05:49 +00:00
}
2007-01-28 15:46:10 +00:00
void Document : : fillConfigDialog ( KConfigDialog * dialog )
{
if ( ! dialog )
return ;
2007-01-28 16:10:12 +00:00
// ensure that we have all the generators with settings loaded
QString constraint ( " ([X-KDE-Priority] > 0) and ( exist Library ) and ( [ X - KDE - okularHasInternalSettings ] ) " ) ;
KService : : List offers = KServiceTypeTrader : : self ( ) - > query ( " okular/Generator " , constraint ) ;
d - > loadServiceList ( offers ) ;
2007-01-28 15:46:10 +00:00
QHash < QString , GeneratorInfo > : : iterator it = d - > m_loadedGenerators . begin ( ) ;
QHash < QString , GeneratorInfo > : : iterator itEnd = d - > m_loadedGenerators . end ( ) ;
for ( ; it ! = itEnd ; + + it )
{
Okular : : ConfigInterface * iface = qobject_cast < Okular : : ConfigInterface * > ( it . value ( ) . generator ) ;
if ( iface )
iface - > addPages ( dialog ) ;
}
}
QStringList Document : : supportedMimeTypes ( ) const
{
if ( ! d - > m_supportedMimeTypes . isEmpty ( ) )
return d - > m_supportedMimeTypes ;
QString constraint ( " ([X-KDE-Priority] > 0) and ( exist Library ) " ) ;
KService : : List offers = KServiceTypeTrader : : self ( ) - > query ( " okular/Generator " , constraint ) ;
KService : : List : : ConstIterator it = offers . begin ( ) , itEnd = offers . end ( ) ;
for ( ; it ! = itEnd ; + + it )
{
KService : : Ptr service = * it ;
QStringList mimeTypes = service - > serviceTypes ( ) ;
foreach ( const QString & mimeType , mimeTypes )
if ( ! mimeType . contains ( " okular " ) )
d - > m_supportedMimeTypes . append ( mimeType ) ;
}
return d - > m_supportedMimeTypes ;
}
2007-03-07 18:15:00 +00:00
const KComponentData * Document : : componentData ( ) const
{
return d - > m_generator ? d - > m_generator - > componentData ( ) : 0 ;
}
2007-01-02 19:05:49 +00:00
void Document : : requestDone ( PixmapRequest * req )
2005-01-03 00:28:46 +00:00
{
2007-01-02 19:05:49 +00:00
# ifndef NDEBUG
2007-01-31 18:31:19 +00:00
if ( ! d - > m_generator - > canGeneratePixmap ( ) )
2007-03-10 05:38:23 +00:00
kDebug ( OkularDebug ) < < " requestDone with generator not in READY state. " < < endl ;
2007-01-02 19:05:49 +00:00
# endif
2005-01-03 00:28:46 +00:00
2007-01-02 19:05:49 +00:00
// [MEM] 1.1 find and remove a previous entry for the same page and id
QLinkedList < AllocatedPixmap * > : : iterator aIt = d - > m_allocatedPixmapsFifo . begin ( ) ;
QLinkedList < AllocatedPixmap * > : : iterator aEnd = d - > m_allocatedPixmapsFifo . end ( ) ;
for ( ; aIt ! = aEnd ; + + aIt )
if ( ( * aIt ) - > page = = req - > pageNumber ( ) & & ( * aIt ) - > id = = req - > id ( ) )
2005-01-27 17:31:07 +00:00
{
2007-01-02 19:05:49 +00:00
AllocatedPixmap * p = * aIt ;
d - > m_allocatedPixmapsFifo . erase ( aIt ) ;
d - > m_allocatedPixmapsTotalMemory - = p - > memory ;
delete p ;
break ;
}
2005-01-28 17:21:51 +00:00
2007-01-02 19:05:49 +00:00
// [MEM] 1.2 append memory allocation descriptor to the FIFO
int memoryBytes = 4 * req - > width ( ) * req - > height ( ) ;
AllocatedPixmap * memoryPage = new AllocatedPixmap ( req - > id ( ) , req - > pageNumber ( ) , memoryBytes ) ;
d - > m_allocatedPixmapsFifo . append ( memoryPage ) ;
d - > m_allocatedPixmapsTotalMemory + = memoryBytes ;
2005-01-28 17:21:51 +00:00
2007-01-02 19:05:49 +00:00
// 2. notify an observer that its pixmap changed
2007-02-03 23:09:40 +00:00
QMap < int , DocumentObserver * > : : const_iterator itObserver = d - > m_observers . constFind ( req - > id ( ) ) ;
if ( itObserver ! = d - > m_observers . constEnd ( ) )
itObserver . value ( ) - > notifyPageChanged ( req - > pageNumber ( ) , DocumentObserver : : Pixmap ) ;
2005-01-28 17:21:51 +00:00
2007-01-02 19:05:49 +00:00
// 3. delete request
delete req ;
2005-01-03 00:28:46 +00:00
2007-01-02 19:05:49 +00:00
// 4. start a new generation if some is pending
if ( ! d - > m_pixmapRequestsStack . isEmpty ( ) )
d - > sendGeneratorRequest ( ) ;
2004-12-24 10:24:10 +00:00
}
2007-01-05 17:09:47 +00:00
void Document : : slotRotation ( int r )
2005-11-04 11:59:51 +00:00
{
2007-01-05 17:09:47 +00:00
Rotation rotation = ( Rotation ) r ;
2006-10-25 15:35:53 +00:00
// tell the pages to rotate
2007-01-02 19:05:49 +00:00
QVector < Okular : : Page * > : : const_iterator pIt = d - > m_pagesVector . begin ( ) ;
QVector < Okular : : Page * > : : const_iterator pEnd = d - > m_pagesVector . end ( ) ;
2006-10-25 15:35:53 +00:00
for ( ; pIt ! = pEnd ; + + pIt )
( * pIt ) - > rotateAt ( rotation ) ;
// notify the generator that the current rotation has changed
2007-01-02 19:05:49 +00:00
d - > m_generator - > rotationChanged ( rotation , d - > m_rotation ) ;
2006-10-25 15:35:53 +00:00
// set the new rotation
2007-01-02 19:05:49 +00:00
d - > m_rotation = rotation ;
2006-10-25 15:35:53 +00:00
2007-01-02 19:05:49 +00:00
foreachObserver ( notifySetup ( d - > m_pagesVector , true ) ) ;
2006-10-25 15:35:53 +00:00
foreachObserver ( notifyContentsCleared ( DocumentObserver : : Pixmap | DocumentObserver : : Highlights | DocumentObserver : : Annotations ) ) ;
2007-03-10 05:38:23 +00:00
kDebug ( OkularDebug ) < < " Rotated: " < < r < < endl ;
2005-11-04 11:59:51 +00:00
}
2005-01-09 23:37:07 +00:00
2007-01-05 23:12:06 +00:00
void Document : : slotPageSizes ( int newsize )
- GIGANTIC 2700 line diff with LOTS OF FEATURES!
- 1. editor-like text selection, and I do mean it, its not pseudo-editor
(like the ones acroread and kviewshell have) it doesnt intersect the
selection area with words under it, no, it does a lot more, including
work on cursors and searching for the text area closest to the given
cursor
- 2. rotation support, change the orientation of the documents if
you need too :)
- 3. the kfaxview backend works beautifully, porting kviewshell backends
is damn easy ! djvu and dvi will be next!
- 4. Hardware Blending of selection rectangles! We now use XRender
instead of KImageEffect, makes a damn faster blend!
- 5. Overview mode - as seen in Kviewshell, but quite a bit extended,
the kviewshell is only one state, while we support it in both
continous and non-continous form
- BTW. I coded all those features myself, (apart from kfaxview backend library)
it is an impressive bit right? but oKular cant be run by only one person,
join in on the fun! i can introduce you into the code just mail niedakh@gmail.com
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=509871
2006-02-15 18:54:49 +00:00
{
2007-01-17 18:02:53 +00:00
if ( ! d - > m_generator - > hasFeature ( Generator : : PageSizes ) | | newsize < 0 | | newsize > = d - > m_pageSizes . count ( ) )
2007-01-05 23:12:06 +00:00
return ;
const PageSize & ps = d - > m_pageSizes . at ( newsize ) ;
// tell the pages to change size
QVector < Okular : : Page * > : : const_iterator pIt = d - > m_pagesVector . begin ( ) ;
QVector < Okular : : Page * > : : const_iterator pEnd = d - > m_pagesVector . end ( ) ;
for ( ; pIt ! = pEnd ; + + pIt )
( * pIt ) - > changeSize ( ps ) ;
// clear 'memory allocation' descriptors
QLinkedList < AllocatedPixmap * > : : const_iterator aIt = d - > m_allocatedPixmapsFifo . begin ( ) ;
QLinkedList < AllocatedPixmap * > : : const_iterator aEnd = d - > m_allocatedPixmapsFifo . end ( ) ;
for ( ; aIt ! = aEnd ; + + aIt )
delete * aIt ;
d - > m_allocatedPixmapsFifo . clear ( ) ;
d - > m_allocatedPixmapsTotalMemory = 0 ;
// notify the generator that the current page size has changed
d - > m_generator - > pageSizeChanged ( ps , d - > m_pageSize ) ;
// set the new page size
d - > m_pageSize = ps ;
foreachObserver ( notifySetup ( d - > m_pagesVector , true ) ) ;
2007-01-17 23:06:40 +00:00
foreachObserver ( notifyContentsCleared ( DocumentObserver : : Pixmap | DocumentObserver : : Highlights ) ) ;
2007-03-10 05:38:23 +00:00
kDebug ( OkularDebug ) < < " PageSize no: " < < newsize < < endl ;
- GIGANTIC 2700 line diff with LOTS OF FEATURES!
- 1. editor-like text selection, and I do mean it, its not pseudo-editor
(like the ones acroread and kviewshell have) it doesnt intersect the
selection area with words under it, no, it does a lot more, including
work on cursors and searching for the text area closest to the given
cursor
- 2. rotation support, change the orientation of the documents if
you need too :)
- 3. the kfaxview backend works beautifully, porting kviewshell backends
is damn easy ! djvu and dvi will be next!
- 4. Hardware Blending of selection rectangles! We now use XRender
instead of KImageEffect, makes a damn faster blend!
- 5. Overview mode - as seen in Kviewshell, but quite a bit extended,
the kviewshell is only one state, while we support it in both
continous and non-continous form
- BTW. I coded all those features myself, (apart from kfaxview backend library)
it is an impressive bit right? but oKular cant be run by only one person,
join in on the fun! i can introduce you into the code just mail niedakh@gmail.com
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=509871
2006-02-15 18:54:49 +00:00
}
2007-01-17 14:20:00 +00:00
2005-01-09 23:37:07 +00:00
/** DocumentViewport **/
DocumentViewport : : DocumentViewport ( int n )
: pageNumber ( n )
{
// default settings
2005-06-13 11:53:47 +00:00
rePos . enabled = false ;
rePos . normalizedX = 0.5 ;
rePos . normalizedY = 0.0 ;
rePos . pos = Center ;
2005-01-09 23:37:07 +00:00
autoFit . enabled = false ;
autoFit . width = false ;
autoFit . height = false ;
}
DocumentViewport : : DocumentViewport ( const QString & xmlDesc )
: pageNumber ( - 1 )
{
// default settings (maybe overridden below)
2005-06-13 11:53:47 +00:00
rePos . enabled = false ;
rePos . normalizedX = 0.5 ;
rePos . normalizedY = 0.0 ;
rePos . pos = Center ;
2005-01-09 23:37:07 +00:00
autoFit . enabled = false ;
autoFit . width = false ;
autoFit . height = false ;
// check for string presence
if ( xmlDesc . isEmpty ( ) )
return ;
// decode the string
bool ok ;
int field = 0 ;
QString token = xmlDesc . section ( ' ; ' , field , field ) ;
while ( ! token . isEmpty ( ) )
{
// decode the current token
if ( field = = 0 )
{
pageNumber = token . toInt ( & ok ) ;
if ( ! ok )
return ;
}
else if ( token . startsWith ( " C1 " ) )
{
2005-06-13 11:53:47 +00:00
rePos . enabled = true ;
rePos . normalizedX = token . section ( ' : ' , 1 , 1 ) . toDouble ( ) ;
rePos . normalizedY = token . section ( ' : ' , 2 , 2 ) . toDouble ( ) ;
rePos . pos = Center ;
}
else if ( token . startsWith ( " C2 " ) )
{
rePos . enabled = true ;
rePos . normalizedX = token . section ( ' : ' , 1 , 1 ) . toDouble ( ) ;
rePos . normalizedY = token . section ( ' : ' , 2 , 2 ) . toDouble ( ) ;
if ( token . section ( ' : ' , 3 , 3 ) . toInt ( ) = = 1 ) rePos . pos = Center ;
else rePos . pos = TopLeft ;
2005-01-09 23:37:07 +00:00
}
else if ( token . startsWith ( " AF1 " ) )
{
autoFit . enabled = true ;
autoFit . width = token . section ( ' : ' , 1 , 1 ) = = " T " ;
autoFit . height = token . section ( ' : ' , 2 , 2 ) = = " T " ;
}
// proceed tokenizing string
field + + ;
token = xmlDesc . section ( ' ; ' , field , field ) ;
}
2004-12-22 18:21:36 +00:00
}
2005-01-09 23:37:07 +00:00
QString DocumentViewport : : toString ( ) const
{
// start string with page number
QString s = QString : : number ( pageNumber ) ;
// if has center coordinates, save them on string
2005-06-13 11:53:47 +00:00
if ( rePos . enabled )
s + = QString ( " ;C2: " ) + QString : : number ( rePos . normalizedX ) +
' : ' + QString : : number ( rePos . normalizedY ) +
' : ' + QString : : number ( rePos . pos ) ;
2005-01-09 23:37:07 +00:00
// if has autofit enabled, save its state on string
if ( autoFit . enabled )
s + = QString ( " ;AF1: " ) + ( autoFit . width ? " T " : " F " ) +
' : ' + ( autoFit . height ? " T " : " F " ) ;
return s ;
}
2006-12-26 12:26:49 +00:00
bool DocumentViewport : : isValid ( ) const
{
return pageNumber ! = - 1 ;
}
2005-01-09 23:37:07 +00:00
bool DocumentViewport : : operator = = ( const DocumentViewport & vp ) const
{
bool equal = ( pageNumber = = vp . pageNumber ) & &
2005-06-13 11:53:47 +00:00
( rePos . enabled = = vp . rePos . enabled ) & &
2005-01-09 23:37:07 +00:00
( autoFit . enabled = = vp . autoFit . enabled ) ;
if ( ! equal )
return false ;
2005-06-13 11:53:47 +00:00
if ( rePos . enabled & &
( ( rePos . normalizedX ! = vp . rePos . normalizedX ) | |
( rePos . normalizedY ! = vp . rePos . normalizedY ) | | rePos . pos ! = vp . rePos . pos ) )
2005-01-09 23:37:07 +00:00
return false ;
if ( autoFit . enabled & &
( ( autoFit . width ! = vp . autoFit . width ) | |
( autoFit . height ! = vp . autoFit . height ) ) )
return false ;
return true ;
}
2005-01-02 22:37:52 +00:00
/** DocumentInfo **/
DocumentInfo : : DocumentInfo ( )
: QDomDocument ( " DocumentInformation " )
{
QDomElement docElement = createElement ( " DocumentInfo " ) ;
appendChild ( docElement ) ;
}
void DocumentInfo : : set ( const QString & key , const QString & value ,
const QString & title )
{
QDomElement docElement = documentElement ( ) ;
QDomElement element ;
// check whether key already exists
QDomNodeList list = docElement . elementsByTagName ( key ) ;
if ( list . count ( ) > 0 )
element = list . item ( 0 ) . toElement ( ) ;
else
element = createElement ( key ) ;
element . setAttribute ( " value " , value ) ;
element . setAttribute ( " title " , title ) ;
if ( list . count ( ) = = 0 )
docElement . appendChild ( element ) ;
}
QString DocumentInfo : : get ( const QString & key ) const
{
QDomElement docElement = documentElement ( ) ;
QDomElement element ;
// check whether key already exists
QDomNodeList list = docElement . elementsByTagName ( key ) ;
if ( list . count ( ) > 0 )
return list . item ( 0 ) . toElement ( ) . attribute ( " value " ) ;
else
return QString ( ) ;
}
2005-01-09 23:37:07 +00:00
2005-01-03 15:51:05 +00:00
/** DocumentSynopsis **/
DocumentSynopsis : : DocumentSynopsis ( )
: QDomDocument ( " DocumentSynopsis " )
{
// void implementation, only subclassed for naming
}
2006-09-20 11:44:58 +00:00
DocumentSynopsis : : DocumentSynopsis ( const QDomDocument & document )
: QDomDocument ( document )
{
}
2005-06-13 15:46:23 +00:00
/** DocumentFonts **/
DocumentFonts : : DocumentFonts ( )
: QDomDocument ( " DocumentFonts " )
{
// void implementation, only subclassed for naming
}
2006-05-28 16:54:54 +00:00
/** EmbeddedFile **/
EmbeddedFile : : EmbeddedFile ( )
{
}
EmbeddedFile : : ~ EmbeddedFile ( )
{
}
2007-01-02 19:05:49 +00:00
VisiblePageRect : : VisiblePageRect ( int page , const NormalizedRect & rectangle )
: pageNumber ( page ) , rect ( rectangle )
{
}
2004-12-22 18:21:36 +00:00
# include "document.moc"