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 > *
2007-08-13 22:25:27 +00:00
* Copyright ( C ) 2004 - 2007 by Albert Astals Cid < aacid @ kde . org > *
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"
2007-09-14 15:17:36 +00:00
# include "document_p.h"
2007-04-19 18:30:20 +00:00
2007-10-31 19:44:35 +00:00
# ifdef Q_OS_WIN
# define _WIN32_WINNT 0x0500
# include <windows.h>
# endif
2004-10-06 00:05:49 +00:00
// qt/kde/system includes
2006-09-21 08:45:36 +00:00
# include <QtCore/QtAlgorithms>
2007-05-21 19:51:30 +00:00
# include <QtCore/QDir>
2006-09-21 08:45:36 +00:00
# include <QtCore/QFile>
# include <QtCore/QFileInfo>
# 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-08-13 22:25:27 +00:00
# include <QtGui/QLabel>
2007-10-15 23:01:27 +00:00
# include <QtGui/QPrinter>
2007-11-26 21:43:54 +00:00
# include <QtGui/QPrintDialog>
2006-09-21 08:45:36 +00:00
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>
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-07-17 18:10:25 +00:00
# include "annotations.h"
# include "annotations_p.h"
2007-02-05 00:49:40 +00:00
# include "audioplayer.h"
2007-07-10 18:24:18 +00:00
# include "audioplayer_p.h"
2006-12-27 16:04:49 +00:00
# include "bookmarkmanager.h"
2007-07-10 22:52:25 +00:00
# include "chooseenginedialog_p.h"
2007-07-31 10:19:48 +00:00
# include "debug_p.h"
2007-04-20 17:26:04 +00:00
# include "generator_p.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 ;
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 ;
2007-07-15 16:10:48 +00:00
qulonglong memory ;
2004-12-21 12:38:52 +00:00
// public constructor: initialize data
2007-07-15 16:10:48 +00:00
AllocatedPixmap ( int i , int p , qulonglong 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 ;
2007-08-13 22:25:27 +00:00
QSet < 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 ;
2007-09-07 13:13:50 +00:00
bool cachedViewportMove : 1 ;
bool cachedNoDialogs : 1 ;
2005-02-02 18:18:26 +00:00
QColor cachedColor ;
2005-02-01 18:26:56 +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-07-12 20:04:56 +00:00
# define foreachObserverD( cmd ) {\
QMap < int , DocumentObserver * > : : const_iterator it = m_observers . begin ( ) , end = m_observers . end ( ) ; \
for ( ; it ! = end ; + + it ) { ( * it ) - > cmd ; } }
2007-07-23 17:12:20 +00:00
# define OKULAR_HISTORY_MAXSTEPS 100
# define OKULAR_HISTORY_SAVEDSTEPS 10
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
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-07-15 16:10:48 +00:00
void DocumentPrivate : : cleanupPixmapMemory ( qulonglong /*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
2007-10-31 19:44:35 +00:00
qulonglong clipValue = ~ 0U ;
qulonglong memoryToFree = ~ 0U ;
2007-01-02 19:05:49 +00:00
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-07-15 16:10:48 +00:00
qulonglong DocumentPrivate : : getTotalMemory ( )
2004-09-08 12:41:14 +00:00
{
2007-07-15 16:10:48 +00:00
static qulonglong cachedValue = 0 ;
2007-01-02 19:05:49 +00:00
if ( cachedValue )
return cachedValue ;
2005-01-03 00:28:46 +00:00
2007-07-15 16:51:23 +00:00
# if defined(Q_OS_LINUX)
2007-01-02 19:05:49 +00:00
// 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-07-15 16:43:24 +00:00
# elif defined(Q_OS_WIN)
MEMORYSTATUSEX stat ;
GlobalMemoryStatusEx ( & stat ) ;
2007-09-15 14:05:08 +00:00
return ( cachedValue = stat . ullTotalPhys ) ;
2007-01-02 19:05:49 +00:00
# endif
return ( cachedValue = 134217728 ) ;
}
2005-01-18 16:43:36 +00:00
2007-07-15 16:10:48 +00:00
qulonglong DocumentPrivate : : getFreeMemory ( )
2007-01-02 19:05:49 +00:00
{
static QTime lastUpdate = QTime : : currentTime ( ) ;
2007-07-15 16:10:48 +00:00
static qulonglong 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-07-15 16:51:23 +00:00
# if defined(Q_OS_LINUX)
2007-01-02 19:05:49 +00:00
// 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.
2007-07-15 16:10:48 +00:00
qulonglong memoryFree = 0 ;
2007-01-02 19:05:49 +00:00
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 ) ) ;
2007-07-15 16:43:24 +00:00
# elif defined(Q_OS_WIN)
2007-07-15 16:47:55 +00:00
MEMORYSTATUSEX stat ;
2007-07-15 16:43:24 +00:00
2007-07-15 16:47:55 +00:00
GlobalMemoryStatusEx ( & stat ) ;
2007-07-15 16:43:24 +00:00
2007-12-11 13:52:55 +00:00
lastUpdate = QTime : : currentTime ( ) ;
2007-08-14 13:03:38 +00:00
return ( cachedValue = stat . ullAvailPhys ) ;
2007-01-02 19:05:49 +00:00
# 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-07-31 10:19:48 +00:00
//kDebug(OkularDebug).nospace() << "Using '" << d->m_xmlFileName << "' as document info file.";
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-07-31 10:19:48 +00:00
kDebug ( OkularDebug ) < < " Can't load XML pair! Check for broken xml. " ;
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 ;
2007-09-03 17:53:45 +00:00
KUrl documentUrl ( root . attribute ( " url " ) ) ;
2007-01-02 19:05:49 +00:00
// 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
// 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 ( ) ) ;
}
2007-11-01 16:15:34 +00:00
else if ( infoElement . tagName ( ) = = " rotation " )
{
QString str = infoElement . text ( ) ;
bool ok = true ;
int newrotation = ! str . isEmpty ( ) ? ( str . toInt ( & ok ) % 4 ) : 0 ;
if ( ok & & newrotation ! = 0 )
{
setRotationInternal ( newrotation , false ) ;
}
}
2007-01-02 19:05:49 +00:00
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-05-24 22:52:29 +00:00
QString DocumentPrivate : : giveAbsolutePath ( const QString & fileName ) const
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-05-21 19:51:30 +00:00
if ( ! QDir : : isRelativePath ( fileName ) )
return fileName ;
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-07-31 10:19:48 +00:00
kDebug ( OkularDebug ) . nospace ( ) < < " openDocument: ' " < < absFileName < < " ' " ;
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-12-02 20:57:24 +00:00
Generator * DocumentPrivate : : loadGeneratorLibrary ( const KService : : Ptr & service )
2007-01-28 15:46:10 +00:00
{
2007-12-02 20:57:24 +00:00
KPluginFactory * factory = KPluginLoader ( service - > library ( ) ) . factory ( ) ;
if ( ! factory )
2007-01-28 15:46:10 +00:00
{
2007-12-02 20:57:24 +00:00
kWarning ( OkularDebug ) . nospace ( ) < < " Invalid plugin factory for " < < service - > library ( ) < < " ! " ;
2007-01-28 15:46:10 +00:00
return 0 ;
}
2007-12-02 20:57:24 +00:00
Generator * generator = factory - > create < Okular : : Generator > ( 0 ) ;
GeneratorInfo info ( factory - > componentData ( ) ) ;
2007-01-28 15:46:10 +00:00
info . generator = generator ;
2007-12-02 20:57:24 +00:00
if ( info . data . isValid ( ) & & info . data . aboutData ( ) )
info . catalogName = info . data . aboutData ( ) - > catalogName ( ) ;
m_loadedGenerators . insert ( service - > 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-11-25 12:08:37 +00:00
if ( ! m_loadedGenerators . isEmpty ( ) & & genIt ! = m_loadedGenerators . end ( ) )
2007-01-28 15:46:10 +00:00
continue ;
2007-12-02 20:57:24 +00:00
Generator * g = loadGeneratorLibrary ( offers . at ( i ) ) ;
2007-01-28 15:46:10 +00:00
( 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 ;
}
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-11-25 12:49:30 +00:00
ConfigInterface * DocumentPrivate : : generatorConfig ( GeneratorInfo & info )
{
if ( info . configChecked )
return info . config ;
info . config = qobject_cast < Okular : : ConfigInterface * > ( info . generator ) ;
info . configChecked = true ;
return info . config ;
}
2007-04-14 19:44:07 +00:00
void DocumentPrivate : : saveDocumentInfo ( ) const
2006-05-28 16:54:54 +00:00
{
2008-01-01 16:22:29 +00:00
if ( m_xmlFileName . isEmpty ( ) )
2007-01-02 19:05:49 +00:00
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 " ) ;
2007-09-03 17:53:45 +00:00
root . setAttribute ( " url " , m_url . pathOrUrl ( ) ) ;
2007-01-02 19:05:49 +00:00
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 ) ;
2007-11-01 16:15:34 +00:00
// create rotation node
if ( m_rotation ! = Rotation0 )
{
QDomElement rotationNode = doc . createElement ( " rotation " ) ;
generalInfo . appendChild ( rotationNode ) ;
rotationNode . appendChild ( doc . createTextNode ( QString : : number ( ( int ) m_rotation ) ) ) ;
}
2007-07-23 17:12:20 +00:00
// <general info><history> ... </history> save history up to OKULAR_HISTORY_SAVEDSTEPS viewports
2007-01-02 19:05:49 +00:00
QLinkedList < DocumentViewport > : : const_iterator backIterator = m_viewportIterator ;
if ( backIterator ! = m_viewportHistory . end ( ) )
{
2007-07-23 17:12:20 +00:00
// go back up to OKULAR_HISTORY_SAVEDSTEPS steps from the current viewportIterator
int backSteps = OKULAR_HISTORY_SAVEDSTEPS ;
2007-01-02 19:05:49 +00:00
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 ;
2007-05-12 21:40:38 +00:00
m_pixmapRequestsMutex . lock ( ) ;
2007-01-02 19:05:49 +00:00
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 )
{
2007-11-25 12:18:10 +00:00
kWarning ( OkularDebug ) . nospace ( ) < < " Running out of memory on page " < < r - > pageNumber ( )
2007-07-31 10:19:48 +00:00
< < " ( " < < r - > width ( ) < < " x " < < r - > height ( ) < < " px); " ;
2007-11-25 12:18:10 +00:00
kWarning ( OkularDebug ) < < " this message will be reported only once. " ;
2007-01-02 19:05:49 +00:00
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 )
2007-05-12 21:40:38 +00:00
{
m_pixmapRequestsMutex . unlock ( ) ;
2007-01-02 19:05:49 +00:00
return ;
2007-05-12 21:40:38 +00:00
}
- 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
2007-07-15 16:10:48 +00:00
qulonglong pixmapBytes = 4 * request - > width ( ) * request - > height ( ) ;
2007-01-02 19:05:49 +00:00
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-07-31 10:19:48 +00:00
kDebug ( OkularDebug ) . nospace ( ) < < " sending request id= " < < request - > id ( ) < < " " < < request - > width ( ) < < " x " < < request - > height ( ) < < " @ " < < request - > pageNumber ( ) < < " async == " < < request - > asynchronous ( ) ;
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-12-04 21:36:32 +00:00
request - > d - > swap ( ) ;
2006-10-25 15:35:53 +00:00
2007-05-12 21:40:38 +00:00
// we always have to unlock _before_ the generatePixmap() because
// a sync generation would end with requestDone() -> deadlock, and
// we can not really know if the generator can do async requests
m_pixmapRequestsMutex . unlock ( ) ;
2007-01-31 18:31:19 +00:00
m_generator - > generatePixmap ( request ) ;
2007-01-02 19:05:49 +00:00
}
else
2007-05-12 21:40:38 +00:00
{
m_pixmapRequestsMutex . unlock ( ) ;
2007-01-02 19:05:49 +00:00
// pino (7/4/2006): set the polling interval from 10 to 30
QTimer : : singleShot ( 30 , m_parent , SLOT ( sendGeneratorRequest ( ) ) ) ;
2007-05-12 21:40:38 +00:00
}
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-07-07 20:35:01 +00:00
void DocumentPrivate : : fontReadingProgress ( int page )
{
emit m_parent - > fontReadingProgress ( page ) ;
2007-12-28 17:06:43 +00:00
if ( page > = ( int ) m_parent - > pages ( ) - 1 )
2007-07-07 20:35:01 +00:00
{
emit m_parent - > fontReadingEnded ( ) ;
m_fontThread = 0 ;
m_fontsCached = true ;
}
}
void DocumentPrivate : : fontReadingGotFont ( const Okular : : FontInfo & font )
{
// TODO try to avoid duplicate fonts
m_fontsCache . append ( font ) ;
emit m_parent - > gotFont ( font ) ;
}
2007-07-12 20:04:56 +00:00
void DocumentPrivate : : slotGeneratorConfigChanged ( const QString & )
{
if ( ! m_generator )
return ;
// reparse generator config and if something changed clear Pages
bool configchanged = false ;
2007-11-25 12:49:30 +00:00
QHash < QString , GeneratorInfo > : : iterator it = m_loadedGenerators . begin ( ) , itEnd = m_loadedGenerators . end ( ) ;
2007-07-12 20:04:56 +00:00
for ( ; it ! = itEnd ; + + it )
{
2007-11-25 12:49:30 +00:00
Okular : : ConfigInterface * iface = generatorConfig ( it . value ( ) ) ;
2007-07-12 20:04:56 +00:00
if ( iface )
{
bool it_changed = iface - > reparseConfig ( ) ;
if ( it_changed & & ( m_generator = = it . value ( ) . generator ) )
configchanged = true ;
}
}
if ( configchanged )
{
// invalidate pixmaps
QVector < Page * > : : const_iterator it = m_pagesVector . begin ( ) , end = m_pagesVector . end ( ) ;
for ( ; it ! = end ; + + it ) {
( * it ) - > deletePixmaps ( ) ;
}
// [MEM] remove allocation descriptors
QLinkedList < AllocatedPixmap * > : : const_iterator aIt = m_allocatedPixmapsFifo . begin ( ) ;
QLinkedList < AllocatedPixmap * > : : const_iterator aEnd = m_allocatedPixmapsFifo . end ( ) ;
for ( ; aIt ! = aEnd ; + + aIt )
delete * aIt ;
m_allocatedPixmapsFifo . clear ( ) ;
m_allocatedPixmapsTotalMemory = 0 ;
// send reload signals to observers
foreachObserverD ( notifyContentsCleared ( DocumentObserver : : Pixmap ) ) ;
}
// free memory if in 'low' profile
if ( Settings : : memoryLevel ( ) = = Settings : : EnumMemoryLevel : : Low & &
! m_allocatedPixmapsFifo . isEmpty ( ) & & ! m_pagesVector . isEmpty ( ) )
cleanupPixmapMemory ( ) ;
}
2007-08-13 22:25:27 +00:00
void DocumentPrivate : : doContinueNextMatchSearch ( void * pagesToNotifySet , void * theMatch , int currentPage , int searchID , const QString & text , int theCaseSensitivity , bool moveViewport , const QColor & color , bool noDialogs , int donePages )
{
RegularAreaRect * match = static_cast < RegularAreaRect * > ( theMatch ) ;
Qt : : CaseSensitivity caseSensitivity = static_cast < Qt : : CaseSensitivity > ( theCaseSensitivity ) ;
QSet < int > * pagesToNotify = static_cast < QSet < int > * > ( pagesToNotifySet ) ;
if ( m_searchCancelled & & ! match )
{
// if the user cancelled but he just got a match, give him the match!
QApplication : : restoreOverrideCursor ( ) ;
2007-08-23 22:16:37 +00:00
emit m_parent - > searchFinished ( searchID , Document : : SearchCancelled ) ;
2007-08-13 22:25:27 +00:00
delete pagesToNotify ;
return ;
}
// if no match found, loop through the whole doc, starting from currentPage
if ( ! match )
{
int pageCount = m_pagesVector . count ( ) ;
if ( donePages < pageCount )
{
bool doContinue = true ;
if ( currentPage > = pageCount )
{
if ( noDialogs | | KMessageBox : : questionYesNo ( m_parent - > widget ( ) , i18n ( " End of document reached. \n Continue from the beginning? " ) , QString ( ) , KStandardGuiItem : : cont ( ) , KStandardGuiItem : : cancel ( ) ) = = KMessageBox : : Yes )
currentPage = 0 ;
else
doContinue = false ;
}
if ( doContinue )
{
// get page
Page * page = m_pagesVector [ currentPage ] ;
// request search page if needed
if ( ! page - > hasTextPage ( ) )
m_parent - > requestTextPage ( page - > number ( ) ) ;
// if found a match on the current page, end the loop
match = page - > findText ( searchID , text , FromTop , caseSensitivity ) ;
if ( ! match ) currentPage + + ;
QMetaObject : : invokeMethod ( m_parent , " doContinueNextMatchSearch " , Qt : : QueuedConnection , Q_ARG ( void * , pagesToNotifySet ) , Q_ARG ( void * , match ) , Q_ARG ( int , currentPage ) , Q_ARG ( int , searchID ) , Q_ARG ( QString , text ) , Q_ARG ( int , caseSensitivity ) , Q_ARG ( bool , moveViewport ) , Q_ARG ( QColor , color ) , Q_ARG ( bool , noDialogs ) , Q_ARG ( int , donePages + 1 ) ) ;
return ;
}
}
}
// reset cursor to previous shape
QApplication : : restoreOverrideCursor ( ) ;
bool foundAMatch = false ;
// if a match has been found..
if ( match )
{
// update the RunningSearch structure adding this match..
RunningSearch * s = m_searches [ searchID ] ;
foundAMatch = true ;
s - > continueOnPage = currentPage ;
s - > continueOnMatch = * match ;
s - > highlightedPages . insert ( currentPage ) ;
// ..add highlight to the page..
m_pagesVector [ currentPage ] - > d - > setHighlight ( searchID , match , color ) ;
// ..queue page for notifying changes..
pagesToNotify - > insert ( 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 ;
m_parent - > setViewport ( searchViewport , - 1 , true ) ;
}
delete match ;
}
else if ( ! noDialogs )
KMessageBox : : information ( m_parent - > widget ( ) , i18n ( " No matches found for '%1'. " , text ) ) ;
// notify observers about highlights changes
foreach ( int pageNumber , * pagesToNotify )
foreach ( DocumentObserver * observer , m_observers )
observer - > notifyPageChanged ( pageNumber , DocumentObserver : : Highlights ) ;
2007-08-23 22:16:37 +00:00
if ( foundAMatch ) emit m_parent - > searchFinished ( searchID , Document : : MatchFound ) ;
else emit m_parent - > searchFinished ( searchID , Document : : NoMatchFound ) ;
2007-08-13 22:25:27 +00:00
delete pagesToNotify ;
}
void DocumentPrivate : : doContinueAllDocumentSearch ( void * pagesToNotifySet , void * pageMatchesMap , int currentPage , int searchID , const QString & text , int theCaseSensitivity , const QColor & color )
{
QMap < Page * , QVector < RegularAreaRect * > > * pageMatches = static_cast < QMap < Page * , QVector < RegularAreaRect * > > * > ( pageMatchesMap ) ;
Qt : : CaseSensitivity caseSensitivity = static_cast < Qt : : CaseSensitivity > ( theCaseSensitivity ) ;
QSet < int > * pagesToNotify = static_cast < QSet < int > * > ( pagesToNotifySet ) ;
if ( m_searchCancelled )
{
typedef QVector < RegularAreaRect * > MatchesVector ;
QApplication : : restoreOverrideCursor ( ) ;
2007-08-23 22:16:37 +00:00
emit m_parent - > searchFinished ( searchID , Document : : SearchCancelled ) ;
2007-08-13 22:25:27 +00:00
foreach ( const MatchesVector & mv , * pageMatches ) qDeleteAll ( mv ) ;
delete pageMatches ;
delete pagesToNotify ;
return ;
}
if ( currentPage < m_pagesVector . count ( ) )
{
// get page (from the first to the last)
Page * page = m_pagesVector . at ( currentPage ) ;
int pageNumber = page - > number ( ) ; // redundant? is it == currentPage ?
// request search page if needed
if ( ! page - > hasTextPage ( ) )
m_parent - > requestTextPage ( pageNumber ) ;
// loop on a page adding highlights for all found items
RegularAreaRect * lastMatch = 0 ;
while ( 1 )
{
if ( lastMatch )
lastMatch = page - > findText ( searchID , text , NextResult , caseSensitivity , lastMatch ) ;
else
lastMatch = page - > findText ( searchID , text , FromTop , caseSensitivity ) ;
if ( ! lastMatch )
break ;
// add highligh rect to the matches map
( * pageMatches ) [ page ] . append ( lastMatch ) ;
}
delete lastMatch ;
QMetaObject : : invokeMethod ( m_parent , " doContinueAllDocumentSearch " , Qt : : QueuedConnection , Q_ARG ( void * , pagesToNotifySet ) , Q_ARG ( void * , pageMatches ) , Q_ARG ( int , currentPage + 1 ) , Q_ARG ( int , searchID ) , Q_ARG ( QString , text ) , Q_ARG ( int , caseSensitivity ) , Q_ARG ( QColor , color ) ) ;
}
else
{
// reset cursor to previous shape
QApplication : : restoreOverrideCursor ( ) ;
RunningSearch * s = m_searches [ searchID ] ;
bool foundAMatch = pageMatches - > count ( ) ! = 0 ;
QMap < Page * , QVector < RegularAreaRect * > > : : const_iterator it , itEnd ;
it = pageMatches - > begin ( ) ;
itEnd = pageMatches - > end ( ) ;
for ( ; it ! = itEnd ; + + it )
{
foreach ( RegularAreaRect * match , it . value ( ) )
{
it . key ( ) - > d - > setHighlight ( searchID , match , color ) ;
delete match ;
}
s - > highlightedPages . insert ( it . key ( ) - > number ( ) ) ;
pagesToNotify - > insert ( it . key ( ) - > number ( ) ) ;
}
foreach ( DocumentObserver * observer , m_observers )
2007-09-09 10:50:36 +00:00
observer - > notifySetup ( m_pagesVector , 0 ) ;
2007-08-13 22:25:27 +00:00
// notify observers about highlights changes
foreach ( int pageNumber , * pagesToNotify )
foreach ( DocumentObserver * observer , m_observers )
observer - > notifyPageChanged ( pageNumber , DocumentObserver : : Highlights ) ;
2007-08-23 22:16:37 +00:00
if ( foundAMatch ) emit m_parent - > searchFinished ( searchID , Document : : MatchFound ) ;
else emit m_parent - > searchFinished ( searchID , Document : : NoMatchFound ) ;
2007-08-13 22:25:27 +00:00
delete pageMatches ;
delete pagesToNotify ;
}
}
void DocumentPrivate : : doContinueGooglesDocumentSearch ( void * pagesToNotifySet , void * pageMatchesMap , int currentPage , int searchID , const QString & text , int theCaseSensitivity , const QColor & color , bool matchAll )
{
typedef QPair < RegularAreaRect * , QColor > MatchColor ;
QMap < Page * , QVector < MatchColor > > * pageMatches = static_cast < QMap < Page * , QVector < MatchColor > > * > ( pageMatchesMap ) ;
Qt : : CaseSensitivity caseSensitivity = static_cast < Qt : : CaseSensitivity > ( theCaseSensitivity ) ;
QSet < int > * pagesToNotify = static_cast < QSet < int > * > ( pagesToNotifySet ) ;
if ( m_searchCancelled )
{
typedef QVector < MatchColor > MatchesVector ;
QApplication : : restoreOverrideCursor ( ) ;
2007-08-23 22:16:37 +00:00
emit m_parent - > searchFinished ( searchID , Document : : SearchCancelled ) ;
2007-08-13 22:25:27 +00:00
foreach ( const MatchesVector & mv , * pageMatches )
{
foreach ( const MatchColor & mc , mv ) delete mc . first ;
}
delete pageMatches ;
delete pagesToNotify ;
return ;
}
QStringList words = text . split ( " " , QString : : SkipEmptyParts ) ;
const int wordCount = words . count ( ) ;
const int hueStep = ( wordCount > 1 ) ? ( 60 / ( wordCount - 1 ) ) : 60 ;
int baseHue , baseSat , baseVal ;
color . getHsv ( & baseHue , & baseSat , & baseVal ) ;
if ( currentPage < m_pagesVector . count ( ) )
{
// get page (from the first to the last)
Page * page = m_pagesVector . at ( currentPage ) ;
int pageNumber = page - > number ( ) ; // redundant? is it == currentPage ?
// request search page if needed
if ( ! page - > hasTextPage ( ) )
m_parent - > requestTextPage ( pageNumber ) ;
// loop on a page adding highlights for all found items
bool allMatched = wordCount > 0 ,
anyMatched = false ;
for ( int w = 0 ; w < wordCount ; w + + )
{
const 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 )
lastMatch = page - > findText ( searchID , word , NextResult , caseSensitivity , lastMatch ) ;
else
lastMatch = page - > findText ( searchID , word , FromTop , caseSensitivity ) ;
if ( ! lastMatch )
break ;
// add highligh rect to the matches map
( * pageMatches ) [ page ] . append ( MatchColor ( lastMatch , wordColor ) ) ;
wordMatched = true ;
}
allMatched = allMatched & & wordMatched ;
anyMatched = anyMatched | | wordMatched ;
}
// if not all words are present in page, remove partial highlights
if ( ! allMatched & & matchAll )
{
QVector < MatchColor > & matches = ( * pageMatches ) [ page ] ;
foreach ( const MatchColor & mc , matches ) delete mc . first ;
pageMatches - > remove ( page ) ;
}
QMetaObject : : invokeMethod ( m_parent , " doContinueGooglesDocumentSearch " , Qt : : QueuedConnection , Q_ARG ( void * , pagesToNotifySet ) , Q_ARG ( void * , pageMatches ) , Q_ARG ( int , currentPage + 1 ) , Q_ARG ( int , searchID ) , Q_ARG ( QString , text ) , Q_ARG ( int , caseSensitivity ) , Q_ARG ( QColor , color ) , Q_ARG ( bool , matchAll ) ) ;
}
else
{
// reset cursor to previous shape
QApplication : : restoreOverrideCursor ( ) ;
RunningSearch * s = m_searches [ searchID ] ;
bool foundAMatch = pageMatches - > count ( ) ! = 0 ;
QMap < Page * , QVector < MatchColor > > : : const_iterator it , itEnd ;
it = pageMatches - > begin ( ) ;
itEnd = pageMatches - > end ( ) ;
for ( ; it ! = itEnd ; + + it )
{
foreach ( const MatchColor & mc , it . value ( ) )
{
it . key ( ) - > d - > setHighlight ( searchID , mc . first , mc . second ) ;
delete mc . first ;
}
s - > highlightedPages . insert ( it . key ( ) - > number ( ) ) ;
pagesToNotify - > insert ( it . key ( ) - > number ( ) ) ;
}
// send page lists to update observers (since some filter on bookmarks)
foreach ( DocumentObserver * observer , m_observers )
2007-09-09 10:50:36 +00:00
observer - > notifySetup ( m_pagesVector , 0 ) ;
2007-08-13 22:25:27 +00:00
// notify observers about highlights changes
foreach ( int pageNumber , * pagesToNotify )
foreach ( DocumentObserver * observer , m_observers )
observer - > notifyPageChanged ( pageNumber , DocumentObserver : : Highlights ) ;
2007-08-23 22:16:37 +00:00
if ( foundAMatch ) emit m_parent - > searchFinished ( searchID , Document : : MatchFound ) ;
else emit m_parent - > searchFinished ( searchID , Document : : NoMatchFound ) ;
2007-08-13 22:25:27 +00:00
delete pageMatches ;
delete pagesToNotify ;
}
}
2007-09-14 22:16:00 +00:00
QVariant DocumentPrivate : : documentMetaData ( const QString & key , const QVariant & option ) const
{
if ( key = = QLatin1String ( " PaperColor " ) )
{
bool giveDefault = option . toBool ( ) ;
// load paper color from Settings, or use the default color (white)
// if we were told to do so
QColor color ;
if ( ( Settings : : renderMode ( ) = = Settings : : EnumRenderMode : : Paper )
& & Settings : : changeColors ( ) )
{
color = Settings : : paperColor ( ) ;
}
else if ( giveDefault )
{
color = Qt : : white ;
}
return color ;
}
else if ( key = = QLatin1String ( " ZoomFactor " ) )
{
return Settings : : zoomFactor ( ) ;
}
2007-12-16 23:36:12 +00:00
else if ( key = = QLatin1String ( " TextAntialias " ) )
{
// TODO: add a configuration
// TODO: eventually read the KDE configuration
return true ;
}
else if ( key = = QLatin1String ( " GraphicsAntialias " ) )
{
// TODO: add a configuration
return true ;
}
2007-09-14 22:16:00 +00:00
return QVariant ( ) ;
}
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-10-28 18:31:33 +00:00
d - > m_bookmarkManager = new BookmarkManager ( d ) ;
2007-10-04 21:41:19 +00:00
d - > m_viewportIterator = d - > m_viewportHistory . insert ( d - > m_viewportHistory . end ( ) , DocumentViewport ( ) ) ;
2007-03-24 10:47:22 +00:00
connect ( PageController : : self ( ) , SIGNAL ( rotationFinished ( int ) ) ,
this , SLOT ( rotationFinished ( int ) ) ) ;
2007-07-07 20:35:01 +00:00
qRegisterMetaType < Okular : : FontInfo > ( ) ;
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 ;
2007-09-30 10:49:38 +00:00
qint64 document_size = - 1 ;
2007-01-12 22:49:14 +00:00
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 ;
2008-01-01 16:22:29 +00:00
if ( url . isLocalFile ( ) )
{
2007-01-12 22:49:14 +00:00
QString fn = docFile . contains ( ' / ' ) ? docFile . section ( ' / ' , - 1 , - 1 ) : docFile ;
2007-07-10 23:49:37 +00:00
document_size = fileReadTest . size ( ) ;
fn = QString : : number ( document_size ) + ' . ' + fn + " .xml " ;
2007-01-12 22:49:14 +00:00
fileReadTest . close ( ) ;
2007-04-21 23:07:44 +00:00
QString newokular = " okular/docdata/ " + fn ;
QString newokularfile = KStandardDirs : : locateLocal ( " data " , newokular ) ;
2007-09-10 17:20:58 +00:00
if ( ! QFile : : exists ( newokularfile ) )
2007-04-21 23:07:44 +00:00
{
2007-09-10 17:20:58 +00:00
QString oldkpdf = " kpdf/ " + fn ;
QString oldkpdffile = KStandardDirs : : locateLocal ( " data " , oldkpdf ) ;
if ( QFile : : exists ( oldkpdffile ) )
{
// ### copy or move?
if ( ! QFile : : copy ( oldkpdffile , newokularfile ) )
return false ;
}
2007-04-21 23:07:44 +00:00
}
d - > m_xmlFileName = newokularfile ;
2008-01-01 16:22:29 +00:00
}
2007-01-12 22:49:14 +00:00
}
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-07-10 23:49:37 +00:00
document_size = filedata . size ( ) ;
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-11-25 12:18:10 +00:00
kWarning ( OkularDebug ) . nospace ( ) < < " No plugin for mimetype ' " < < mime - > name ( ) < < " '. " ;
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 ( ) ;
}
2007-05-24 22:52:29 +00:00
ChooseEngineDialog choose ( list , mime , widget ( ) ) ;
2007-01-28 15:46:10 +00:00
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-07-14 13:47:11 +00:00
QString catalogName ;
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-07-14 13:47:11 +00:00
catalogName = genIt . value ( ) . catalogName ;
2007-01-02 19:05:49 +00:00
}
else
{
2007-12-02 20:57:24 +00:00
d - > m_generator = d - > loadGeneratorLibrary ( offers . at ( hRank ) ) ;
2007-01-28 15:46:10 +00:00
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 ( ) ) ;
2007-07-14 13:47:11 +00:00
catalogName = genIt . value ( ) . catalogName ;
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-07-14 13:47:11 +00:00
if ( ! catalogName . isEmpty ( ) )
KGlobal : : locale ( ) - > insertCatalog ( catalogName ) ;
2007-03-11 22:35:14 +00:00
2007-09-14 15:29:16 +00:00
d - > m_generator - > d_func ( ) - > m_document = d ;
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-07-14 13:47:11 +00:00
if ( ! catalogName . isEmpty ( ) )
KGlobal : : locale ( ) - > removeCatalog ( catalogName ) ;
2007-03-11 22:35:14 +00:00
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
2007-09-09 10:50:36 +00:00
foreachObserver ( notifySetup ( d - > m_pagesVector , DocumentObserver : : DocumentChanged ) ) ;
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-07-10 18:24:18 +00:00
AudioPlayer : : instance ( ) - > d - > m_currentDocument = isstdin ? KUrl ( ) : d - > m_url ;
2007-07-10 23:49:37 +00:00
d - > m_docSize = document_size ;
2007-07-10 18:24:18 +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-08-28 23:17:00 +00:00
KXMLGUIClient * Document : : guiClient ( )
2006-08-08 15:31:13 +00:00
{
2007-01-02 19:05:49 +00:00
if ( d - > m_generator )
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 )
2007-08-28 23:17:00 +00:00
return iface - > guiClient ( ) ;
2006-09-14 18:42:28 +00:00
}
2007-08-28 23:17:00 +00:00
return 0 ;
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-10-03 15:03:49 +00:00
// check if there's anything to close...
if ( ! d - > m_generator )
return ;
2007-07-08 21:22:37 +00:00
if ( d - > m_fontThread )
{
disconnect ( d - > m_fontThread , 0 , this , 0 ) ;
d - > m_fontThread - > stopExtraction ( ) ;
d - > m_fontThread - > wait ( ) ;
d - > m_fontThread = 0 ;
}
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 - > saveDocumentInfo ( ) ;
2007-07-04 09:28:31 +00:00
d - > m_generator - > closeDocument ( ) ;
2007-01-02 19:05:49 +00:00
}
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-28 15:46:10 +00:00
// disconnect the generator from this document ...
2007-09-14 13:31:55 +00:00
d - > m_generator - > d_func ( ) - > m_document = 0 ;
2007-01-28 15:46:10 +00:00
// .. 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 ( ) ) ;
2007-11-25 12:49:30 +00:00
if ( ! genIt . value ( ) . catalogName . isEmpty ( ) & & ! genIt . value ( ) . config )
2007-07-14 13:47:11 +00:00
KGlobal : : locale ( ) - > removeCatalog ( genIt . value ( ) . catalogName ) ;
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-07-10 23:49:37 +00:00
d - > m_docSize = - 1 ;
2007-03-10 20:51:50 +00:00
d - > m_exportCached = false ;
d - > m_exportFormats . clear ( ) ;
d - > m_exportToText = ExportFormat ( ) ;
2007-07-07 20:35:01 +00:00
d - > m_fontsCached = false ;
d - > m_fontsCache . clear ( ) ;
2007-05-24 22:52:29 +00:00
d - > m_rotation = Rotation0 ;
2007-01-02 19:05:49 +00:00
// remove requests left in queue
2007-05-12 21:40:38 +00:00
d - > m_pixmapRequestsMutex . lock ( ) ;
2007-01-02 19:05:49 +00:00
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 ( ) ;
2007-05-12 21:40:38 +00:00
d - > m_pixmapRequestsMutex . unlock ( ) ;
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)
2007-09-09 10:50:36 +00:00
foreachObserver ( notifySetup ( QVector < Page * > ( ) , DocumentObserver : : DocumentChanged ) ) ;
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 ( ) ;
2007-07-10 18:24:18 +00:00
AudioPlayer : : instance ( ) - > d - > m_currentDocument = KUrl ( ) ;
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-09-09 10:50:36 +00:00
pObserver - > notifySetup ( d - > m_pagesVector , DocumentObserver : : DocumentChanged ) ;
2007-01-02 19:05:49 +00:00
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 ( ) ;
}
// [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
{
2007-05-02 22:56:51 +00:00
return parent ( ) ? static_cast < QWidget * > ( parent ( ) ) : 0 ;
2007-03-30 17:46:50 +00:00
}
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-07-10 23:49:37 +00:00
const DocumentInfo * infoConst = d - > m_generator - > generateDocumentInfo ( ) ;
if ( ! infoConst )
return 0 ;
DocumentInfo * info = const_cast < DocumentInfo * > ( infoConst ) ;
2007-01-02 19:05:49 +00:00
QString pagesSize = d - > pagesSizeString ( ) ;
2007-07-10 23:49:37 +00:00
if ( d - > m_docSize ! = - 1 )
{
QString sizeString = KGlobal : : locale ( ) - > formatByteSize ( d - > m_docSize ) ;
info - > set ( " documentSize " , sizeString , i18n ( " File Size " ) ) ;
}
2007-01-02 19:05:49 +00:00
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-07-07 20:35:01 +00:00
void Document : : startFontReading ( )
2007-01-02 19:05:49 +00:00
{
2007-07-07 20:35:01 +00:00
if ( ! d - > m_generator | | ! d - > m_generator - > hasFeature ( Generator : : FontInfo ) | | d - > m_fontThread )
return ;
if ( d - > m_fontsCached )
{
// in case we have cached fonts, simulate a reading
// this way the API is the same, and users no need to care about the
// internal caching
for ( int i = 0 ; i < d - > m_fontsCache . count ( ) ; + + i )
{
emit gotFont ( d - > m_fontsCache . at ( i ) ) ;
emit fontReadingProgress ( i / pages ( ) ) ;
}
emit fontReadingEnded ( ) ;
return ;
}
d - > m_fontThread = new FontExtractionThread ( d - > m_generator , pages ( ) ) ;
connect ( d - > m_fontThread , SIGNAL ( gotFont ( const Okular : : FontInfo & ) ) , this , SLOT ( fontReadingGotFont ( const Okular : : FontInfo & ) ) ) ;
connect ( d - > m_fontThread , SIGNAL ( progress ( int ) ) , this , SLOT ( fontReadingProgress ( int ) ) ) ;
d - > m_fontThread - > startExtraction ( /*d->m_generator->hasFeature( Generator::Threaded )*/ true ) ;
}
2007-07-08 21:22:37 +00:00
void Document : : stopFontReading ( )
{
if ( ! d - > m_fontThread )
return ;
disconnect ( d - > m_fontThread , 0 , this , 0 ) ;
d - > m_fontThread - > stopExtraction ( ) ;
d - > m_fontThread = 0 ;
d - > m_fontsCache . clear ( ) ;
}
2007-07-07 20:35:01 +00:00
bool Document : : canProvideFontInformation ( ) const
{
return d - > m_generator ? d - > m_generator - > hasFeature ( Generator : : FontInfo ) : false ;
2007-01-02 19:05:49 +00:00
}
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-05-24 22:52:29 +00:00
if ( requests . isEmpty ( ) )
return ;
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 ( ) ;
2007-05-12 21:40:38 +00:00
d - > m_pixmapRequestsMutex . lock ( ) ;
2007-01-02 19:05:49 +00:00
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-07-31 10:19:48 +00:00
kDebug ( OkularDebug ) . nospace ( ) < < " request id= " < < request - > id ( ) < < " " < < request - > width ( ) < < " x " < < request - > height ( ) < < " @ " < < request - > pageNumber ( ) ;
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-09-30 21:44:31 +00:00
request - > d - > mPage = 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 ( ) )
2007-09-30 21:44:31 +00:00
request - > d - > mPriority = 0 ;
2004-10-06 00:05:49 +00:00
2007-01-02 19:05:49 +00:00
if ( request - > asynchronous ( ) & & threadingDisabled )
2007-09-30 21:44:31 +00:00
request - > d - > mAsynchronous = 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 ) ;
}
}
2007-05-12 21:40:38 +00:00
d - > m_pixmapRequestsMutex . unlock ( ) ;
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-08-13 22:25:27 +00:00
void Document : : requestTextPage ( uint page )
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-08-13 22:25:27 +00:00
d - > m_generator - > generateTextPage ( kp ) ;
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-07-17 18:10:25 +00:00
// the annotation belongs already to a page
if ( annotation - > d_ptr - > m_page )
return ;
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-05-26 19:25:18 +00:00
void Document : : removePageAnnotations ( int page , const QList < Annotation * > & annotations )
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-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 )
2007-05-05 18:07:34 +00:00
kp - > d - > setTextSelections ( rect , color ) ;
2007-01-02 19:05:49 +00:00
else
2007-09-03 23:47:12 +00:00
kp - > d - > deleteTextSelections ( ) ;
2007-01-02 19:05:49 +00:00
// 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-07-31 10:19:48 +00:00
// kDebug(OkularDebug) << "setViewport with the same viewport.";
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
2007-07-23 17:12:20 +00:00
if ( d - > m_viewportHistory . count ( ) > = OKULAR_HISTORY_MAXSTEPS )
2007-01-02 19:05:49 +00:00
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-07-08 14:25:08 +00:00
void Document : : setZoom ( int factor , int excludeId )
{
// 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 ) - > notifyZoom ( factor ) ;
}
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 ;
}
2007-08-13 22:25:27 +00:00
void Document : : searchText ( int searchID , const QString & text , bool fromStart , Qt : : CaseSensitivity caseSensitivity ,
2007-01-02 19:05:49 +00:00
SearchType type , bool moveViewport , const QColor & color , bool noDialogs )
{
2007-08-13 22:25:27 +00:00
d - > m_searchCancelled = false ;
2007-01-02 19:05:49 +00:00
// 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-08-13 22:25:27 +00:00
{
2007-08-23 22:16:37 +00:00
emit searchFinished ( searchID , NoMatchFound ) ;
2007-08-13 22:25:27 +00:00
return ;
}
if ( ! noDialogs )
{
KDialog * searchDialog = new KDialog ( widget ( ) ) ;
searchDialog - > setCaption ( i18n ( " Search in progress... " ) ) ;
searchDialog - > setButtons ( KDialog : : Cancel ) ;
QLabel * searchLabel = new QLabel ( i18n ( " Searching for %1 " , text ) , searchDialog ) ;
searchDialog - > setMainWidget ( searchLabel ) ;
QTimer : : singleShot ( 500 , searchDialog , SLOT ( show ( ) ) ) ;
2007-08-23 22:16:37 +00:00
connect ( this , SIGNAL ( searchFinished ( int , Okular : : Document : : SearchStatus ) ) , searchDialog , SLOT ( deleteLater ( ) ) ) ;
2007-08-13 22:25:27 +00:00
connect ( searchDialog , SIGNAL ( finished ( ) ) , this , SLOT ( cancelSearch ( ) ) ) ;
}
2007-01-02 19:05:49 +00:00
// 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
2007-08-13 22:25:27 +00:00
QSet < int > * pagesToNotify = new QSet < int > ;
2007-01-02 19:05:49 +00:00
// remove highlights from pages and queue them for notifying changes
2007-08-13 22:25:27 +00:00
* pagesToNotify + = s - > highlightedPages ;
foreach ( int pageNumber , s - > highlightedPages )
d - > m_pagesVector . at ( pageNumber ) - > d - > deleteHighlights ( searchID ) ;
2007-01-02 19:05:49 +00:00
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
{
2007-08-13 22:25:27 +00:00
QMap < Page * , QVector < RegularAreaRect * > > * pageMatches = new QMap < Page * , QVector < RegularAreaRect * > > ;
2007-01-02 19:05:49 +00:00
2007-08-13 22:25:27 +00:00
// search and highlight 'text' (as a solid phrase) on all pages
QMetaObject : : invokeMethod ( this , " doContinueAllDocumentSearch " , Qt : : QueuedConnection , Q_ARG ( void * , pagesToNotify ) , Q_ARG ( void * , pageMatches ) , Q_ARG ( int , 0 ) , Q_ARG ( int , searchID ) , Q_ARG ( QString , text ) , Q_ARG ( int , caseSensitivity ) , Q_ARG ( QColor , color ) ) ;
2007-01-02 19:05:49 +00:00
}
// 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-08-13 22:25:27 +00:00
QMetaObject : : invokeMethod ( this , " doContinueNextMatchSearch " , Qt : : QueuedConnection , Q_ARG ( void * , pagesToNotify ) , Q_ARG ( void * , match ) , Q_ARG ( int , currentPage ) , Q_ARG ( int , searchID ) , Q_ARG ( QString , text ) , Q_ARG ( int , caseSensitivity ) , Q_ARG ( bool , moveViewport ) , Q_ARG ( QColor , color ) , Q_ARG ( bool , noDialogs ) , Q_ARG ( int , 1 ) ) ;
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 )
{
bool matchAll = type = = GoogleAll ;
2007-08-13 22:25:27 +00:00
QMap < Page * , QVector < QPair < RegularAreaRect * , QColor > > > * pageMatches = new QMap < Page * , QVector < QPair < RegularAreaRect * , QColor > > > ;
2007-01-02 19:05:49 +00:00
2007-08-13 22:25:27 +00:00
// search and highlight every word in 'text' on all pages
QMetaObject : : invokeMethod ( this , " doContinueGooglesDocumentSearch " , Qt : : QueuedConnection , Q_ARG ( void * , pagesToNotify ) , Q_ARG ( void * , pageMatches ) , Q_ARG ( int , 0 ) , Q_ARG ( int , searchID ) , Q_ARG ( QString , text ) , Q_ARG ( int , caseSensitivity ) , Q_ARG ( QColor , color ) , Q_ARG ( bool , matchAll ) ) ;
2007-01-02 19:05:49 +00:00
}
}
2007-08-13 22:25:27 +00:00
void Document : : continueSearch ( int searchID )
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 * > : : const_iterator it = d - > m_searches . constFind ( searchID ) ;
if ( it = = d - > m_searches . constEnd ( ) )
2007-08-13 22:25:27 +00:00
{
2007-08-23 22:16:37 +00:00
emit searchFinished ( searchID , NoMatchFound ) ;
2007-08-13 22:25:27 +00:00
return ;
}
2007-01-02 19:05:49 +00:00
// start search with cached parameters from last search by searchID
2007-02-12 14:15:51 +00:00
RunningSearch * p = * it ;
2007-08-13 22:25:27 +00:00
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
2007-08-13 22:25:27 +00:00
foreach ( int pageNumber , s - > highlightedPages )
- 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-08-13 22:25:27 +00:00
d - > m_pagesVector . at ( pageNumber ) - > d - > deleteHighlights ( searchID ) ;
2007-01-02 19:05:49 +00:00
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)
2007-09-09 10:50:36 +00:00
foreachObserver ( notifySetup ( d - > m_pagesVector , 0 ) ) ;
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 ;
}
2007-08-13 22:25:27 +00:00
void Document : : cancelSearch ( )
{
d - > m_searchCancelled = true ;
}
2007-01-02 19:05:49 +00:00
2007-10-28 18:31:33 +00:00
BookmarkManager * Document : : bookmarkManager ( ) const
2007-01-02 19:05:49 +00:00
{
return d - > m_bookmarkManager ;
}
2004-12-22 18:21:36 +00:00
2007-11-26 21:43:54 +00:00
QList < int > Document : : bookmarkedPageList ( ) const
{
QList < int > list ;
uint docPages = pages ( ) ;
//pages are 0-indexed internally, but 1-indexed externally
for ( uint i = 0 ; i < docPages ; i + + )
{
if ( bookmarkManager ( ) - > isBookmarked ( i ) )
{
list < < i + 1 ;
}
}
return list ;
}
QString Document : : bookmarkedPageRange ( ) const
{
// Code formerly in Part::slotPrint()
// range detecting
QString range ;
uint docPages = pages ( ) ;
int startId = - 1 ;
int endId = - 1 ;
for ( uint i = 0 ; i < docPages ; + + i )
{
if ( bookmarkManager ( ) - > isBookmarked ( i ) )
{
if ( startId < 0 )
startId = i ;
if ( endId < 0 )
endId = startId ;
else
+ + endId ;
}
else if ( startId > = 0 & & endId > = 0 )
{
if ( ! range . isEmpty ( ) )
range + = ' , ' ;
if ( endId - startId > 0 )
range + = QString ( " %1-%2 " ) . arg ( startId + 1 ) . arg ( endId + 1 ) ;
else
range + = QString : : number ( startId + 1 ) ;
startId = - 1 ;
endId = - 1 ;
}
}
if ( startId > = 0 & & endId > = 0 )
{
if ( ! range . isEmpty ( ) )
range + = ' , ' ;
if ( endId - startId > 0 )
range + = QString ( " %1-%2 " ) . arg ( startId + 1 ) . arg ( endId + 1 ) ;
else
range + = QString : : number ( startId + 1 ) ;
}
return range ;
}
2007-04-20 12:49:17 +00:00
void Document : : processAction ( const Action * action )
2007-01-02 19:05:49 +00:00
{
2007-04-20 12:49:17 +00:00
if ( ! action )
2007-01-02 19:05:49 +00:00
return ;
2004-12-24 10:24:10 +00:00
2007-04-20 12:49:17 +00:00
switch ( action - > actionType ( ) )
2004-12-22 18:21:36 +00:00
{
2007-04-20 12:37:12 +00:00
case Action : : Goto : {
2007-05-02 22:50:27 +00:00
const GotoAction * go = static_cast < const GotoAction * > ( action ) ;
2007-01-02 19:05:49 +00:00
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-11-25 12:18:10 +00:00
kWarning ( OkularDebug ) . nospace ( ) < < " Action: Error opening ' " < < go - > fileName ( ) < < " '. " ;
2007-01-02 19:05:49 +00:00
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-04-20 12:37:12 +00:00
case Action : : Execute : {
2007-05-02 22:50:27 +00:00
const ExecuteAction * exe = static_cast < const ExecuteAction * > ( action ) ;
2007-01-02 19:05:49 +00:00
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-05-02 23:06:38 +00:00
KMessageBox : : information ( widget ( ) , i18n ( " The document 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-05-02 23:06:38 +00:00
KMessageBox : : information ( widget ( ) , i18n ( " The document 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 ;
2007-05-02 22:50:27 +00:00
case Action : : DocAction : {
const DocumentAction * docaction = static_cast < const DocumentAction * > ( action ) ;
2007-04-20 19:32:09 +00:00
switch ( docaction - > documentActionType ( ) )
2007-01-02 19:05:49 +00:00
{
2007-05-02 22:50:27 +00:00
case DocumentAction : : PageFirst :
2007-01-02 19:05:49 +00:00
setViewportPage ( 0 ) ;
break ;
2007-05-02 22:50:27 +00:00
case DocumentAction : : PagePrev :
2007-01-02 19:05:49 +00:00
if ( ( * d - > m_viewportIterator ) . pageNumber > 0 )
setViewportPage ( ( * d - > m_viewportIterator ) . pageNumber - 1 ) ;
break ;
2007-05-02 22:50:27 +00:00
case DocumentAction : : PageNext :
2007-01-02 19:05:49 +00:00
if ( ( * d - > m_viewportIterator ) . pageNumber < ( int ) d - > m_pagesVector . count ( ) - 1 )
setViewportPage ( ( * d - > m_viewportIterator ) . pageNumber + 1 ) ;
break ;
2007-05-02 22:50:27 +00:00
case DocumentAction : : PageLast :
2007-01-02 19:05:49 +00:00
setViewportPage ( d - > m_pagesVector . count ( ) - 1 ) ;
break ;
2007-05-02 22:50:27 +00:00
case DocumentAction : : HistoryBack :
2007-01-02 19:05:49 +00:00
setPrevViewport ( ) ;
break ;
2007-05-02 22:50:27 +00:00
case DocumentAction : : HistoryForward :
2007-01-02 19:05:49 +00:00
setNextViewport ( ) ;
break ;
2007-05-02 22:50:27 +00:00
case DocumentAction : : Quit :
2007-01-02 19:05:49 +00:00
emit quit ( ) ;
break ;
2007-05-02 22:50:27 +00:00
case DocumentAction : : Presentation :
2007-01-02 19:05:49 +00:00
emit linkPresentation ( ) ;
break ;
2007-05-02 22:50:27 +00:00
case DocumentAction : : EndPresentation :
2007-01-02 19:05:49 +00:00
emit linkEndPresentation ( ) ;
break ;
2007-05-02 22:50:27 +00:00
case DocumentAction : : Find :
2007-01-02 19:05:49 +00:00
emit linkFind ( ) ;
break ;
2007-05-02 22:50:27 +00:00
case DocumentAction : : GoToPage :
2007-01-02 19:05:49 +00:00
emit linkGoToPage ( ) ;
break ;
2007-05-02 22:50:27 +00:00
case DocumentAction : : Close :
2007-01-02 19:05:49 +00:00
emit close ( ) ;
break ;
}
} break ;
2006-11-15 19:39:39 +00:00
2007-04-20 12:37:12 +00:00
case Action : : Browse : {
2007-05-02 22:50:27 +00:00
const BrowseAction * browse = static_cast < const BrowseAction * > ( action ) ;
2007-01-02 19:05:49 +00:00
// 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-05-02 22:56:51 +00:00
new KRun ( KUrl ( url ) , widget ( ) ) ;
2007-01-02 19:05:49 +00:00
}
} break ;
2006-11-15 19:39:39 +00:00
2007-04-20 12:37:12 +00:00
case Action : : Sound : {
2007-05-02 22:50:27 +00:00
const SoundAction * linksound = static_cast < const SoundAction * > ( action ) ;
2007-02-05 00:49:40 +00:00
AudioPlayer : : instance ( ) - > playSound ( linksound - > sound ( ) , linksound ) ;
} break ;
2007-04-20 12:37:12 +00:00
case Action : : Movie :
2007-05-02 22:50:27 +00:00
//const MovieAction * movie = static_cast< const MovieAction * >( action );
2007-04-20 12:49:17 +00:00
// TODO this (Movie action)
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
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-07-31 10:19:48 +00:00
kDebug ( OkularDebug ) . nospace ( ) < < " No such file: ' " < < ref - > fileName ( ) < < " ' " ;
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-11-26 21:43:54 +00:00
Document : : PrintingType Document : : printingSupport ( ) const
{
if ( d - > m_generator )
{
if ( d - > m_generator - > hasFeature ( Generator : : PrintNative ) )
{
return NativePrinting ;
}
# ifndef Q_OS_WIN
if ( d - > m_generator - > hasFeature ( Generator : : PrintPostscript ) )
{
return PostscriptPrinting ;
}
# endif
}
return NoPrinting ;
}
bool Document : : supportsPrintToFile ( ) const
{
return d - > m_generator ? d - > m_generator - > hasFeature ( Generator : : PrintToFile ) : false ;
}
2007-10-15 23:01:27 +00:00
bool Document : : print ( QPrinter & 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-10-15 23:01:27 +00:00
QWidget * 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
2007-07-12 20:04:56 +00:00
bool pagesAdded = false ;
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 )
{
2007-11-25 12:49:30 +00:00
Okular : : ConfigInterface * iface = d - > generatorConfig ( it . value ( ) ) ;
2007-01-28 15:46:10 +00:00
if ( iface )
2007-07-12 17:52:14 +00:00
{
2007-01-28 15:46:10 +00:00
iface - > addPages ( dialog ) ;
2007-07-12 20:04:56 +00:00
pagesAdded = true ;
2007-11-25 12:49:30 +00:00
if ( ! it . value ( ) . catalogName . isEmpty ( ) )
KGlobal : : locale ( ) - > insertCatalog ( it . value ( ) . catalogName ) ;
2007-07-12 17:52:14 +00:00
}
2007-01-28 15:46:10 +00:00
}
2007-07-12 20:04:56 +00:00
if ( pagesAdded )
{
connect ( dialog , SIGNAL ( settingsChanged ( const QString & ) ) ,
this , SLOT ( slotGeneratorConfigChanged ( const QString & ) ) ) ;
}
2007-01-28 15:46:10 +00:00
}
2007-07-12 17:52:14 +00:00
int Document : : configurableGenerators ( ) const
{
QString constraint ( " ([X-KDE-Priority] > 0) and ( exist Library ) and ( [ X - KDE - okularHasInternalSettings ] ) " ) ;
KService : : List offers = KServiceTypeTrader : : self ( ) - > query ( " okular/Generator " , constraint ) ;
2007-07-30 22:29:41 +00:00
return offers . count ( ) ;
2007-07-12 17:52:14 +00:00
}
2007-01-28 15:46:10 +00:00
QStringList Document : : supportedMimeTypes ( ) const
{
if ( ! d - > m_supportedMimeTypes . isEmpty ( ) )
return d - > m_supportedMimeTypes ;
2008-01-02 00:37:51 +00:00
QString constraint ( " (Library == 'okularpart') " ) ;
QLatin1String basePartService ( " KParts/ReadOnlyPart " ) ;
KService : : List offers = KServiceTypeTrader : : self ( ) - > query ( basePartService , constraint ) ;
2007-01-28 15:46:10 +00:00
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 )
2008-01-02 00:37:51 +00:00
if ( mimeType ! = basePartService )
2007-01-28 15:46:10 +00:00
d - > m_supportedMimeTypes . append ( mimeType ) ;
}
return d - > m_supportedMimeTypes ;
}
2007-03-07 18:15:00 +00:00
const KComponentData * Document : : componentData ( ) const
{
2007-11-24 18:07:59 +00:00
if ( ! d - > m_generator )
return 0 ;
2007-12-02 20:57:24 +00:00
QHash < QString , GeneratorInfo > : : const_iterator genIt = d - > m_loadedGenerators . constFind ( d - > m_generatorName ) ;
Q_ASSERT ( genIt ! = d - > m_loadedGenerators . constEnd ( ) ) ;
const KComponentData * kcd = & genIt . value ( ) . data ;
2007-11-24 18:07:59 +00:00
// empty about data
2007-12-02 20:57:24 +00:00
if ( kcd - > isValid ( ) & & kcd - > aboutData ( ) & & kcd - > aboutData ( ) - > programName ( ) . isEmpty ( ) )
2007-11-24 18:07:59 +00:00
return 0 ;
return kcd ;
2007-03-07 18:15:00 +00:00
}
2007-09-14 15:29:16 +00:00
void DocumentPrivate : : requestDone ( PixmapRequest * req )
2005-01-03 00:28:46 +00:00
{
2007-09-14 15:29:16 +00:00
if ( ! m_generator | | ! req )
2007-05-24 22:52:29 +00:00
return ;
2007-01-02 19:05:49 +00:00
# ifndef NDEBUG
2007-09-14 15:29:16 +00:00
if ( ! m_generator - > canGeneratePixmap ( ) )
2007-07-31 10:19:48 +00:00
kDebug ( OkularDebug ) < < " requestDone with generator not in READY state. " ;
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
2007-09-14 15:29:16 +00:00
QLinkedList < AllocatedPixmap * > : : iterator aIt = m_allocatedPixmapsFifo . begin ( ) ;
QLinkedList < AllocatedPixmap * > : : iterator aEnd = m_allocatedPixmapsFifo . end ( ) ;
2007-01-02 19:05:49 +00:00
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 ;
2007-09-14 15:29:16 +00:00
m_allocatedPixmapsFifo . erase ( aIt ) ;
m_allocatedPixmapsTotalMemory - = p - > memory ;
2007-01-02 19:05:49 +00:00
delete p ;
break ;
}
2005-01-28 17:21:51 +00:00
2007-09-14 15:29:16 +00:00
QMap < int , DocumentObserver * > : : const_iterator itObserver = m_observers . constFind ( req - > id ( ) ) ;
if ( itObserver ! = m_observers . constEnd ( ) )
2007-05-17 16:52:44 +00:00
{
// [MEM] 1.2 append memory allocation descriptor to the FIFO
2007-07-15 16:10:48 +00:00
qulonglong memoryBytes = 4 * req - > width ( ) * req - > height ( ) ;
2007-05-17 16:52:44 +00:00
AllocatedPixmap * memoryPage = new AllocatedPixmap ( req - > id ( ) , req - > pageNumber ( ) , memoryBytes ) ;
2007-09-14 15:29:16 +00:00
m_allocatedPixmapsFifo . append ( memoryPage ) ;
m_allocatedPixmapsTotalMemory + = memoryBytes ;
2007-05-17 16:52:44 +00:00
// 2. notify an observer that its pixmap changed
2007-02-03 23:09:40 +00:00
itObserver . value ( ) - > notifyPageChanged ( req - > pageNumber ( ) , DocumentObserver : : Pixmap ) ;
2007-05-17 16:52:44 +00:00
}
# ifndef NDEBUG
else
2007-11-25 12:18:10 +00:00
kWarning ( OkularDebug ) < < " Receiving a done request for the defunct observer " < < req - > id ( ) ;
2007-05-17 16:52:44 +00:00
# endif
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
2007-09-14 15:29:16 +00:00
m_pixmapRequestsMutex . lock ( ) ;
bool hasPixmaps = ! m_pixmapRequestsStack . isEmpty ( ) ;
m_pixmapRequestsMutex . unlock ( ) ;
2007-05-12 21:40:38 +00:00
if ( hasPixmaps )
2007-09-14 15:29:16 +00:00
sendGeneratorRequest ( ) ;
2004-12-24 10:24:10 +00:00
}
2007-05-01 23:09:45 +00:00
void Document : : setRotation ( int r )
2007-11-01 16:15:34 +00:00
{
d - > setRotationInternal ( r , true ) ;
}
void DocumentPrivate : : setRotationInternal ( int r , bool notify )
2005-11-04 11:59:51 +00:00
{
2007-01-05 17:09:47 +00:00
Rotation rotation = ( Rotation ) r ;
2007-11-01 16:15:34 +00:00
if ( ! m_generator | | ( m_rotation = = rotation ) )
2007-07-17 18:13:50 +00:00
return ;
2006-10-25 15:35:53 +00:00
// tell the pages to rotate
2007-11-01 16:15:34 +00:00
QVector < Okular : : Page * > : : const_iterator pIt = m_pagesVector . begin ( ) ;
QVector < Okular : : Page * > : : const_iterator pEnd = m_pagesVector . end ( ) ;
2006-10-25 15:35:53 +00:00
for ( ; pIt ! = pEnd ; + + pIt )
2007-05-01 23:36:57 +00:00
( * pIt ) - > d - > rotateAt ( rotation ) ;
2007-11-01 16:15:34 +00:00
if ( notify )
{
// notify the generator that the current rotation has changed
m_generator - > rotationChanged ( rotation , m_rotation ) ;
}
2006-10-25 15:35:53 +00:00
// set the new rotation
2007-11-01 16:15:34 +00:00
m_rotation = rotation ;
2006-10-25 15:35:53 +00:00
2007-11-01 16:15:34 +00:00
if ( notify )
{
foreachObserverD ( notifySetup ( m_pagesVector , DocumentObserver : : NewLayoutForPages ) ) ;
foreachObserverD ( notifyContentsCleared ( DocumentObserver : : Pixmap | DocumentObserver : : Highlights | DocumentObserver : : Annotations ) ) ;
}
2007-07-31 10:19:48 +00:00
kDebug ( OkularDebug ) < < " Rotated: " < < r ;
2005-11-04 11:59:51 +00:00
}
2005-01-09 23:37:07 +00:00
2007-05-01 23:21:29 +00:00
void Document : : setPageSize ( const PageSize & size )
- 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-05-24 22:52:29 +00:00
if ( ! d - > m_generator | | ! d - > m_generator - > hasFeature ( Generator : : PageSizes ) )
return ;
if ( d - > m_pageSizes . isEmpty ( ) )
d - > m_pageSizes = d - > m_generator - > pageSizes ( ) ;
2007-05-01 23:21:29 +00:00
int sizeid = d - > m_pageSizes . indexOf ( size ) ;
2007-05-24 22:52:29 +00:00
if ( sizeid = = - 1 )
2007-01-05 23:12:06 +00:00
return ;
// 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 )
2007-05-01 23:36:57 +00:00
( * pIt ) - > d - > changeSize ( size ) ;
2007-01-05 23:12:06 +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 ( ) ;
d - > m_allocatedPixmapsTotalMemory = 0 ;
// notify the generator that the current page size has changed
2007-05-01 23:21:29 +00:00
d - > m_generator - > pageSizeChanged ( size , d - > m_pageSize ) ;
2007-01-05 23:12:06 +00:00
// set the new page size
2007-05-01 23:21:29 +00:00
d - > m_pageSize = size ;
2007-01-05 23:12:06 +00:00
2007-09-09 10:50:36 +00:00
foreachObserver ( notifySetup ( d - > m_pagesVector , DocumentObserver : : NewLayoutForPages ) ) ;
2007-01-17 23:06:40 +00:00
foreachObserver ( notifyContentsCleared ( DocumentObserver : : Pixmap | DocumentObserver : : Highlights ) ) ;
2007-07-31 10:19:48 +00:00
kDebug ( OkularDebug ) < < " New PageSize id: " < < sizeid ;
- 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
{
2007-05-02 18:21:15 +00:00
return pageNumber > = 0 ;
2006-12-26 12:26:49 +00:00
}
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 ) ;
}
2007-05-13 12:54:46 +00:00
void DocumentInfo : : set ( enum Key key , const QString & value )
{
switch ( key ) {
case Title :
set ( " title " , value , i18n ( " Title " ) ) ;
break ;
case Subject :
set ( " subject " , value , i18n ( " Subject " ) ) ;
break ;
case Description :
set ( " description " , value , i18n ( " Description " ) ) ;
break ;
case Author :
set ( " author " , value , i18n ( " Author " ) ) ;
break ;
case Creator :
set ( " creator " , value , i18n ( " Creator " ) ) ;
break ;
case Producer :
set ( " producer " , value , i18n ( " Producer " ) ) ;
break ;
case Copyright :
set ( " copyright " , value , i18n ( " Copyright " ) ) ;
break ;
case Pages :
set ( " pages " , value , i18n ( " Pages " ) ) ;
break ;
case CreationDate :
set ( " creationDate " , value , i18n ( " Created " ) ) ;
break ;
case ModificationDate :
set ( " modificationDate " , value , i18n ( " Modified " ) ) ;
break ;
case MimeType :
set ( " mimeType " , value , i18n ( " Mime Type " ) ) ;
break ;
case Category :
set ( " category " , value , i18n ( " Category " ) ) ;
break ;
case Keywords :
set ( " keywords " , value , i18n ( " Keywords " ) ) ;
break ;
default :
2007-11-25 12:18:10 +00:00
kWarning ( OkularDebug ) < < " Invalid key passed " ;
2007-05-13 12:54:46 +00:00
break ;
}
}
2005-01-02 22:37:52 +00:00
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
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"