Commit 3e1834c2 authored by Enrico Ros's avatar Enrico Ros
Browse files

smoothscroll

svn path=/trunk/kdegraphics/kpdf/; revision=385041
parent d1e07405
...@@ -686,7 +686,6 @@ void Part::slotShowMenu(const KPDFPage *page, const QPoint &point) ...@@ -686,7 +686,6 @@ void Part::slotShowMenu(const KPDFPage *page, const QPoint &point)
m_pageView->fitPageWidth( page->number() ); m_pageView->fitPageWidth( page->number() );
break; break;
// case 3: // switch to edit mode // case 3: // switch to edit mode
// m_pageView->slotSetMouseDraw();
// break; // break;
} }
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <qcursor.h> #include <qcursor.h>
#include <qpainter.h> #include <qpainter.h>
#include <qtimer.h> #include <qtimer.h>
#include <qdatetime.h>
#include <qpushbutton.h> #include <qpushbutton.h>
#include <qapplication.h> #include <qapplication.h>
#include <qclipboard.h> #include <qclipboard.h>
...@@ -72,15 +73,22 @@ public: ...@@ -72,15 +73,22 @@ public:
QRect mouseSelectionRect; QRect mouseSelectionRect;
QColor selectionRectColor; QColor selectionRectColor;
// other stuff // type ahead find
QTimer * delayTimer; bool typeAheadActive;
QTimer * scrollTimer; QString typeAheadString;
QTimer * findTimer; QTimer * findTimeoutTimer;
// viewport move
bool viewportMoveActive;
QTime viewportMoveTime;
QPoint viewportMoveDest;
QTimer * viewportMoveTimer;
// auto scroll
int scrollIncrement; int scrollIncrement;
QTimer * autoScrollTimer;
// other stuff
QTimer * delayResizeTimer;
bool dirtyLayout; bool dirtyLayout;
bool typeAheadActivated; bool blockViewport; // prevents changes to viewport
QString findString;
bool blockViewport;
bool blockPixmapsRequest; // prevent pixmap requests bool blockPixmapsRequest; // prevent pixmap requests
PageViewMessage * messageWindow; // in pageviewutils.h PageViewMessage * messageWindow; // in pageviewutils.h
...@@ -120,11 +128,13 @@ PageView::PageView( QWidget *parent, KPDFDocument *document ) ...@@ -120,11 +128,13 @@ PageView::PageView( QWidget *parent, KPDFDocument *document )
d->mouseMode = MouseNormal; d->mouseMode = MouseNormal;
d->mouseMidStartY = -1; d->mouseMidStartY = -1;
d->mouseOnRect = false; d->mouseOnRect = false;
d->delayTimer = 0; d->typeAheadActive = false;
d->scrollTimer = 0; d->findTimeoutTimer = 0;
d->findTimer = 0; d->viewportMoveActive = false;
d->typeAheadActivated = false; d->viewportMoveTimer = 0;
d->scrollIncrement = 0; d->scrollIncrement = 0;
d->autoScrollTimer = 0;
d->delayResizeTimer = 0;
d->dirtyLayout = false; d->dirtyLayout = false;
d->blockViewport = false; d->blockViewport = false;
d->blockPixmapsRequest = false; d->blockPixmapsRequest = false;
...@@ -275,7 +285,7 @@ void PageView::notifySetup( const QValueVector< KPDFPage * > & pageSet, bool doc ...@@ -275,7 +285,7 @@ void PageView::notifySetup( const QValueVector< KPDFPage * > & pageSet, bool doc
PageViewMessage::Info, 4000 ); PageViewMessage::Info, 4000 );
} }
void PageView::notifyViewportChanged( bool /*smoothMove*/ ) void PageView::notifyViewportChanged( bool smoothMove )
{ {
// if we are the one changing viewport, skip this nofity // if we are the one changing viewport, skip this nofity
if ( d->blockViewport ) if ( d->blockViewport )
...@@ -305,16 +315,40 @@ void PageView::notifyViewportChanged( bool /*smoothMove*/ ) ...@@ -305,16 +315,40 @@ void PageView::notifyViewportChanged( bool /*smoothMove*/ )
if ( !Settings::viewContinous() || d->dirtyLayout ) if ( !Settings::viewContinous() || d->dirtyLayout )
slotRelayoutPages(); slotRelayoutPages();
// restore viewport or use default x-center, v-top alignment // restore viewport center or use default {x-center,v-top} alignment
const QRect & r = item->geometry(); const QRect & r = item->geometry();
int newCenterX = r.left(),
newCenterY = r.top();
if ( vp.reCenter.enabled ) if ( vp.reCenter.enabled )
{ {
int xCenter = (int)( vp.reCenter.normalizedCenterX * (double)r.width() ); newCenterX += (int)( vp.reCenter.normalizedCenterX * (double)r.width() );
int yCenter = (int)( vp.reCenter.normalizedCenterY * (double)r.height() ); newCenterY += (int)( vp.reCenter.normalizedCenterY * (double)r.height() );
center( r.left() + xCenter, r.top() + yCenter ); }
else
{
newCenterX += r.width() / 2;
newCenterY += visibleHeight() / 2 - 10;
}
// if smooth movement requested, setup parameters and start it
if ( smoothMove )
{
d->viewportMoveActive = true;
d->viewportMoveTime.start();
d->viewportMoveDest.setX( newCenterX );
d->viewportMoveDest.setY( newCenterY );
if ( !d->viewportMoveTimer )
{
d->viewportMoveTimer = new QTimer( this );
connect( d->viewportMoveTimer, SIGNAL( timeout() ),
this, SLOT( slotMoveViewport() ) );
}
d->viewportMoveTimer->start( 25 );
verticalScrollBar()->setEnabled( false );
horizontalScrollBar()->setEnabled( false );
} }
else else
center( r.left() + r.width() / 2, r.top() + visibleHeight() / 2 - 10 ); center( newCenterX, newCenterY );
d->blockPixmapsRequest = false; d->blockPixmapsRequest = false;
// request visible pixmaps in the current viewport and recompute it // request visible pixmaps in the current viewport and recompute it
...@@ -502,28 +536,33 @@ void PageView::viewportPaintEvent( QPaintEvent * pe ) ...@@ -502,28 +536,33 @@ void PageView::viewportPaintEvent( QPaintEvent * pe )
void PageView::viewportResizeEvent( QResizeEvent * ) void PageView::viewportResizeEvent( QResizeEvent * )
{ {
// start a timer that will refresh the pixmap after 0.5s // start a timer that will refresh the pixmap after 0.5s
if ( !d->delayTimer ) if ( !d->delayResizeTimer )
{ {
d->delayTimer = new QTimer( this ); d->delayResizeTimer = new QTimer( this );
connect( d->delayTimer, SIGNAL( timeout() ), this, SLOT( slotRelayoutPages() ) ); connect( d->delayResizeTimer, SIGNAL( timeout() ), this, SLOT( slotRelayoutPages() ) );
} }
d->delayTimer->start( 333, true ); d->delayResizeTimer->start( 333, true );
} }
void PageView::keyPressEvent( QKeyEvent * e ) void PageView::keyPressEvent( QKeyEvent * e )
{ {
e->accept(); e->accept();
// if performing a selection or dyn zooming, disable keys handling
if ( !d->mouseSelectionRect.isNull() || d->mouseMidStartY != -1 ||
d->viewportMoveActive )
return;
// handle 'find as you type' (based on khtml/khtmlview.cpp) // handle 'find as you type' (based on khtml/khtmlview.cpp)
if( d->typeAheadActivated ) if( d->typeAheadActive )
{ {
if( e->key() == Key_BackSpace ) if( e->key() == Key_BackSpace )
{ {
d->findString = d->findString.left( d->findString.length() - 1 ); d->typeAheadString = d->typeAheadString.left( d->typeAheadString.length() - 1 );
if( !d->findString.isEmpty() ) if( !d->typeAheadString.isEmpty() )
{ {
findAhead( false ); findAhead( false );
d->findTimer->start( 3000, true ); d->findTimeoutTimer->start( 3000, true );
} }
else else
{ {
...@@ -535,12 +574,12 @@ void PageView::keyPressEvent( QKeyEvent * e ) ...@@ -535,12 +574,12 @@ void PageView::keyPressEvent( QKeyEvent * e )
else if( e->key() == KStdAccel::findNext() ) else if( e->key() == KStdAccel::findNext() )
{ {
// part doesn't get this key event because of the keyboard grab // part doesn't get this key event because of the keyboard grab
d->findTimer->stop(); // restore normal operation during possible messagebox is displayed d->findTimeoutTimer->stop(); // restore normal operation during possible messagebox is displayed
releaseKeyboard(); releaseKeyboard();
if ( d->document->findText() ) if ( d->document->findText() )
d->messageWindow->display( i18n("Text found: \"%1\".").arg(d->findString.lower()), d->messageWindow->display( i18n("Text found: \"%1\".").arg(d->typeAheadString.lower()),
PageViewMessage::Find, 3000 ); PageViewMessage::Find, 3000 );
d->findTimer->start( 3000, true ); d->findTimeoutTimer->start( 3000, true );
grabKeyboard(); grabKeyboard();
return; return;
} }
...@@ -551,24 +590,31 @@ void PageView::keyPressEvent( QKeyEvent * e ) ...@@ -551,24 +590,31 @@ void PageView::keyPressEvent( QKeyEvent * e )
} }
else if( e->text().isEmpty() == false ) else if( e->text().isEmpty() == false )
{ {
d->findString += e->text(); d->typeAheadString += e->text();
findAhead( true ); findAhead( true );
d->findTimer->start( 3000, true ); d->findTimeoutTimer->start( 3000, true );
return; return;
} }
} }
else if( e->key() == '/' && d->document->isOpened() ) else if( e->key() == '/' && d->document->isOpened() )
{ {
d->findString = QString(); // stop scrolling the page (if doing it)
if ( d->autoScrollTimer )
{
d->scrollIncrement = 0;
d->autoScrollTimer->stop();
}
// start type-adeas search
d->typeAheadString = QString();
d->messageWindow->display(i18n("Starting -- find text as you type"), PageViewMessage::Find, 3000); d->messageWindow->display(i18n("Starting -- find text as you type"), PageViewMessage::Find, 3000);
d->typeAheadActivated = true; d->typeAheadActive = true;
if ( !d->findTimer ) if ( !d->findTimeoutTimer )
{ {
// create the timer on demand // create the timer on demand
d->findTimer = new QTimer( this ); d->findTimeoutTimer = new QTimer( this );
connect( d->findTimer, SIGNAL(timeout()), this, SLOT(findTimeout()) ); connect( d->findTimeoutTimer, SIGNAL(timeout()), this, SLOT(findTimeout()) );
} }
d->findTimer->start( 3000, true ); d->findTimeoutTimer->start( 3000, true );
grabKeyboard(); grabKeyboard();
return; return;
} }
...@@ -624,10 +670,10 @@ void PageView::keyPressEvent( QKeyEvent * e ) ...@@ -624,10 +670,10 @@ void PageView::keyPressEvent( QKeyEvent * e )
break; break;
case Key_Shift: case Key_Shift:
case Key_Control: case Key_Control:
if ( d->scrollTimer ) if ( d->autoScrollTimer )
{ {
if ( d->scrollTimer->isActive() ) if ( d->autoScrollTimer->isActive() )
d->scrollTimer->stop(); d->autoScrollTimer->stop();
else else
slotAutoScoll(); slotAutoScoll();
return; return;
...@@ -637,17 +683,17 @@ void PageView::keyPressEvent( QKeyEvent * e ) ...@@ -637,17 +683,17 @@ void PageView::keyPressEvent( QKeyEvent * e )
return; return;
} }
// if a known key has been pressed, stop scrolling the page // if a known key has been pressed, stop scrolling the page
if ( d->scrollTimer ) if ( d->autoScrollTimer )
{ {
d->scrollIncrement = 0; d->scrollIncrement = 0;
d->scrollTimer->stop(); d->autoScrollTimer->stop();
} }
} }
void PageView::findTimeout() void PageView::findTimeout()
{ {
d->typeAheadActivated = false; d->typeAheadActive = false;
d->findString = ""; d->typeAheadString = "";
d->messageWindow->display(i18n("Find stopped."),PageViewMessage::Find,1000); d->messageWindow->display(i18n("Find stopped."),PageViewMessage::Find,1000);
releaseKeyboard(); releaseKeyboard();
} }
...@@ -658,12 +704,12 @@ void PageView::findAhead(bool increase) ...@@ -658,12 +704,12 @@ void PageView::findAhead(bool increase)
d->document->setViewportPage(0); d->document->setViewportPage(0);
QString status; QString status;
d->document->unHilightPages(false); d->document->unHilightPages(false);
bool found = d->document->findText(d->findString, false, true); bool found = d->document->findText(d->typeAheadString, false, true);
if(found) if(found)
status = i18n("Text found: \"%1\"."); status = i18n("Text found: \"%1\".");
else else
status = i18n("Text not found: \"%1\"."); status = i18n("Text not found: \"%1\".");
d->messageWindow->display(status.arg(d->findString.lower()), d->messageWindow->display(status.arg(d->typeAheadString.lower()),
found ? PageViewMessage::Find : PageViewMessage::Warning, 4000); found ? PageViewMessage::Find : PageViewMessage::Warning, 4000);
} }
...@@ -674,6 +720,10 @@ void PageView::contentsMouseMoveEvent( QMouseEvent * e ) ...@@ -674,6 +720,10 @@ void PageView::contentsMouseMoveEvent( QMouseEvent * e )
if ( d->items.isEmpty() ) if ( d->items.isEmpty() )
return; return;
// don't perform any mouse action when viewport is autoscrolling
if ( d->viewportMoveActive )
return;
// if holding mouse mid button, perform zoom // if holding mouse mid button, perform zoom
if ( (e->state() & MidButton) && d->mouseMidStartY > 0 ) if ( (e->state() & MidButton) && d->mouseMidStartY > 0 )
{ {
...@@ -700,12 +750,6 @@ void PageView::contentsMouseMoveEvent( QMouseEvent * e ) ...@@ -700,12 +750,6 @@ void PageView::contentsMouseMoveEvent( QMouseEvent * e )
QPoint delta = d->mouseGrabPos - e->globalPos(); QPoint delta = d->mouseGrabPos - e->globalPos();
scrollBy( delta.x(), delta.y() ); scrollBy( delta.x(), delta.y() );
d->mouseGrabPos = e->globalPos(); d->mouseGrabPos = e->globalPos();
// if the page was scrolling, stop it
if ( d->scrollTimer )
{
d->scrollIncrement = 0;
d->scrollTimer->stop();
}
} }
} }
else if ( rightButton && !d->mousePressPos.isNull() ) else if ( rightButton && !d->mousePressPos.isNull() )
...@@ -749,9 +793,17 @@ void PageView::contentsMousePressEvent( QMouseEvent * e ) ...@@ -749,9 +793,17 @@ void PageView::contentsMousePressEvent( QMouseEvent * e )
return; return;
// if performing a selection or dyn zooming, disable mouse press // if performing a selection or dyn zooming, disable mouse press
if ( !d->mouseSelectionRect.isNull() || d->mouseMidStartY != -1 ) if ( !d->mouseSelectionRect.isNull() || d->mouseMidStartY != -1 ||
d->viewportMoveActive )
return; return;
// if the page is scrolling, stop it
if ( d->autoScrollTimer )
{
d->scrollIncrement = 0;
d->autoScrollTimer->stop();
}
// if pressing mid mouse button while not doing other things, begin 'comtinous zoom' mode // if pressing mid mouse button while not doing other things, begin 'comtinous zoom' mode
if ( e->button() & MidButton ) if ( e->button() & MidButton )
{ {
...@@ -803,6 +855,10 @@ void PageView::contentsMouseReleaseEvent( QMouseEvent * e ) ...@@ -803,6 +855,10 @@ void PageView::contentsMouseReleaseEvent( QMouseEvent * e )
if ( d->items.isEmpty() ) if ( d->items.isEmpty() )
return; return;
// don't perform any mouse action when viewport is autoscrolling
if ( d->viewportMoveActive )
return;
// handle mode indepent mid buttom zoom // handle mode indepent mid buttom zoom
bool midButton = e->button() & MidButton; bool midButton = e->button() & MidButton;
if ( midButton && d->mouseMidStartY > 0 ) if ( midButton && d->mouseMidStartY > 0 )
...@@ -1034,6 +1090,10 @@ void PageView::contentsMouseReleaseEvent( QMouseEvent * e ) ...@@ -1034,6 +1090,10 @@ void PageView::contentsMouseReleaseEvent( QMouseEvent * e )
void PageView::wheelEvent( QWheelEvent *e ) void PageView::wheelEvent( QWheelEvent *e )
{ {
// don't perform any mouse action when viewport is autoscrolling
if ( d->viewportMoveActive )
return;
int delta = e->delta(), int delta = e->delta(),
vScroll = verticalScrollBar()->value(); vScroll = verticalScrollBar()->value();
e->accept(); e->accept();
...@@ -1220,10 +1280,10 @@ void PageView::selectionStart( int x, int y, const QColor & color, bool /*aboveA ...@@ -1220,10 +1280,10 @@ void PageView::selectionStart( int x, int y, const QColor & color, bool /*aboveA
d->mouseSelectionRect.setRect( x, y, 1, 1 ); d->mouseSelectionRect.setRect( x, y, 1, 1 );
d->selectionRectColor = color; d->selectionRectColor = color;
// ensures page doesn't scroll // ensures page doesn't scroll
if ( d->scrollTimer ) if ( d->autoScrollTimer )
{ {
d->scrollIncrement = 0; d->scrollIncrement = 0;
d->scrollTimer->stop(); d->autoScrollTimer->stop();
} }
} }
...@@ -1412,6 +1472,15 @@ void PageView::slotRelayoutPages() ...@@ -1412,6 +1472,15 @@ void PageView::slotRelayoutPages()
return; return;
} }
// if viewport was auto-moving, stop it
if ( d->viewportMoveActive )
{
d->viewportMoveActive = false;
d->viewportMoveTimer->stop();
verticalScrollBar()->setEnabled( true );
horizontalScrollBar()->setEnabled( true );
}
// common iterator used in this method and viewport parameters // common iterator used in this method and viewport parameters
QValueVector< PageViewItem * >::iterator iIt, iEnd = d->items.end(); QValueVector< PageViewItem * >::iterator iIt, iEnd = d->items.end();
int viewportWidth = visibleWidth(), int viewportWidth = visibleWidth(),
...@@ -1581,7 +1650,7 @@ void PageView::slotRelayoutPages() ...@@ -1581,7 +1650,7 @@ void PageView::slotRelayoutPages()
void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop ) void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop )
{ {
// if requests are blocked (because raised by an unwanted event), exit // if requests are blocked (because raised by an unwanted event), exit
if ( d->blockPixmapsRequest ) if ( d->blockPixmapsRequest || d->viewportMoveActive )
return; return;
// precalc view limits for intersecting with page coords inside the lOOp // precalc view limits for intersecting with page coords inside the lOOp
...@@ -1686,19 +1755,45 @@ void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop ) ...@@ -1686,19 +1755,45 @@ void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop )
} }
} }
void PageView::slotMoveViewport()
{
// converge to viewportMoveDest in 1 second
int diffTime = d->viewportMoveTime.elapsed();
if ( diffTime >= 667 || !d->viewportMoveActive )
{
center( d->viewportMoveDest.x(), d->viewportMoveDest.y() );
d->viewportMoveTimer->stop();
d->viewportMoveActive = false;
slotRequestVisiblePixmaps();
verticalScrollBar()->setEnabled( true );
horizontalScrollBar()->setEnabled( true );
return;
}
// move the viewport smoothly (kmplot: p(x)=x+x*(1-x)*(1-x))
float convergeSpeed = (float)diffTime / 667.0,
x = ((float)visibleWidth() / 2.0) + contentsX(),
y = ((float)visibleHeight() / 2.0) + contentsY(),
diffX = (float)d->viewportMoveDest.x() - x,
diffY = (float)d->viewportMoveDest.y() - y;
convergeSpeed *= convergeSpeed * (1.4 - convergeSpeed);
center( (int)(x + diffX * convergeSpeed),
(int)(y + diffY * convergeSpeed ) );
}
void PageView::slotAutoScoll() void PageView::slotAutoScoll()
{ {
// the first time create the timer // the first time create the timer
if ( !d->scrollTimer ) if ( !d->autoScrollTimer )
{ {
d->scrollTimer = new QTimer( this ); d->autoScrollTimer = new QTimer( this );
connect( d->scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScoll() ) ); connect( d->autoScrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScoll() ) );
} }
// if scrollIncrement is zero, stop the timer // if scrollIncrement is zero, stop the timer
if ( !d->scrollIncrement ) if ( !d->scrollIncrement )
{ {
d->scrollTimer->stop(); d->autoScrollTimer->stop();
return; return;
} }
...@@ -1706,7 +1801,7 @@ void PageView::slotAutoScoll() ...@@ -1706,7 +1801,7 @@ void PageView::slotAutoScoll()
int index = abs( d->scrollIncrement ) - 1; // 0..9 int index = abs( d->scrollIncrement ) - 1; // 0..9
const int scrollDelay[10] = { 200, 100, 50, 30, 20, 30, 25, 20, 30, 20 }; const int scrollDelay[10] = { 200, 100, 50, 30, 20, 30, 25, 20, 30, 20 };
const int scrollOffset[10] = { 1, 1, 1, 1, 1, 2, 2, 2, 4, 4 }; const int scrollOffset[10] = { 1, 1, 1, 1, 1, 2, 2, 2, 4, 4 };
d->scrollTimer->changeInterval( scrollDelay[ index ] ); d->autoScrollTimer->changeInterval( scrollDelay[ index ] );
scrollBy( 0, d->scrollIncrement > 0 ? scrollOffset[ index ] : -scrollOffset[ index ] ); scrollBy( 0, d->scrollIncrement > 0 ? scrollOffset[ index ] : -scrollOffset[ index ] );
} }
......
...@@ -63,9 +63,6 @@ class PageView : public QScrollView, public DocumentObserver ...@@ -63,9 +63,6 @@ class PageView : public QScrollView, public DocumentObserver
void notifyContentsCleared( int changedFlags ); void notifyContentsCleared( int changedFlags );
bool canUnloadPixmap( int pageNum ); bool canUnloadPixmap( int pageNum );
public slots:
void slotSetMouseDraw();
signals: signals:
void urlDropped( const KURL& ); void urlDropped( const KURL& );
void rightClick( const KPDFPage *, const QPoint & ); void rightClick( const KPDFPage *, const QPoint & );
...@@ -114,12 +111,14 @@ class PageView : public QScrollView, public DocumentObserver ...@@ -114,12 +111,14 @@ class PageView : public QScrollView, public DocumentObserver
void slotRelayoutPages(); void slotRelayoutPages();
// activated either directly or via the contentsMoving(int,int) signal // activated either directly or via the contentsMoving(int,int) signal
void slotRequestVisiblePixmaps( int left = -1, int top = -1 ); void slotRequestVisiblePixmaps( int left = -1, int top = -1 );
// activated by the viewport move timer
void slotMoveViewport();
// activated by the autoscroll timer (Shift+Up/Down keys) // activated by the autoscroll timer (Shift+Up/Down keys)
void slotAutoScoll(); void slotAutoScoll();
// type-ahead find timeout // type-ahead find timeout
void findTimeout(); void findTimeout();
// connected to local actions // connected to local actions (toolbar, menu, ..)
void slotZoom(); void slotZoom();
void slotZoomIn(); void slotZoomIn();
void slotZoomOut(); void slotZoomOut();
...@@ -131,6 +130,7 @@ class PageView : public QScrollView, public DocumentObserver ...@@ -131,6 +130,7 @@ class PageView : public QScrollView, public DocumentObserver
void slotSetMouseNormal(); void slotSetMouseNormal();
void slotSetMouseZoom(); void slotSetMouseZoom();
void slotSetMouseSelect(); void slotSetMouseSelect();
void slotSetMouseDraw();
void slotScrollUp(); void slotScrollUp();
void slotScrollDown(); void slotScrollDown();
}; };
......
Markdown is supported
0% or