Commit 3bf154b5 authored by Enrico Ros's avatar Enrico Ros

Viewport: fixes, setViewport( vp, id ) excludes id from the notified

bodies. Optimized fit width and a saved a couple of pixmap requests. Busy
cursor on load and searches.

svn path=/trunk/kdegraphics/kpdf/; revision=377152
parent 162d1a9c
......@@ -19,15 +19,12 @@ Urgent fixes and items to get ready before 3.4 (special high-priority list):
-> mem: check for running request in thread too
-> mem: iterate from older pages to newest ones when freeing memory (not rand)
-> generator: add preloading
-> viewport: definition. note, Acroread has a simple implementation that shares
the same bug we'll have if defining a page+rect+props viewport.
-> viewport: observers sync. broadcasts a setviewport() by one observer to all
other observers.
-> viewport: use it in Links and Synopsis (requires a QString constructor?)
-> new word highlighting for searches / other highlights (on paper - enrico)
-> cleanup code and update README.png
More items (first items will enter 'In progress list' first):
-> show Viewport in ThumbnailsList (blended/contour)
-> Delay TOC (DocumentSynapsis) generation (and move it on thread)
-> refactor ThumbnailsList to do internal rendering as pageview does (way
faster than using QScrollView + inserted Widgets and saves 8% on document
......@@ -36,7 +33,6 @@ More items (first items will enter 'In progress list' first):
-> move toolbar view actions in the PageView instead of the part. maybe.. or not...
-> usability: layout 2PPV [1 2,3 4,5 6] -> [1,2 3,4 5]. add option for 'ebook' style alignment. (by Mikolaj)
-> usability: trigger redraw on 'filter text' on current page (by Mikolaj)
-> watch out for FIXMEs in code
-> fix: requestPixmaps not triggered when exiting fullscreen mode (to verify..I can't reproduce-enrico)
-> fix: On continous view mode, if you click to a link that moves you to another
page, then scroll up and click again on the same link it does not work. (by Albert)
......@@ -54,7 +50,7 @@ More items (first items will enter 'In progress list' first):
- <X> Synopsis will go there after 1st generation (so we can edit it too)
- <X> Document info (after the 1st gen)
- <X> Bookmarked pages
- <X - only for pagenumber> General info (like viewport state)
- <X - only for viewport> General info (like viewport state)
- Edited pages (rotated/with_data for example)
- Overlay editing (hilighting/notations/etc..)
- Presentation related overrides (FS mode, individual / global transitions)
......@@ -66,7 +62,6 @@ More items (first items will enter 'In progress list' first):
-> add kpdf manual in PDF format loaded on the first startup or on menu->help->manual
this visually explains basic usage, mouse buttons functions & more..
-> take care of TODOs in code
-> find: scroll page if the the searched string is not visible [after 'viewport changes']
-> ADD: click over image allows "save image" [60% done (activerect of type image)]
-> screen editing (annotations): framework (BR67300,BR62793)
-> screen editing (annotations): tools (BR67300)
......@@ -95,6 +90,8 @@ More items (first items will enter 'In progress list' first):
-> move some document related features from part to the document (see find, goto dialog, ...)
Done (newest features come first):
-> FIX: scroll page if the the searched string is not visible
-> FIX: use a global Viewport over the document (linked views, real link following, location restoring, etc)
-> FIX: wrong zoom buttons order (BR74248) (check consistancy with kdvi/kviewshell/kghostview/.. (not konq))
-> ADD: presentation: cursor modes: hidden, visible, hidden with delay (Tobias)
-> ADD: presentation: default transition which is used when no transition is defined in document (Tobias)
......
......@@ -118,9 +118,11 @@ bool KPDFDocument::openDocument( const QString & docFile )
connect( generator, SIGNAL( contentsChanged( int, int ) ),
this, SLOT( slotGeneratedContents( int, int ) ) );
// 1. load Document
// 1. load Document (and set busy cursor while loading)
documentFileName = docFile;
QApplication::setOverrideCursor( waitCursor );
bool openOk = generator->loadDocument( docFile, pages_vector );
QApplication::restoreOverrideCursor();
if ( !openOk || pages_vector.size() <= 0 )
return openOk;
......@@ -320,7 +322,7 @@ void KPDFDocument::setPrevPage()
setViewport( DocumentViewport( d->viewport.pageNumber - 1 ) );
}
*/
void KPDFDocument::setViewportPage( int page )
void KPDFDocument::setViewportPage( int page, int id )
{
// clamp page in range [0 ... numPages-1]
if ( page < 0 )
......@@ -329,21 +331,23 @@ void KPDFDocument::setViewportPage( int page )
page = pages_vector.count() - 1;
// make a viewport from the page and broadcast it
setViewport( DocumentViewport( page ) );
setViewport( DocumentViewport( page ), id );
}
void KPDFDocument::setViewport( const DocumentViewport & viewport )
void KPDFDocument::setViewport( const DocumentViewport & viewport, int id )
{
// if already broadcasted, don't redo it
if ( viewport == d->viewport )
{
kdDebug() << "setViewport with the same viewport." << endl;
return;
}
// save viewport and notify the change to all observers
// set internal viewport
d->viewport = viewport;
foreachObserver( notifyViewportChanged() );
// notify change to all other (different from id) viewports
QMap< int, ObserverData * >::iterator it = d->observers.begin(), end = d->observers.end();
for ( ; it != end ; ++ it )
if ( it.key() != id )
(*it)->instance->notifyViewportChanged();
}
void KPDFDocument::findText( const QString & string, bool keepCase )
......@@ -401,7 +405,14 @@ void KPDFDocument::findText( const QString & string, bool keepCase )
int pageNumber = foundPage->number();
d->searchPage = pageNumber;
foundPage->setAttribute( KPDFPage::Highlight );
setViewportPage( pageNumber ); // TODO set viewport to show the found rectangle centered
// move the viewport to show the searched word centered
DocumentViewport searchViewport( pageNumber );
const QPoint & center = foundPage->getLastSearchCenter();
searchViewport.reCenter.enabled = true;
searchViewport.reCenter.normalizedCenterX = (double)center.x() / foundPage->width();
searchViewport.reCenter.normalizedCenterY = (double)center.y() / foundPage->height();
setViewport( searchViewport );
// notify all observers about hilighting chages
foreachObserver( notifyPageChanged( pageNumber, DocumentObserver::Highlights ) );
}
else
......@@ -414,10 +425,15 @@ void KPDFDocument::findTextAll( const QString & pattern, bool keepCase )
if ( pattern.isEmpty() )
unHilightPages();
// cache search pattern and perform a linear search/mark
// cache search pattern
d->filterText = pattern;
d->filterCase = keepCase;
// set the busy cursor globally on the application
QApplication::setOverrideCursor( waitCursor );
// perform a linear search/mark
processPageList( false );
// reset cursor to previous shape
QApplication::restoreOverrideCursor();
}
void KPDFDocument::toggleBookmark( int n )
......@@ -548,6 +564,7 @@ void KPDFDocument::processLink( const KPDFLink * link )
} break;
case KPDFLink::Movie:
//const KPDFLinkMovie * browse = static_cast< const KPDFLinkMovie * >( link );
// TODO this
break;
}
......
......@@ -70,8 +70,8 @@ class KPDFDocument : public QObject // only for a private slot..
QString getMetaData( const QString & key, const QString & option = QString() ) const;
// perform actions on document / pages
void setViewportPage( int page );
void setViewport( const DocumentViewport & viewport );
void setViewportPage( int page, int id = -1 );
void setViewport( const DocumentViewport & viewport, int id = -1 );
void requestPixmaps( const QValueList< PixmapRequest * > & requests, bool asyncronous );
void requestTextPage( uint page );
void findText( const QString & text = "", bool caseSensitive = false );
......
......@@ -16,7 +16,10 @@
/**
* @short Encapsulates data that describes a link.
* TODO: comment
*
* This is the base class for links. It makes mandatory for inherited
* widgets to reimplement the 'linkType' method and return the type of
* the link described by the reimplemented class.
*/
class KPDFLink
{
......@@ -30,6 +33,7 @@ class KPDFLink
};
/** Goto: a viewport and maybe a reference to an external filename **/
class KPDFLinkGoto : public KPDFLink
{
public:
......@@ -47,7 +51,7 @@ class KPDFLinkGoto : public KPDFLink
DocumentViewport m_vp;
};
/** Execute: filename and parameters to execute **/
class KPDFLinkExecute : public KPDFLink
{
public:
......@@ -64,7 +68,7 @@ class KPDFLinkExecute : public KPDFLink
QString m_parameters;
};
/** Browse: an URL to open, ranging from 'http://' to 'mailto:' etc.. **/
class KPDFLinkBrowse : public KPDFLink
{
public:
......@@ -79,7 +83,7 @@ class KPDFLinkBrowse : public KPDFLink
QString m_url;
};
/** Action: contains an action to perform on document / kpdf **/
class KPDFLinkAction : public KPDFLink
{
public:
......@@ -97,7 +101,7 @@ class KPDFLinkAction : public KPDFLink
ActionType m_type;
};
/** Movie: Not yet defined -> think renaming to 'Media' link **/
class KPDFLinkMovie : public KPDFLink
//TODO: this
{
......
......@@ -98,6 +98,13 @@ const KPDFPageTransition * KPDFPage::getTransition() const
return m_transition;
}
const QPoint KPDFPage::getLastSearchCenter() const
{
int centerX = (int)((m_sRight + m_sLeft) / 2),
centerY = (int)((m_sTop + m_sBottom) / 2);
return QPoint( centerX, centerY );
}
const QString KPDFPage::getTextInRect( const QRect & rect, double zoom ) const
{
if ( !m_text )
......@@ -122,11 +129,20 @@ bool KPDFPage::hasText( const QString & text, bool strictCase, bool fromTop )
for (int i = 0; i < len; ++i)
u[i] = str[i].unicode();
bool found = m_text->findText( u, len, fromTop ? gTrue : gFalse, gTrue, fromTop ? gFalse : gTrue, gFalse, &m_sLeft, &m_sTop, &m_sRight, &m_sBottom );
if( found && strictCase )
bool found = false;
while ( !found )
{
GString * orig = m_text->getText( m_sLeft, m_sTop, m_sRight, m_sBottom );
found = QString::fromUtf8( orig->getCString() ) == text;
found = m_text->findText( u, len, fromTop ? gTrue : gFalse, gTrue, fromTop ? gFalse : gTrue, gFalse, &m_sLeft, &m_sTop, &m_sRight, &m_sBottom );
if ( !found )
break;
if( strictCase )
{
// since we're in 'Case sensitive' mode, check if words are identical
GString * orig = m_text->getText( m_sLeft, m_sTop, m_sRight, m_sBottom );
found = QString::fromUtf8( orig->getCString() ) == text;
if ( !found && fromTop )
fromTop = false;
}
}
gfree(u);
return found;
......
......@@ -51,7 +51,8 @@ class KPDFPage
bool hasLink( int mouseX, int mouseY ) const;
const KPDFPageRect * getRect( int mouseX, int mouseY ) const;
const KPDFPageTransition * getTransition() const;
const QString getTextInRect( const QRect & rect, double zoom = 1.0 ) const;
const QPoint getLastSearchCenter() const;
const QString getTextInRect( const QRect & rect, double zoom /*= 1.0*/ ) const;
// operations (by KPDFDocument)
inline void setAttribute( int att ) { m_attributes |= att; }
......
......@@ -573,7 +573,8 @@ void Part::slotShowMenu(const KPDFPage *page, const QPoint &point)
popup->insertItem( SmallIcon("bookmark"), i18n("Remove Bookmark"), 1 );
else
popup->insertItem( SmallIcon("bookmark_add"), i18n("Add Bookmark"), 1 );
popup->insertItem( SmallIcon("viewmagfit"), i18n("Fit Width"), 2 );
if ( m_pageView->canFitPageWidth() )
popup->insertItem( SmallIcon("viewmagfit"), i18n("Fit Width"), 2 );
//popup->insertItem( SmallIcon("pencil"), i18n("Edit"), 3 );
//popup->setItemEnabled( 3, false );
reallyShow = true;
......
......@@ -197,6 +197,11 @@ void PageView::setupActions( KActionCollection * ac )
sd->setShortcut( "Shift+Down" );
}
bool PageView::canFitPageWidth()
{
return Settings::viewColumns() != 1 || d->zoomMode != ZoomFitWidth;
}
void PageView::fitPageWidth( int page )
{
// zoom: Fit Width, columns: 1. setActions + relayout + setPage + update
......@@ -209,9 +214,8 @@ void PageView::fitPageWidth( int page )
viewport()->setUpdatesEnabled( false );
slotRelayoutPages();
viewport()->setUpdatesEnabled( true );
updateContents();
// updateZoomText(); active?
d->document->setViewportPage( page );
updateZoomText();
}
......@@ -307,7 +311,7 @@ void PageView::notifyViewportChanged()
updateCursor( viewportToContents( mapFromGlobal( QCursor::pos() ) ) );
}
void PageView::notifyPageChanged( int pageNumber, int changedFlags )
void PageView::notifyPageChanged( int pageNumber, int /*changedFlags*/ )
{
// only handle pixmap changed notifies (the only defined for now)
//if ( !(changedFlags & DocumentObserver::Pixmap) )
......@@ -694,7 +698,7 @@ void PageView::contentsMouseReleaseEvent( QMouseEvent * e )
else
{
// mouse not moved since press, so we have a click. select the page.
d->document->setViewportPage( pageItem->pageNumber() );
d->document->setViewportPage( pageItem->pageNumber(), PAGEVIEW_ID );
}
}
else if ( rightButton )
......@@ -1347,30 +1351,35 @@ void PageView::slotRelayoutPages()
d->dirtyLayout = false;
// 4) update scrollview's contents size and recenter view
bool wasUpdatesEnabled = viewport()->isUpdatesEnabled();
if ( fullWidth != contentsWidth() || fullHeight != contentsHeight() )
{
// disable updates and resize the viewportContents
bool prevUpdatesState = viewport()->isUpdatesEnabled();
viewport()->setUpdatesEnabled( false );
if ( wasUpdatesEnabled )
viewport()->setUpdatesEnabled( false );
resizeContents( fullWidth, fullHeight );
// restore previous viewport if defined
const DocumentViewport & vp = d->document->viewport();
if ( vp.pageNumber >= 0 )
// restore previous viewport if defined and updates enabled
if ( wasUpdatesEnabled )
{
const QRect & geometry = d->items[ vp.pageNumber ]->geometry();
double nX = vp.reCenter.enabled ? vp.reCenter.normalizedCenterX : 0.5,
nY = vp.reCenter.enabled ? vp.reCenter.normalizedCenterY : 0.0;
center( geometry.left() + ROUND( nX * (double)geometry.width() ),
geometry.top() + ROUND( nY * (double)geometry.height() ) );
const DocumentViewport & vp = d->document->viewport();
if ( vp.pageNumber >= 0 )
{
const QRect & geometry = d->items[ vp.pageNumber ]->geometry();
double nX = vp.reCenter.enabled ? vp.reCenter.normalizedCenterX : 0.5,
nY = vp.reCenter.enabled ? vp.reCenter.normalizedCenterY : 0.0;
center( geometry.left() + ROUND( nX * (double)geometry.width() ),
geometry.top() + ROUND( nY * (double)geometry.height() ) );
}
// or else go to center page
else
center( fullWidth / 2, 0 );
viewport()->setUpdatesEnabled( true );
}
// or else go to center page
else
center( fullWidth / 2, 0 );
viewport()->setUpdatesEnabled( prevUpdatesState );
}
// 5) update the whole viewport
updateContents();
// 5) update the whole viewport if updated enabled
if ( wasUpdatesEnabled )
updateContents();
}
void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop )
......@@ -1383,10 +1392,8 @@ void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop )
// some variables used to determine the viewport
int nearPageNumber = -1,
viewportWidth = visibleWidth(),
viewportHeight = visibleHeight(),
viewportCenterX = contentsX() + viewportWidth / 2,
viewportCenterY = contentsY() + viewportHeight / 2;
viewportCenterX = (viewportRect.left() + viewportRect.right()) / 2,
viewportCenterY = (viewportRect.top() + viewportRect.bottom()) / 2;
double focusedX = 0.5,
focusedY = 0.0,
minDistance = -1.0;
......@@ -1416,8 +1423,8 @@ void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop )
{
const QRect & geometry = i->geometry();
// compute distance between item center and viewport center
double distance = hypot( geometry.left() + geometry.width() / 2 - viewportCenterX,
geometry.top() + geometry.height() / 2 - viewportCenterY );
double distance = hypot( (geometry.left() + geometry.right()) / 2 - viewportCenterX,
(geometry.top() + geometry.bottom()) / 2 - viewportCenterY );
if ( distance >= minDistance && nearPageNumber != -1 )
continue;
nearPageNumber = i->pageNumber();
......@@ -1443,10 +1450,7 @@ void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop )
newViewport.reCenter.normalizedCenterX = focusedX;
newViewport.reCenter.normalizedCenterY = focusedY;
// set the viewport to other observers
bool prevState = d->blockViewport;
d->blockViewport = true;
d->document->setViewport( newViewport );
d->blockViewport = prevState;
d->document->setViewport( newViewport , PAGEVIEW_ID);
}
}
......
......@@ -52,6 +52,7 @@ class PageView : public QScrollView, public DocumentObserver
void setupActions( KActionCollection * collection );
// used from RMB menu
bool canFitPageWidth();
void fitPageWidth( int page );
// inherited from DocumentObserver
......
......@@ -157,7 +157,7 @@ void ThumbnailList::notifyViewportChanged()
}
}
void ThumbnailList::notifyPageChanged( int pageNumber, int changedFlags )
void ThumbnailList::notifyPageChanged( int pageNumber, int /*changedFlags*/ )
{
// only handle pixmap changed notifies (the only defined for now)
//if ( !(changedFlags & DocumentObserver::Pixmap) )
......@@ -270,7 +270,8 @@ void ThumbnailList::contentsMousePressEvent( QMouseEvent * e )
int childTop = childY(t);
if ( clickY > childTop && clickY < (childTop + t->height()) )
{
m_document->setViewportPage( t->pageNumber() );
if ( m_document->viewport().pageNumber != t->pageNumber() )
m_document->setViewportPage( t->pageNumber() );
break;
}
}
......
......@@ -122,7 +122,7 @@ void TOC::slotExecuted( QListViewItem *i )
if ( e.hasAttribute( "PageViewport" ) )
{
// if the node has a viewport, set it
m_document->setViewport( DocumentViewport( e.attribute( "PageViewport" ) ) );
m_document->setViewport( DocumentViewport( e.attribute( "PageViewport" ) ), TOC_ID );
}
else if ( e.hasAttribute( "ViewportName" ) )
{
......@@ -130,7 +130,7 @@ void TOC::slotExecuted( QListViewItem *i )
const QString & page = e.attribute( "ViewportName" );
const QString & viewport = m_document->getMetaData( "NamedViewport", page );
if ( !viewport.isNull() )
m_document->setViewport( DocumentViewport( viewport ) );
m_document->setViewport( DocumentViewport( viewport ), TOC_ID );
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment