Fix:Zoom flickerlessy and follows view type changes.

Minor:update outline too when pixmapChanged(). d->pages moved to d->items
and iterators updated accordingly.
headMergeBlocks--;

svn path=/branches/kpdf_experiments/kdegraphics/kpdf/; revision=360557
This commit is contained in:
Enrico Ros 2004-11-05 00:14:00 +00:00
parent cb68d1a905
commit 934fdee66b
2 changed files with 100 additions and 63 deletions

View file

@ -13,7 +13,6 @@ In progress on the branch (first item comes first):
Things to do in order to merge in HEAD (first item has highest priority): Things to do in order to merge in HEAD (first item has highest priority):
-> memory manager with different profiles (mem/cpu tradeoff: {memory saving, normal, memory aggressive}) -> memory manager with different profiles (mem/cpu tradeoff: {memory saving, normal, memory aggressive})
-> fix viewport restoring after zoom (not, fix zoom globally)
-> link thumbnails view with document -> link thumbnails view with document
-> this may be postponed after merge: implementing async document generator using Albert's generator thread -> this may be postponed after merge: implementing async document generator using Albert's generator thread
-> new icons (contest at kde-look has ended and we know the winner. good choice :-) -> new icons (contest at kde-look has ended and we know the winner. good choice :-)
@ -40,6 +39,7 @@ More items (first items will enter 'In progress list' first):
-> wrong zoom buttons order (BR74248) (check consistancy with kdvi/kghostview/.. (not konq)) -> wrong zoom buttons order (BR74248) (check consistancy with kdvi/kghostview/.. (not konq))
Done (newest feature comes firts): Done (newest feature comes firts):
-> FIX: zoom preserved when switching modes and flickerless
-> ADD: Printing as PS instead of as image (Albert) -> ADD: Printing as PS instead of as image (Albert)
-> ADD: Remember page on session logout and put the document in it on session restore (Albert) -> ADD: Remember page on session logout and put the document in it on session restore (Albert)
-> ADD: gfx capturing tool -> ADD: gfx capturing tool

View file

@ -47,8 +47,8 @@ class PageViewPrivate
public: public:
// the document, current page and pages indices vector // the document, current page and pages indices vector
KPDFDocument * document; KPDFDocument * document;
PageViewItem * activeItem; //equal to pages[vectorIndex] PageViewItem * activeItem; //equal to items[vectorIndex]
QValueVector< PageViewItem * > pages; QValueVector< PageViewItem * > items;
int vectorIndex; int vectorIndex;
// view layout (columns and continous in Settings), zoom and mouse // view layout (columns and continous in Settings), zoom and mouse
@ -196,27 +196,27 @@ void PageView::setupActions( KActionCollection * ac )
void PageView::pageSetup( const QValueVector<KPDFPage*> & pageSet, bool documentChanged ) void PageView::pageSetup( const QValueVector<KPDFPage*> & pageSet, bool documentChanged )
{ {
// reuse current pages if nothing new // reuse current pages if nothing new
if ( ( pageSet.count() == d->pages.count() ) && !documentChanged ) if ( ( pageSet.count() == d->items.count() ) && !documentChanged )
{ {
int count = pageSet.count(); int count = pageSet.count();
for ( int i = 0; (i < count) && !documentChanged; i++ ) for ( int i = 0; (i < count) && !documentChanged; i++ )
if ( (int)pageSet[i]->number() != d->pages[i]->pageNumber() ) if ( (int)pageSet[i]->number() != d->items[i]->pageNumber() )
documentChanged = true; documentChanged = true;
if ( !documentChanged ) if ( !documentChanged )
return; return;
} }
// delete all widgets (one for each page in pageSet) // delete all widgets (one for each page in pageSet)
QValueVector< PageViewItem * >::iterator dIt = d->pages.begin(), dEnd = d->pages.end(); QValueVector< PageViewItem * >::iterator dIt = d->items.begin(), dEnd = d->items.end();
for ( ; dIt != dEnd; ++dIt ) for ( ; dIt != dEnd; ++dIt )
delete *dIt; delete *dIt;
d->pages.clear(); d->items.clear();
d->activeItem = 0; d->activeItem = 0;
// create children widgets // create children widgets
QValueVector< KPDFPage * >::const_iterator setIt = pageSet.begin(), setEnd = pageSet.end(); QValueVector< KPDFPage * >::const_iterator setIt = pageSet.begin(), setEnd = pageSet.end();
for ( ; setIt != setEnd; ++setIt ) for ( ; setIt != setEnd; ++setIt )
d->pages.push_back( new PageViewItem( *setIt ) ); d->items.push_back( new PageViewItem( *setIt ) );
// invalidate layout // invalidate layout
d->dirtyLayout = true; d->dirtyLayout = true;
@ -233,12 +233,12 @@ void PageView::pageSetCurrent( int pageNumber, const QRect & /*viewport*/ )
// select next page // select next page
d->vectorIndex = 0; d->vectorIndex = 0;
d->activeItem = 0; d->activeItem = 0;
QValueVector< PageViewItem * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end(); QValueVector< PageViewItem * >::iterator iIt = d->items.begin(), iEnd = d->items.end();
for ( ; pIt != pEnd; ++pIt ) for ( ; iIt != iEnd; ++iIt )
{ {
if ( (*pIt)->pageNumber() == pageNumber ) if ( (*iIt)->pageNumber() == pageNumber )
{ {
d->activeItem = *pIt; d->activeItem = *iIt;
break; break;
} }
d->vectorIndex ++; d->vectorIndex ++;
@ -263,11 +263,14 @@ void PageView::pageSetCurrent( int pageNumber, const QRect & /*viewport*/ )
void PageView::notifyPixmapChanged( int pageNumber ) void PageView::notifyPixmapChanged( int pageNumber )
{ {
QValueVector< PageViewItem * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end(); QValueVector< PageViewItem * >::iterator iIt = d->items.begin(), iEnd = d->items.end();
for ( ; pIt != pEnd; ++pIt ) for ( ; iIt != iEnd; ++iIt )
if ( (*pIt)->pageNumber() == pageNumber ) if ( (*iIt)->pageNumber() == pageNumber )
{ {
updateContents( (*pIt)->geometry() ); // update item's rectangle plus the little outline
QRect expandedRect = (*iIt)->geometry();
expandedRect.addCoords( -1, -1, 3, 3 );
updateContents( expandedRect );
break; break;
} }
} }
@ -364,13 +367,13 @@ void PageView::viewportPaintEvent( QPaintEvent * pe )
// 4) Layer 3: overlays // 4) Layer 3: overlays
#if 1 #if 1
// only a test to try selecting under alpha items // only a test to try selecting under alpha items
QValueVector< PageViewItem * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end(); QValueVector< PageViewItem * >::iterator iIt = d->items.begin(), iEnd = d->items.end();
for ( ; pIt != pEnd; ++pIt ) for ( ; iIt != iEnd; ++iIt )
{ {
// check if a piece of the page intersects the contents rect // check if a piece of the page intersects the contents rect
if ( (*pIt)->geometry().intersects( contentsRect ) ) if ( (*iIt)->geometry().intersects( contentsRect ) )
{ {
PageViewItem * item = *pIt; PageViewItem * item = *iIt;
QRect pixmapGeometry = item->geometry(); QRect pixmapGeometry = item->geometry();
pixmapGeometry.setWidth( QMIN( pixmapGeometry.width(), 74 ) ); pixmapGeometry.setWidth( QMIN( pixmapGeometry.width(), 74 ) );
pixmapGeometry.setHeight( QMIN( pixmapGeometry.height(), 74 ) ); pixmapGeometry.setHeight( QMIN( pixmapGeometry.height(), 74 ) );
@ -432,14 +435,14 @@ void PageView::keyPressEvent( QKeyEvent * e )
verticalScrollBar()->subtractLine(); verticalScrollBar()->subtractLine();
// if in single page mode and at the top of the screen, go to previous page // if in single page mode and at the top of the screen, go to previous page
else if ( d->vectorIndex > 0 ) else if ( d->vectorIndex > 0 )
d->document->slotSetCurrentPage( d->pages[ d->vectorIndex - 1 ]->pageNumber() ); d->document->slotSetCurrentPage( d->items[ d->vectorIndex - 1 ]->pageNumber() );
break; break;
case Key_Down: case Key_Down:
if ( Settings::viewContinous() || verticalScrollBar()->value() < verticalScrollBar()->maxValue() ) if ( Settings::viewContinous() || verticalScrollBar()->value() < verticalScrollBar()->maxValue() )
verticalScrollBar()->addLine(); verticalScrollBar()->addLine();
// if in single page mode and at the bottom of the screen, go to next page // if in single page mode and at the bottom of the screen, go to next page
else if ( d->vectorIndex < (int)d->pages.count() - 1 ) else if ( d->vectorIndex < (int)d->items.count() - 1 )
d->document->slotSetCurrentPage( d->pages[ d->vectorIndex + 1 ]->pageNumber() ); d->document->slotSetCurrentPage( d->items[ d->vectorIndex + 1 ]->pageNumber() );
break; break;
case Key_Left: case Key_Left:
horizontalScrollBar()->subtractLine(); horizontalScrollBar()->subtractLine();
@ -686,7 +689,7 @@ void PageView::contentsMouseReleaseEvent( QMouseEvent * e )
break; break;
case MouseSelText: case MouseSelText:
if ( leftButton && !d->mouseSelectionRect.isNull() ) if ( leftButton && d->mouseSelectionRect.width() > 2 && d->mouseSelectionRect.height() > 2 )
{ {
// request the textpage if there isn't one // request the textpage if there isn't one
const KPDFPage * kpdfPage = d->mouseSelectionItem->page(); const KPDFPage * kpdfPage = d->mouseSelectionItem->page();
@ -719,7 +722,7 @@ void PageView::contentsMouseReleaseEvent( QMouseEvent * e )
if ( leftButton && !d->mouseSelectionRect.isNull() ) if ( leftButton && !d->mouseSelectionRect.isNull() )
{ {
QRect relativeRect = d->mouseSelectionRect.normalize(); QRect relativeRect = d->mouseSelectionRect.normalize();
if ( relativeRect.width() > 2 && relativeRect.height() > 2 ) if ( relativeRect.width() > 4 && relativeRect.height() > 4 )
{ {
// grab rendered page into the pixmap // grab rendered page into the pixmap
QPixmap copyPix( relativeRect.width(), relativeRect.height() ); QPixmap copyPix( relativeRect.width(), relativeRect.height() );
@ -784,14 +787,14 @@ void PageView::wheelEvent( QWheelEvent *e )
else if ( delta <= -120 && !Settings::viewContinous() && vScroll == verticalScrollBar()->maxValue() ) else if ( delta <= -120 && !Settings::viewContinous() && vScroll == verticalScrollBar()->maxValue() )
{ {
// go to next page // go to next page
if ( d->vectorIndex < (int)d->pages.count() - 1 ) if ( d->vectorIndex < (int)d->items.count() - 1 )
d->document->slotSetCurrentPage( d->pages[ d->vectorIndex + 1 ]->pageNumber() ); d->document->slotSetCurrentPage( d->items[ d->vectorIndex + 1 ]->pageNumber() );
} }
else if ( delta >= 120 && !Settings::viewContinous() && vScroll == verticalScrollBar()->minValue() ) else if ( delta >= 120 && !Settings::viewContinous() && vScroll == verticalScrollBar()->minValue() )
{ {
// go to prev page // go to prev page
if ( d->vectorIndex > 0 ) if ( d->vectorIndex > 0 )
d->document->slotSetCurrentPage( d->pages[ d->vectorIndex - 1 ]->pageNumber() ); d->document->slotSetCurrentPage( d->items[ d->vectorIndex - 1 ]->pageNumber() );
} }
else else
QScrollView::wheelEvent( e ); QScrollView::wheelEvent( e );
@ -821,13 +824,13 @@ void PageView::paintItems( QPainter * p, const QRect & contentsRect )
// create a region from wich we'll subtract painted rects // create a region from wich we'll subtract painted rects
QRegion remainingArea( contentsRect ); QRegion remainingArea( contentsRect );
QValueVector< PageViewItem * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end(); QValueVector< PageViewItem * >::iterator iIt = d->items.begin(), iEnd = d->items.end();
for ( ; pIt != pEnd; ++pIt ) for ( ; iIt != iEnd; ++iIt )
{ {
// check if a piece of the page intersects the contents rect // check if a piece of the page intersects the contents rect
if ( (*pIt)->geometry().intersects( checkRect ) ) if ( (*iIt)->geometry().intersects( checkRect ) )
{ {
PageViewItem * item = *pIt; PageViewItem * item = *iIt;
QRect pixmapGeometry = item->geometry(); QRect pixmapGeometry = item->geometry();
// translate the painter so we draw top-left pixmap corner in 0,0 // translate the painter so we draw top-left pixmap corner in 0,0
@ -923,10 +926,10 @@ void PageView::updateItemSize( PageViewItem * item, int colWidth, int rowHeight
PageViewItem * PageView::pickItemOnPoint( int x, int y ) PageViewItem * PageView::pickItemOnPoint( int x, int y )
{ {
PageViewItem * item = 0; PageViewItem * item = 0;
QValueVector< PageViewItem * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end(); QValueVector< PageViewItem * >::iterator iIt = d->items.begin(), iEnd = d->items.end();
for ( ; pIt != pEnd; ++pIt ) for ( ; iIt != iEnd; ++iIt )
{ {
PageViewItem * i = *pIt; PageViewItem * i = *iIt;
const QRect & r = i->geometry(); const QRect & r = i->geometry();
if ( x < r.right() && x > r.left() && y < r.bottom() ) if ( x < r.right() && x > r.left() && y < r.bottom() )
{ {
@ -1056,8 +1059,8 @@ void PageView::updateZoom( ZoomMode newZoomMode )
void PageView::updateZoomText() void PageView::updateZoomText()
{ {
// use current page zoom as zoomFactor if in ZoomFit/* mode // use current page zoom as zoomFactor if in ZoomFit/* mode
if ( d->zoomMode != ZoomFixed && d->pages.count() > 0 ) if ( d->zoomMode != ZoomFixed && d->items.count() > 0 )
d->zoomFactor = d->activeItem ? d->activeItem->zoomFactor() : d->pages[0]->zoomFactor(); d->zoomFactor = d->activeItem ? d->activeItem->zoomFactor() : d->items[0]->zoomFactor();
float newFactor = d->zoomFactor; float newFactor = d->zoomFactor;
d->aZoom->clear(); d->aZoom->clear();
@ -1103,18 +1106,51 @@ void PageView::slotRelayoutPages()
// called by: pageSetup, viewportResizeEvent, slotTwoPagesToggled, slotContinousToggled, updateZoom // called by: pageSetup, viewportResizeEvent, slotTwoPagesToggled, slotContinousToggled, updateZoom
{ {
// set an empty container if we have no pages // set an empty container if we have no pages
int pageCount = d->pages.count(); int pageCount = d->items.count();
if ( pageCount < 1 ) if ( pageCount < 1 )
{ {
resizeContents( 0, 0 ); resizeContents( 0, 0 );
return; return;
} }
// common iterator used in this method and viewport parameters
QValueVector< PageViewItem * >::iterator iIt, iEnd = d->items.end();
int viewportWidth = visibleWidth(), int viewportWidth = visibleWidth(),
viewportHeight = visibleHeight(), viewportHeight = visibleHeight(),
viewportCenterX = contentsX() + viewportWidth / 2,
viewportCenterY = contentsY() + viewportHeight / 2,
fullWidth = 0, fullWidth = 0,
fullHeight = 0; fullHeight = 0;
QRect viewportRect( contentsX(), contentsY(), viewportWidth, viewportHeight );
// look for the item closest to viewport center and the relative position
// between the item and the viewport center (for viewport restoring at end)
PageViewItem * focusedPage = 0;
float focusedX = 0.5,
focusedY = 0.0,
minDistance = -1.0;
// find the page nearest to viewport center
for ( iIt = d->items.begin(); iIt != iEnd; ++iIt )
{
const QRect & geometry = (*iIt)->geometry();
if ( geometry.intersects( viewportRect ) )
{
// compute distance between item center and viewport center
float distance = hypotf( geometry.left() + geometry.width() / 2 - viewportCenterX,
geometry.top() + geometry.height() / 2 - viewportCenterY );
if ( distance >= minDistance && minDistance != -1.0 )
continue;
focusedPage = *iIt;
minDistance = distance;
if ( geometry.height() > 0 && geometry.width() > 0 )
{
focusedX = ( viewportCenterX - geometry.left() ) / (float)geometry.width();
focusedY = ( viewportCenterY - geometry.top() ) / (float)geometry.height();
}
}
}
// set all items geometry and resize contents. handle 'continous' and 'single' modes separately
if ( Settings::viewContinous() ) if ( Settings::viewContinous() )
{ {
// Here we find out column's width and row's height to compute a table // Here we find out column's width and row's height to compute a table
@ -1132,10 +1168,9 @@ void PageView::slotRelayoutPages()
// 1) find the maximum columns width and rows height for a grid in // 1) find the maximum columns width and rows height for a grid in
// which each page must well-fit inside a cell // which each page must well-fit inside a cell
QValueVector< PageViewItem * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end(); for ( iIt = d->items.begin(); iIt != iEnd; ++iIt )
for ( ; pIt != pEnd; ++pIt )
{ {
PageViewItem * item = *pIt; PageViewItem * item = *iIt;
// update internal page size (leaving a little margin in case of Fit* modes) // update internal page size (leaving a little margin in case of Fit* modes)
updateItemSize( item, colWidth[ cIdx ] - 10, viewportHeight - 10 ); updateItemSize( item, colWidth[ cIdx ] - 10, viewportHeight - 10 );
// find row's maximum height and column's max width // find row's maximum height and column's max width
@ -1156,9 +1191,9 @@ void PageView::slotRelayoutPages()
insertY = 10; //TODO take d->zoomFactor into account (2+4*x) insertY = 10; //TODO take d->zoomFactor into account (2+4*x)
cIdx = 0; cIdx = 0;
rIdx = 0; rIdx = 0;
for ( pIt = d->pages.begin(); pIt != pEnd; ++pIt ) for ( iIt = d->items.begin(); iIt != iEnd; ++iIt )
{ {
PageViewItem * item = *pIt; PageViewItem * item = *iIt;
int cWidth = colWidth[ cIdx ], int cWidth = colWidth[ cIdx ],
rHeight = rowHeight[ rIdx ]; rHeight = rowHeight[ rIdx ];
// center widget inside 'cells' // center widget inside 'cells'
@ -1184,7 +1219,7 @@ void PageView::slotRelayoutPages()
} }
else // viewContinous is FALSE else // viewContinous is FALSE
{ {
PageViewItem * currentItem = d->activeItem ? d->activeItem : d->pages[0]; PageViewItem * currentItem = d->activeItem ? d->activeItem : d->items[0];
// setup varialbles for a 1(row) x N(columns) grid // setup varialbles for a 1(row) x N(columns) grid
int nCols = Settings::viewColumns(), int nCols = Settings::viewColumns(),
@ -1195,10 +1230,9 @@ void PageView::slotRelayoutPages()
colWidth[ i ] = viewportWidth / nCols; colWidth[ i ] = viewportWidth / nCols;
// 1) find out maximum area extension for the pages // 1) find out maximum area extension for the pages
QValueVector< PageViewItem * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end(); for ( iIt = d->items.begin(); iIt != iEnd; ++iIt )
for ( ; pIt != pEnd; ++pIt )
{ {
PageViewItem * item = *pIt; PageViewItem * item = *iIt;
if ( item == currentItem || (cIdx > 0 && cIdx < nCols) ) if ( item == currentItem || (cIdx > 0 && cIdx < nCols) )
{ {
// update internal page size (leaving a little margin in case of Fit* modes) // update internal page size (leaving a little margin in case of Fit* modes)
@ -1215,9 +1249,9 @@ void PageView::slotRelayoutPages()
// 2) hide all widgets except the displayable ones and dispose those // 2) hide all widgets except the displayable ones and dispose those
int insertX = 0; int insertX = 0;
cIdx = 0; cIdx = 0;
for ( pIt = d->pages.begin(); pIt != pEnd; ++pIt ) for ( iIt = d->items.begin(); iIt != iEnd; ++iIt )
{ {
PageViewItem * item = *pIt; PageViewItem * item = *iIt;
if ( item == currentItem || (cIdx > 0 && cIdx < nCols) ) if ( item == currentItem || (cIdx > 0 && cIdx < nCols) )
{ {
// center widget inside 'cells' // center widget inside 'cells'
@ -1236,24 +1270,27 @@ void PageView::slotRelayoutPages()
delete [] colWidth; delete [] colWidth;
} }
// 3) update scrollview's contents size and recenter view // 3) reset dirty state
int oldWidth = contentsWidth(), d->dirtyLayout = false;
oldHeight = contentsHeight();
if ( oldWidth != fullWidth || oldHeight != fullHeight ) // 4) update scrollview's contents size and recenter view
if ( fullWidth != contentsWidth() || fullHeight != contentsHeight() )
{ {
viewport()->setUpdatesEnabled( false );
resizeContents( fullWidth, fullHeight ); resizeContents( fullWidth, fullHeight );
if ( oldWidth > 0 && oldHeight > 0 ) if ( focusedPage )
center( fullWidth * (contentsX() + visibleWidth() / 2) / oldWidth, {
fullHeight * (contentsY() + visibleHeight() / 2) / oldHeight ); const QRect & geometry = focusedPage->geometry();
center( geometry.left() + (int)( focusedX * (float)geometry.width() ),
geometry.top() + (int)( focusedY * (float)geometry.height() ) );
}
else else
center( fullWidth / 2, 0 ); center( fullWidth / 2, 0 );
viewport()->setUpdatesEnabled( true );
} }
// 4) update the viewport since a relayout is a big operation // 5) update the whole viewport
updateContents(); updateContents();
// reset dirty state
d->dirtyLayout = false;
} }
void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop ) void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop )
@ -1264,10 +1301,10 @@ void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop )
visibleWidth(), visibleHeight() ); visibleWidth(), visibleHeight() );
// scroll from the top to the last visible thumbnail // scroll from the top to the last visible thumbnail
QValueVector< PageViewItem * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end(); QValueVector< PageViewItem * >::iterator iIt = d->items.begin(), iEnd = d->items.end();
for ( ; pIt != pEnd; ++pIt ) for ( ; iIt != iEnd; ++iIt )
{ {
PageViewItem * item = *pIt; PageViewItem * item = *iIt;
const QRect & itemRect = item->geometry(); const QRect & itemRect = item->geometry();
if ( viewportRect.intersects( itemRect ) ) if ( viewportRect.intersects( itemRect ) )
{ {