Commit 6dd95c9e authored by Enrico Ros's avatar Enrico Ros

Viewport MOD 1. Implemented the DocumentViewport class, owned by Document.

A const reference may be asked. When set all DocumentObservers will be
notified so they can update their gfx if needed. Converted TOC, Links
to the new usage. DocumentViewport can be saved/restored to/from QString
so it can be asked as metadata and saved on document's XML. When loading
a document the viewport is restored exactly where it was when the document
was closed. More fixes with Viewport class. Swapped groupboxes in Perform
dialog. Changed members naming in DocumentObservers and inherited classes.
PageView and ThumbnailsList now linked.

Still regressions / TODOs about the Viewport thing.

svn path=/trunk/kdegraphics/kpdf/; revision=377066
parent 3e317aab
...@@ -86,6 +86,7 @@ More items (first items will enter 'In progress list' first): ...@@ -86,6 +86,7 @@ More items (first items will enter 'In progress list' first):
-> presentation: add some gfx tools (like a red pencil) -> presentation: add some gfx tools (like a red pencil)
-> presentation: save a flag (to the xml) to open a pdf in presentation mode -> presentation: save a flag (to the xml) to open a pdf in presentation mode
-> presentation: link following (difficult due to pagerects related to pageview pixmap only) -> presentation: link following (difficult due to pagerects related to pageview pixmap only)
-> presentation: wheel not visible on black. gradient appreciated on lighter backgrounds.
-> investigate 'Splash' lack of smoothness at low resolutions (see lines in thumbnails) -> investigate 'Splash' lack of smoothness at low resolutions (see lines in thumbnails)
-> add search on the toc widget (a prune on type lineedit like in thumbnails widget) -> add search on the toc widget (a prune on type lineedit like in thumbnails widget)
-> goto 'logical' page (usually differs from pdf's page) (req. by Luca Burrelli) -> goto 'logical' page (usually differs from pdf's page) (req. by Luca Burrelli)
......
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
<property name="margin"> <property name="margin">
<number>0</number> <number>0</number>
</property> </property>
<widget class="QButtonGroup"> <widget class="QGroupBox">
<property name="name"> <property name="name">
<cstring>kcfg_MemoryLevel</cstring> <cstring>groupBox1</cstring>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy> <sizepolicy>
...@@ -32,63 +32,41 @@ ...@@ -32,63 +32,41 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="title"> <property name="title">
<string>Memory Usage</string> <string>CPU Usage</string>
</property> </property>
<grid> <hbox>
<property name="name"> <property name="name">
<cstring>unnamed</cstring> <cstring>unnamed</cstring>
</property> </property>
<widget class="QLabel" row="1" column="0" rowspan="1" colspan="2"> <widget class="QLayoutWidget">
<property name="name">
<cstring>descLabel</cstring>
</property>
<property name="text">
<string>...</string>
</property>
<property name="textFormat">
<enum>PlainText</enum>
</property>
<property name="alignment">
<set>WordBreak|AlignVCenter</set>
</property>
</widget>
<widget class="QLayoutWidget" row="0" column="0">
<property name="name"> <property name="name">
<cstring>layout5</cstring> <cstring>layout9</cstring>
</property> </property>
<vbox> <vbox>
<property name="name"> <property name="name">
<cstring>unnamed</cstring> <cstring>unnamed</cstring>
</property> </property>
<widget class="QRadioButton"> <widget class="QCheckBox">
<property name="name">
<cstring>lowRadio</cstring>
</property>
<property name="text">
<string>&amp;Low</string>
</property>
</widget>
<widget class="QRadioButton">
<property name="name"> <property name="name">
<cstring>normalRadio</cstring> <cstring>kcfg_DisableCompositing</cstring>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Normal (default)</string> <string>Disable &amp;transparency effects</string>
</property> </property>
</widget> </widget>
<widget class="QRadioButton"> <widget class="QCheckBox">
<property name="name"> <property name="name">
<cstring>aggressiveRadio</cstring> <cstring>kcfg_DisableThreading</cstring>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Aggressive</string> <string>Disable &amp;background generation</string>
</property> </property>
</widget> </widget>
</vbox> </vbox>
</widget> </widget>
<widget class="QLayoutWidget" row="0" column="1"> <widget class="QLayoutWidget">
<property name="name"> <property name="name">
<cstring>layout6</cstring> <cstring>layout6_2</cstring>
</property> </property>
<vbox> <vbox>
<property name="name"> <property name="name">
...@@ -96,7 +74,7 @@ ...@@ -96,7 +74,7 @@
</property> </property>
<widget class="QLabel"> <widget class="QLabel">
<property name="name"> <property name="name">
<cstring>pixmapLabel1</cstring> <cstring>pixmapLabel1_2</cstring>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy> <sizepolicy>
...@@ -107,12 +85,12 @@ ...@@ -107,12 +85,12 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap>"kcmmemory", 32</pixmap> <pixmap>"kcmprocessor", 32</pixmap>
</property> </property>
</widget> </widget>
<spacer> <spacer>
<property name="name"> <property name="name">
<cstring>spacer7</cstring> <cstring>spacer7_2</cstring>
</property> </property>
<property name="orientation"> <property name="orientation">
<enum>Vertical</enum> <enum>Vertical</enum>
...@@ -129,11 +107,11 @@ ...@@ -129,11 +107,11 @@
</spacer> </spacer>
</vbox> </vbox>
</widget> </widget>
</grid> </hbox>
</widget> </widget>
<widget class="QGroupBox"> <widget class="QButtonGroup">
<property name="name"> <property name="name">
<cstring>groupBox1</cstring> <cstring>kcfg_MemoryLevel</cstring>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy> <sizepolicy>
...@@ -144,41 +122,63 @@ ...@@ -144,41 +122,63 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="title"> <property name="title">
<string>CPU Usage</string> <string>Memory Usage</string>
</property> </property>
<hbox> <grid>
<property name="name"> <property name="name">
<cstring>unnamed</cstring> <cstring>unnamed</cstring>
</property> </property>
<widget class="QLayoutWidget"> <widget class="QLabel" row="1" column="0" rowspan="1" colspan="2">
<property name="name"> <property name="name">
<cstring>layout9</cstring> <cstring>descLabel</cstring>
</property>
<property name="text">
<string>...</string>
</property>
<property name="textFormat">
<enum>PlainText</enum>
</property>
<property name="alignment">
<set>WordBreak|AlignVCenter</set>
</property>
</widget>
<widget class="QLayoutWidget" row="0" column="0">
<property name="name">
<cstring>layout5</cstring>
</property> </property>
<vbox> <vbox>
<property name="name"> <property name="name">
<cstring>unnamed</cstring> <cstring>unnamed</cstring>
</property> </property>
<widget class="QCheckBox"> <widget class="QRadioButton">
<property name="name"> <property name="name">
<cstring>kcfg_DisableCompositing</cstring> <cstring>lowRadio</cstring>
</property> </property>
<property name="text"> <property name="text">
<string>Disable &amp;transparency effects</string> <string>&amp;Low</string>
</property> </property>
</widget> </widget>
<widget class="QCheckBox"> <widget class="QRadioButton">
<property name="name"> <property name="name">
<cstring>kcfg_DisableThreading</cstring> <cstring>normalRadio</cstring>
</property>
<property name="text">
<string>&amp;Normal (default)</string>
</property>
</widget>
<widget class="QRadioButton">
<property name="name">
<cstring>aggressiveRadio</cstring>
</property> </property>
<property name="text"> <property name="text">
<string>Disable &amp;asyncronous generation</string> <string>&amp;Aggressive</string>
</property> </property>
</widget> </widget>
</vbox> </vbox>
</widget> </widget>
<widget class="QLayoutWidget"> <widget class="QLayoutWidget" row="0" column="1">
<property name="name"> <property name="name">
<cstring>layout6_2</cstring> <cstring>layout6</cstring>
</property> </property>
<vbox> <vbox>
<property name="name"> <property name="name">
...@@ -186,7 +186,7 @@ ...@@ -186,7 +186,7 @@
</property> </property>
<widget class="QLabel"> <widget class="QLabel">
<property name="name"> <property name="name">
<cstring>pixmapLabel1_2</cstring> <cstring>pixmapLabel1</cstring>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy> <sizepolicy>
...@@ -197,12 +197,12 @@ ...@@ -197,12 +197,12 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap>"kcmprocessor", 32</pixmap> <pixmap>"kcmmemory", 32</pixmap>
</property> </property>
</widget> </widget>
<spacer> <spacer>
<property name="name"> <property name="name">
<cstring>spacer7_2</cstring> <cstring>spacer7</cstring>
</property> </property>
<property name="orientation"> <property name="orientation">
<enum>Vertical</enum> <enum>Vertical</enum>
...@@ -219,7 +219,7 @@ ...@@ -219,7 +219,7 @@
</spacer> </spacer>
</vbox> </vbox>
</widget> </widget>
</hbox> </grid>
</widget> </widget>
<spacer> <spacer>
<property name="name"> <property name="name">
......
...@@ -47,7 +47,7 @@ class KPDFDocumentPrivate ...@@ -47,7 +47,7 @@ class KPDFDocumentPrivate
bool filterCase; bool filterCase;
// cached stuff // cached stuff
int currentPage; DocumentViewport viewport;
// memory check/free timer // memory check/free timer
QTimer * memCheckTimer; QTimer * memCheckTimer;
...@@ -62,22 +62,21 @@ class KPDFDocumentPrivate ...@@ -62,22 +62,21 @@ class KPDFDocumentPrivate
struct ObserverData struct ObserverData
{ {
// public data fields // public data fields
KPDFDocumentObserver * observer; DocumentObserver * instance;
QMap< int, int > pageMemory; QMap< int, int > pageMemory;
int totalMemory; int totalMemory;
// public constructor: initialize data // public constructor: initialize data
ObserverData( KPDFDocumentObserver * obs ) : observer( obs ), totalMemory( 0 ) {}; ObserverData( DocumentObserver * obs ) : instance( obs ), totalMemory( 0 ) {};
}; };
#define foreachObserver( cmd ) {\ #define foreachObserver( cmd ) {\
QMap< int, ObserverData * >::iterator it = d->observers.begin(), end = d->observers.end();\ QMap< int, ObserverData * >::iterator it = d->observers.begin(), end = d->observers.end();\
for ( ; it != end ; ++ it ) { (*it)->observer-> cmd ; } } for ( ; it != end ; ++ it ) { (*it)->instance-> cmd ; } }
KPDFDocument::KPDFDocument() KPDFDocument::KPDFDocument()
: generator( 0 ), d( new KPDFDocumentPrivate ) : generator( 0 ), d( new KPDFDocumentPrivate )
{ {
d->currentPage = -1;
d->searchPage = -1; d->searchPage = -1;
d->memCheckTimer = new QTimer( this ); d->memCheckTimer = new QTimer( this );
connect( d->memCheckTimer, SIGNAL( timeout() ), this, SLOT( slotCheckMemory() ) ); connect( d->memCheckTimer, SIGNAL( timeout() ), this, SLOT( slotCheckMemory() ) );
...@@ -132,9 +131,12 @@ bool KPDFDocument::openDocument( const QString & docFile ) ...@@ -132,9 +131,12 @@ bool KPDFDocument::openDocument( const QString & docFile )
processPageList( true ); processPageList( true );
// 4. set initial page (restoring previous page saved in xml) // 4. set initial page (restoring previous page saved in xml)
int displayedPage = ( d->currentPage >= 0 ) ? d->currentPage : 0; DocumentViewport loadedViewport = d->viewport;
d->currentPage = -1; if ( loadedViewport.pageNumber < 0 )
setCurrentPage( displayedPage ); loadedViewport.pageNumber = 0;
else
d->viewport = DocumentViewport();
setViewport( loadedViewport );
// start bookmark saver timer // start bookmark saver timer
d->saveBookmarksTimer->start( 5 * 60 * 1000 ); d->saveBookmarksTimer->start( 5 * 60 * 1000 );
...@@ -159,7 +161,7 @@ void KPDFDocument::closeDocument() ...@@ -159,7 +161,7 @@ void KPDFDocument::closeDocument()
generator = 0; generator = 0;
// send an empty list to observers (to free their data) // send an empty list to observers (to free their data)
foreachObserver( pageSetup( QValueVector< KPDFPage * >(), true ) ); foreachObserver( notifySetup( QValueVector< KPDFPage * >(), true ) );
// delete pages and clear 'pages_vector' container // delete pages and clear 'pages_vector' container
for ( uint i = 0; i < pages_vector.count() ; i++ ) for ( uint i = 0; i < pages_vector.count() ; i++ )
...@@ -176,22 +178,22 @@ void KPDFDocument::closeDocument() ...@@ -176,22 +178,22 @@ void KPDFDocument::closeDocument()
} }
// reset internal variables // reset internal variables
d->currentPage = -1; d->viewport = DocumentViewport();
d->searchPage = -1; d->searchPage = -1;
} }
void KPDFDocument::addObserver( KPDFDocumentObserver * pObserver ) void KPDFDocument::addObserver( DocumentObserver * pObserver )
{ {
// keep the pointer to the observer in a map // keep the pointer to the observer in a map
d->observers[ pObserver->observerId() ] = new ObserverData( pObserver ); d->observers[ pObserver->observerId() ] = new ObserverData( pObserver );
// if the observer is added while a document is already opened, tell it // if the observer is added while a document is already opened, tell it
if ( !pages_vector.isEmpty() ) if ( !pages_vector.isEmpty() )
pObserver->pageSetup( pages_vector, true ); pObserver->notifySetup( pages_vector, true );
} }
void KPDFDocument::removeObserver( KPDFDocumentObserver * pObserver ) void KPDFDocument::removeObserver( DocumentObserver * pObserver )
{ {
// remove observer from the map. it won't receive notifications anymore // remove observer from the map. it won't receive notifications anymore
if ( d->observers.contains( pObserver->observerId() ) ) if ( d->observers.contains( pObserver->observerId() ) )
...@@ -217,7 +219,7 @@ void KPDFDocument::reparseConfig() ...@@ -217,7 +219,7 @@ void KPDFDocument::reparseConfig()
QValueVector<KPDFPage*>::iterator it = pages_vector.begin(), end = pages_vector.end(); QValueVector<KPDFPage*>::iterator it = pages_vector.begin(), end = pages_vector.end();
for ( ; it != end; ++it ) for ( ; it != end; ++it )
(*it)->deletePixmapsAndRects(); (*it)->deletePixmapsAndRects();
foreachObserver( notifyPixmapsCleared() ); foreachObserver( notifyContentsCleared( DocumentObserver::Pixmap) );
} }
} }
...@@ -237,9 +239,14 @@ const KPDFPage * KPDFDocument::page( uint n ) const ...@@ -237,9 +239,14 @@ const KPDFPage * KPDFDocument::page( uint n ) const
return ( n < pages_vector.count() ) ? pages_vector[n] : 0; return ( n < pages_vector.count() ) ? pages_vector[n] : 0;
} }
const DocumentViewport & KPDFDocument::viewport() const
{
return d->viewport;
}
uint KPDFDocument::currentPage() const uint KPDFDocument::currentPage() const
{ {
return d->currentPage; return d->viewport.pageNumber;
} }
uint KPDFDocument::pages() const uint KPDFDocument::pages() const
...@@ -298,17 +305,45 @@ void KPDFDocument::requestTextPage( uint page ) ...@@ -298,17 +305,45 @@ void KPDFDocument::requestTextPage( uint page )
generator->requestTextPage( kp ); generator->requestTextPage( kp );
} }
/* REFERENCE IMPLEMENTATION: better calling setViewport from other code
void KPDFDocument::setNextPage()
{
// advance page and set viewport on observers
if ( d->viewport.pageNumber < (int)pages_vector.count() - 1 )
setViewport( DocumentViewport( d->viewport.pageNumber + 1 ) );
}
void KPDFDocument::setCurrentPage( int page, const QRect & viewport ) void KPDFDocument::setPrevPage()
{ {
// go to previous page and set viewport on observers
if ( d->viewport.pageNumber > 0 )
setViewport( DocumentViewport( d->viewport.pageNumber - 1 ) );
}
*/
void KPDFDocument::setViewportPage( int page )
{
// clamp page in range [0 ... numPages-1]
if ( page < 0 ) if ( page < 0 )
page = 0; page = 0;
else if ( page > (int)pages_vector.count() ) else if ( page > (int)pages_vector.count() )
page = pages_vector.count() - 1; page = pages_vector.count() - 1;
if ( page == d->currentPage )
// make a viewport from the page and broadcast it
setViewport( DocumentViewport( page ) );
}
void KPDFDocument::setViewport( const DocumentViewport & viewport )
{
// if already broadcasted, don't redo it
if ( viewport == d->viewport )
{
kdDebug() << "setViewport with the same viewport." << endl;
return; return;
d->currentPage = page; }
foreachObserver( pageSetCurrent( page, viewport ) );
// save viewport and notify the change to all observers
d->viewport = viewport;
foreachObserver( notifyViewportChanged() );
} }
void KPDFDocument::findText( const QString & string, bool keepCase ) void KPDFDocument::findText( const QString & string, bool keepCase )
...@@ -325,7 +360,7 @@ void KPDFDocument::findText( const QString & string, bool keepCase ) ...@@ -325,7 +360,7 @@ void KPDFDocument::findText( const QString & string, bool keepCase )
} }
// continue checking last SearchPage first (if it is the current page) // continue checking last SearchPage first (if it is the current page)
int currentPage = d->currentPage; int currentPage = d->viewport.pageNumber;
int pageCount = pages_vector.count(); int pageCount = pages_vector.count();
KPDFPage * foundPage = 0, KPDFPage * foundPage = 0,
* lastPage = (d->searchPage > -1) ? pages_vector[ d->searchPage ] : 0; * lastPage = (d->searchPage > -1) ? pages_vector[ d->searchPage ] : 0;
...@@ -366,8 +401,8 @@ void KPDFDocument::findText( const QString & string, bool keepCase ) ...@@ -366,8 +401,8 @@ void KPDFDocument::findText( const QString & string, bool keepCase )
int pageNumber = foundPage->number(); int pageNumber = foundPage->number();
d->searchPage = pageNumber; d->searchPage = pageNumber;
foundPage->setAttribute( KPDFPage::Highlight ); foundPage->setAttribute( KPDFPage::Highlight );
setCurrentPage( pageNumber ); setViewportPage( pageNumber ); // TODO set viewport to show the found rectangle centered
foreachObserver( notifyPixmapChanged( pageNumber ) ); foreachObserver( notifyPageChanged( pageNumber, DocumentObserver::Highlights ) );
} }
else else
KMessageBox::information( 0, i18n("No matches found for '%1'.").arg(d->searchText) ); KMessageBox::information( 0, i18n("No matches found for '%1'.").arg(d->searchText) );
...@@ -391,7 +426,7 @@ void KPDFDocument::toggleBookmark( int n ) ...@@ -391,7 +426,7 @@ void KPDFDocument::toggleBookmark( int n )
if ( page ) if ( page )
{ {
page->toggleAttribute( KPDFPage::Bookmark ); page->toggleAttribute( KPDFPage::Bookmark );
foreachObserver( notifyPixmapChanged( n ) ); foreachObserver( notifyPageChanged( n, DocumentObserver::Bookmark ) );
} }
} }
...@@ -404,7 +439,7 @@ void KPDFDocument::processLink( const KPDFLink * link ) ...@@ -404,7 +439,7 @@ void KPDFDocument::processLink( const KPDFLink * link )
{ {
case KPDFLink::Goto: { case KPDFLink::Goto: {
const KPDFLinkGoto * go = static_cast< const KPDFLinkGoto * >( link ); const KPDFLinkGoto * go = static_cast< const KPDFLinkGoto * >( link );
KPDFLinkGoto::Viewport destVp = go->destViewport(); DocumentViewport destVp = go->destViewport();
// first open filename if link is pointing outside this document // first open filename if link is pointing outside this document
if ( go->isExternal() && !openRelativeFile( go->fileName() ) ) if ( go->isExternal() && !openRelativeFile( go->fileName() ) )
...@@ -414,7 +449,7 @@ void KPDFDocument::processLink( const KPDFLink * link ) ...@@ -414,7 +449,7 @@ void KPDFDocument::processLink( const KPDFLink * link )
} }
// note: if external file is opened, 'link' doesn't exist anymore! // note: if external file is opened, 'link' doesn't exist anymore!
setCurrentPage( destVp.page ); //TODO implement and use Viewport setViewport( destVp );
} break; } break;
case KPDFLink::Execute: { case KPDFLink::Execute: {
...@@ -471,18 +506,18 @@ void KPDFDocument::processLink( const KPDFLink * link ) ...@@ -471,18 +506,18 @@ void KPDFDocument::processLink( const KPDFLink * link )
switch( action->actionType() ) switch( action->actionType() )
{ {
case KPDFLinkAction::PageFirst: case KPDFLinkAction::PageFirst:
setCurrentPage( 0 ); setViewportPage( 0 );
break; break;
case KPDFLinkAction::PagePrev: case KPDFLinkAction::PagePrev:
if ( d->currentPage > 0 ) if ( d->viewport.pageNumber > 0 )
setCurrentPage( d->currentPage - 1 ); setViewportPage( d->viewport.pageNumber - 1 );
break; break;
case KPDFLinkAction::PageNext: case KPDFLinkAction::PageNext:
if ( d->currentPage < (int)pages_vector.count() - 1 ) if ( d->viewport.pageNumber < (int)pages_vector.count() - 1 )
setCurrentPage( d->currentPage + 1 ); setViewportPage( d->viewport.pageNumber + 1 );
break; break;
case KPDFLinkAction::PageLast: case KPDFLinkAction::PageLast:
setCurrentPage( pages_vector.count() - 1 );