okular/kpdf/pageview.cpp
Enrico Ros 2cd31678ce Implemented Tobias requests on presentation mode. Made them all
configurable. Presentation mode is fully configurable now (at least with
bools). We should remove some options in the future. Changed some bits in
configuration dialog's "general" page.
CCMAIL:tokoe@kde.org

svn path=/branches/kpdf_experiments/kdegraphics/kpdf/; revision=374340
2004-12-30 22:43:15 +00:00

1472 lines
53 KiB
C++

/***************************************************************************
* Copyright (C) 2004 by Enrico Ros <eros.kde@email.it> *
* Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es> *
* *
* With portions of code from kpdf_pagewidget.cc by: *
* Copyright (C) 2002 by Wilco Greven <greven@kde.org> *
* Copyright (C) 2003 by Christophe Devriese *
* <Christophe.Devriese@student.kuleuven.ac.be> *
* Copyright (C) 2003 by Laurent Montel <montel@kde.org> *
* Copyright (C) 2003 by Dirk Mueller <mueller@kde.org> *
* Copyright (C) 2004 by James Ots <kde@jamesots.com> *
* *
* 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. *
***************************************************************************/
#include <qpainter.h>
#include <qtimer.h>
#include <qpushbutton.h>
#include <qapplication.h>
#include <qclipboard.h>
#include <kiconloader.h>
#include <kurldrag.h>
#include <kaction.h>
#include <kactioncollection.h>
#include <kpopupmenu.h>
#include <klocale.h>
#include <kfiledialog.h>
#include <kimageeffect.h>
#include <kimageio.h>
#include <kdebug.h>
#include <math.h>
#include <stdlib.h>
#include "pageview.h"
#include "pageviewutils.h"
#include "page.h"
#include "link.h"
#include "generator.h"
#include "settings.h"
#define ROUND(x) (int(x + 0.5))
// structure used internally by PageView for data storage
class PageViewPrivate
{
public:
// the document, current page and pages indices vector
KPDFDocument * document;
PageViewItem * activeItem; //equal to items[vectorIndex]
QValueVector< PageViewItem * > items;
int vectorIndex;
QValueList< PageViewItem * > visibleItems;
// view layout (columns and continous in Settings), zoom and mouse
PageView::ZoomMode zoomMode;
float zoomFactor;
PageView::MouseMode mouseMode;
QPoint mouseGrabPos;
QPoint mouseStartPos;
int mouseMidStartY;
bool mouseOnRect;
QRect mouseSelectionRect;
// other stuff
QTimer * delayTimer;
QTimer * scrollTimer;
int scrollIncrement;
bool dirtyLayout;
PageViewMessage * messageWindow; //in pageviewutils.h
// actions
KToggleAction * aMouseEdit;
KSelectAction * aZoom;
KToggleAction * aZoomFitWidth;
KToggleAction * aZoomFitPage;
KToggleAction * aZoomFitText;
KToggleAction * aViewTwoPages;
KToggleAction * aViewContinous;
};
/* PageView. What's in this file? -> quick overview.
* Code weight (in rows) and meaning:
* 160 - constructor and creating actions plus their connected slots (empty stuff)
* 70 - DocumentObserver inherited methodes (important)
* 200 - events: mouse, keyboard, drag/drop
* 170 - slotRelayoutPages: set contents of the scrollview on continous/single modes
* 100 - zoom: zooming pages in different ways, keeping update the toolbar actions, etc..
* other misc functions: only slotRequestVisiblePixmaps and pickItemOnPoint noticeable,
* and many insignificant stuff like this comment :-)
*/
PageView::PageView( QWidget *parent, KPDFDocument *document )
: QScrollView( parent, "KPDF::pageView", WStaticContents | WNoAutoErase )
{
// create and initialize private storage structure
d = new PageViewPrivate();
d->document = document;
d->activeItem = 0;
d->vectorIndex = -1;
d->zoomMode = ZoomFixed;
d->zoomFactor = 1.0;
d->mouseMode = MouseNormal;
d->mouseMidStartY = -1;
d->mouseOnRect = false;
d->delayTimer = 0;
d->scrollTimer = 0;
d->scrollIncrement = 0;
d->dirtyLayout = false;
d->messageWindow = new PageViewMessage(this);
// widget setup: setup focus, accept drops and track mouse
viewport()->setFocusProxy( this );
viewport()->setFocusPolicy( StrongFocus );
//viewport()->setPaletteBackgroundColor( Qt::white );
viewport()->setBackgroundMode( Qt::NoBackground );
setResizePolicy( Manual );
setAcceptDrops( true );
setDragAutoScroll( false );
viewport()->setMouseTracking( true );
// conntect the padding of the viewport to pixmaps requests
connect( this, SIGNAL(contentsMoving(int, int)), this, SLOT(slotRequestVisiblePixmaps(int, int)) );
// ### [RELEASE: REMOVE] show initial warning for dev_version > 2004-Dec-04
d->messageWindow->display( "kpdf_experiments is taking its way to HEAD! ;-)", PageViewMessage::Warning, 8000 );
// set a corner button to resize the view to the page size
// QPushButton * resizeButton = new QPushButton( viewport() );
// resizeButton->setPixmap( SmallIcon("crop") );
// setCornerWidget( resizeButton );
// resizeButton->setEnabled( false );
// connect(...);
}
PageView::~PageView()
{
delete d;
}
void PageView::setupActions( KActionCollection * ac )
{
// Zoom actions ( higher scales takes lots of memory! )
d->aZoom = new KSelectAction( i18n( "Zoom" ), "viewmag", 0, this, SLOT( slotZoom() ), ac, "zoom_to" );
d->aZoom->setEditable( true );
updateZoomText();
KStdAction::zoomIn( this, SLOT( slotZoomIn() ), ac, "zoom_in" );
KStdAction::zoomOut( this, SLOT( slotZoomOut() ), ac, "zoom_out" );
d->aZoomFitWidth = new KToggleAction( i18n("Fit to Page &Width"), "viewmagfit", 0, ac, "zoom_fit_width" );
connect( d->aZoomFitWidth, SIGNAL( toggled( bool ) ), SLOT( slotFitToWidthToggled( bool ) ) );
d->aZoomFitPage = new KToggleAction( i18n("Fit to &Page"), "viewmagfit", 0, ac, "zoom_fit_page" );
connect( d->aZoomFitPage, SIGNAL( toggled( bool ) ), SLOT( slotFitToPageToggled( bool ) ) );
d->aZoomFitText = new KToggleAction( i18n("Fit to &Text"), "viewmagfit", 0, ac, "zoom_fit_text" );
connect( d->aZoomFitText, SIGNAL( toggled( bool ) ), SLOT( slotFitToTextToggled( bool ) ) );
// View-Layout actions
d->aViewTwoPages = new KToggleAction( i18n("Two Pages"), "view_left_right", 0, ac, "view_twopages" );
connect( d->aViewTwoPages, SIGNAL( toggled( bool ) ), SLOT( slotTwoPagesToggled( bool ) ) );
d->aViewTwoPages->setChecked( Settings::viewColumns() > 1 );
d->aViewContinous = new KToggleAction( i18n("Continous"), "view_text", 0, ac, "view_continous" );
connect( d->aViewContinous, SIGNAL( toggled( bool ) ), SLOT( slotContinousToggled( bool ) ) );
d->aViewContinous->setChecked( Settings::viewContinous() );
// Mouse-Mode actions
KToggleAction * mn = new KRadioAction( i18n("Normal"), "mouse", 0, this, SLOT( slotSetMouseNormal() ), ac, "mouse_drag" );
mn->setExclusiveGroup( "MouseType" );
mn->setChecked( true );
KToggleAction * mz = new KRadioAction( i18n("Zoom Tool"), "viewmag", 0, this, SLOT( slotSetMouseZoom() ), ac, "mouse_zoom" );
mz->setExclusiveGroup( "MouseType" );
KToggleAction * mst = new KRadioAction( i18n("Select"), "frame_edit", 0, this, SLOT( slotSetMouseSelect() ), ac, "mouse_select" );
mst->setExclusiveGroup( "MouseType" );
d->aMouseEdit = new KRadioAction( i18n("Draw"), "edit", 0, this, SLOT( slotSetMouseDraw() ), ac, "mouse_draw" );
d->aMouseEdit->setExclusiveGroup("MouseType");
d->aMouseEdit->setEnabled( false ); // implement feature before removing this line
// Other actions
KAction * su = new KAction( i18n("Scroll Up"), 0, this, SLOT( slotScrollUp() ), ac, "view_scroll_up" );
su->setShortcut( "Shift+Up" );
KAction * sd = new KAction( i18n("Scroll Down"), 0, this, SLOT( slotScrollDown() ), ac, "view_scroll_down" );
sd->setShortcut( "Shift+Down" );
}
void PageView::setZoomFitWidth()
{
d->zoomMode = ZoomFitWidth;
Settings::setViewColumns( 1 );
d->aZoomFitWidth->setChecked( true );
d->aZoomFitPage->setChecked( false );
d->aZoomFitText->setChecked( false );
d->aViewTwoPages->setChecked( false );
viewport()->setUpdatesEnabled( false );
slotRelayoutPages();
viewport()->setUpdatesEnabled( true );
updateContents();
updateZoomText();
}
//BEGIN KPDFDocumentObserver inherited methods
void PageView::pageSetup( const QValueVector<KPDFPage*> & pageSet, bool documentChanged )
{
// reuse current pages if nothing new
if ( ( pageSet.count() == d->items.count() ) && !documentChanged )
{
int count = pageSet.count();
for ( int i = 0; (i < count) && !documentChanged; i++ )
if ( (int)pageSet[i]->number() != d->items[i]->pageNumber() )
documentChanged = true;
if ( !documentChanged )
return;
}
// delete all widgets (one for each page in pageSet)
QValueVector< PageViewItem * >::iterator dIt = d->items.begin(), dEnd = d->items.end();
for ( ; dIt != dEnd; ++dIt )
delete *dIt;
d->items.clear();
d->activeItem = 0;
// create children widgets
QValueVector< KPDFPage * >::const_iterator setIt = pageSet.begin(), setEnd = pageSet.end();
for ( ; setIt != setEnd; ++setIt )
d->items.push_back( new PageViewItem( *setIt ) );
// invalidate layout
d->dirtyLayout = true;
// OSD to display pages
if ( documentChanged && pageSet.count() > 0 && Settings::showOSD() )
d->messageWindow->display(
i18n(" Loaded a one page document.",
" Loaded a %n pages document.",
pageSet.count() ),
PageViewMessage::Info, 4000 );
}
void PageView::pageSetCurrent( int pageNumber, const QRect & viewport )
{
// select next page
d->vectorIndex = 0;
d->activeItem = 0;
QValueVector< PageViewItem * >::iterator iIt = d->items.begin(), iEnd = d->items.end();
for ( ; iIt != iEnd; ++iIt )
{
if ( (*iIt)->pageNumber() == pageNumber )
{
d->activeItem = *iIt;
break;
}
d->vectorIndex ++;
}
if ( !d->activeItem )
return;
// relayout in "Single Pages" mode or if a relayout is pending
if ( !Settings::viewContinous() || d->dirtyLayout )
slotRelayoutPages();
// center the view to see the selected page
if ( viewport.isNull() || true ) // FIXME take care of viewport
{
const QRect & r = d->activeItem->geometry();
center( r.left() + r.width() / 2, r.top() + visibleHeight() / 2 - 10 );
}
slotRequestVisiblePixmaps();
// update zoom text if in a ZoomFit/* zoom mode
if ( d->zoomMode != ZoomFixed )
updateZoomText();
}
bool PageView::canUnloadPixmap( int pageNumber )
{
// if the item is visible, forbid unloading
QValueList< PageViewItem * >::iterator vIt = d->visibleItems.begin(), vEnd = d->visibleItems.end();
for ( ; vIt != vEnd; ++vIt )
if ( (*vIt)->pageNumber() == pageNumber )
return false;
// if hidden premit unloading
return true;
}
void PageView::notifyPixmapChanged( int pageNumber )
{
QValueVector< PageViewItem * >::iterator iIt = d->items.begin(), iEnd = d->items.end();
for ( ; iIt != iEnd; ++iIt )
if ( (*iIt)->pageNumber() == pageNumber )
{
// update item's rectangle plus the little outline
QRect expandedRect = (*iIt)->geometry();
expandedRect.addCoords( -1, -1, 3, 3 );
updateContents( expandedRect );
break;
}
}
void PageView::notifyPixmapsCleared()
{
slotRequestVisiblePixmaps();
}
//END KPDFDocumentObserver inherited methods
//BEGIN widget events
void PageView::viewportPaintEvent( QPaintEvent * pe )
{
// create the rect into contents from the clipped screen rect
QRect viewportRect = viewport()->rect();
QRect contentsRect = pe->rect().intersect( viewportRect );
contentsRect.moveBy( contentsX(), contentsY() );
if ( !contentsRect.isValid() )
return;
// create the screen painter. a pixel painted ar contentsX,contentsY
// appears to the top-left corner of the scrollview.
QPainter screenPainter( viewport(), true );
screenPainter.translate( -contentsX(), -contentsY() );
// selectionRect is the normalized mouse selection rect
QRect selectionRect = d->mouseSelectionRect;
if ( !selectionRect.isNull() )
selectionRect = selectionRect.normalize();
// selectionRectInternal without the border
QRect selectionRectInternal = selectionRect;
selectionRectInternal.addCoords( 1, 1, -1, -1 );
// color for blending
QColor selBlendColor = (selectionRect.width() > 20 || selectionRect.height() > 20) ?
palette().active().highlight() : Qt::red;
// subdivide region into rects
QMemArray<QRect> allRects = pe->region().rects();
uint numRects = allRects.count();
// preprocess rects area to see if it worths or not using subdivision
uint summedArea = 0;
for ( uint i = 0; i < numRects; i++ )
{
const QRect & r = allRects[i];
summedArea += r.width() * r.height();
}
// very elementary check: SUMj(Region[j].area) is less than boundingRect.area
bool useSubdivision = summedArea < (0.7 * contentsRect.width() * contentsRect.height());
if ( !useSubdivision )
numRects = 1;
// iterate over the rects (only one loop if not using subdivision)
for ( uint i = 0; i < numRects; i++ )
{
if ( useSubdivision )
{
// set 'contentsRect' to a part of the sub-divided region
contentsRect = allRects[i].normalize().intersect( viewportRect );
contentsRect.moveBy( contentsX(), contentsY() );
if ( !contentsRect.isValid() )
continue;
}
// note: this check will take care of all things requiring alpha blending (not only selection)
bool wantCompositing = !selectionRect.isNull() && contentsRect.intersects( selectionRect );
if ( wantCompositing && !Settings::disableCompositing() )
{
// create pixmap and open a painter over it (contents{left,top} becomes pixmap {0,0})
QPixmap doubleBuffer( contentsRect.size() );
QPainter pixmapPainter( &doubleBuffer );
pixmapPainter.translate( -contentsRect.left(), -contentsRect.top() );
// 1) Layer 0: paint items and clear bg on unpainted rects
paintItems( &pixmapPainter, contentsRect );
// 2) Layer 1: pixmap manipulated areas
// 3) Layer 2: paint (blend) transparent selection
if ( !selectionRect.isNull() && selectionRect.intersects( contentsRect ) &&
!selectionRectInternal.contains( contentsRect ) )
{
QRect blendRect = selectionRectInternal.intersect( contentsRect );
// skip rectangles covered by the selection's border
if ( blendRect.isValid() )
{
// grab current pixmap into a new one to colorize contents
QPixmap blendedPixmap( blendRect.width(), blendRect.height() );
copyBlt( &blendedPixmap, 0,0, &doubleBuffer,
blendRect.left() - contentsRect.left(), blendRect.top() - contentsRect.top(),
blendRect.width(), blendRect.height() );
// blend selBlendColor into the background pixmap
QImage blendedImage = blendedPixmap.convertToImage();
KImageEffect::blend( selBlendColor.dark(140), blendedImage, 0.2 );
// copy the blended pixmap back to its place
pixmapPainter.drawPixmap( blendRect.left(), blendRect.top(), blendedImage );
}
// draw border (red if the selection is too small)
pixmapPainter.setPen( selBlendColor );
pixmapPainter.drawRect( selectionRect );
}
// 4) Layer 3: overlays
if ( Settings::debugDrawBoundaries() )
{
pixmapPainter.setPen( Qt::blue );
pixmapPainter.drawRect( contentsRect );
}
// finish painting and draw contents
pixmapPainter.end();
screenPainter.drawPixmap( contentsRect.left(), contentsRect.top(), doubleBuffer );
}
else
{
// 1) Layer 0: paint items and clear bg on unpainted rects
paintItems( &screenPainter, contentsRect );
// 2) Layer 1: opaque manipulated ares (filled / contours)
// 3) Layer 2: paint opaque selection
if ( !selectionRect.isNull() && selectionRect.intersects( contentsRect ) &&
!selectionRectInternal.contains( contentsRect ) )
{
screenPainter.setPen( palette().active().highlight().dark(110) );
screenPainter.drawRect( selectionRect );
}
// 4) Layer 3: overlays
if ( Settings::debugDrawBoundaries() )
{
screenPainter.setPen( Qt::red );
screenPainter.drawRect( contentsRect );
}
}
}
}
void PageView::viewportResizeEvent( QResizeEvent * )
{
// start a timer that will refresh the pixmap after 0.5s
if ( !d->delayTimer )
{
d->delayTimer = new QTimer( this );
connect( d->delayTimer, SIGNAL( timeout() ), this, SLOT( slotRelayoutPages() ) );
}
d->delayTimer->start( 400, true );
}
void PageView::keyPressEvent( QKeyEvent * e )
{
e->accept();
// move/scroll page by using keys
switch ( e->key() )
{
case Key_Up:
case Key_PageUp:
// if in single page mode and at the top of the screen, go to previous page
if ( Settings::viewContinous() || verticalScrollBar()->value() > verticalScrollBar()->minValue() )
{
if ( e->key() == Key_Up )
verticalScrollBar()->subtractLine();
else
verticalScrollBar()->subtractPage();
}
else if ( d->vectorIndex > 0 )
d->document->setCurrentPage( d->items[ d->vectorIndex - 1 ]->pageNumber() );
break;
case Key_Down:
case Key_PageDown:
// if in single page mode and at the bottom of the screen, go to next page
if ( Settings::viewContinous() || verticalScrollBar()->value() < verticalScrollBar()->maxValue() )
{
if ( e->key() == Key_Down )
verticalScrollBar()->addLine();
else
verticalScrollBar()->addPage();
}
else if ( d->vectorIndex < (int)d->items.count() - 1 )
d->document->setCurrentPage( d->items[ d->vectorIndex + 1 ]->pageNumber() );
break;
case Key_Left:
horizontalScrollBar()->subtractLine();
break;
case Key_Right:
horizontalScrollBar()->addLine();
break;
case Key_Shift:
case Key_Control:
if ( d->scrollTimer )
{
if ( d->scrollTimer->isActive() )
d->scrollTimer->stop();
else
slotAutoScoll();
return;
}
default:
e->ignore();
return;
}
// if a known key has been pressed, stop scrolling the page
if ( d->scrollTimer )
{
d->scrollIncrement = 0;
d->scrollTimer->stop();
}
}
void PageView::contentsMouseMoveEvent( QMouseEvent * e )
{
// if holding mouse mid button, perform zoom
if ( (e->state() & MidButton) && d->mouseMidStartY > 0 )
{
int deltaY = d->mouseMidStartY - e->globalPos().y();
d->mouseMidStartY = e->globalPos().y();
d->zoomFactor *= ( 1.0 + ( (double)deltaY / 500.0 ) );
updateZoom( ZoomRefreshCurrent );
// uncomment following line to force a complete redraw
viewport()->repaint( false );
return;
}
bool leftButton = e->state() & LeftButton;
switch ( d->mouseMode )
{
case MouseNormal:
if ( leftButton )
{
// drag page
if ( !d->mouseGrabPos.isNull() )
{
// scroll page by position increment
QPoint delta = d->mouseGrabPos - e->globalPos();
scrollBy( delta.x(), delta.y() );
d->mouseGrabPos = e->globalPos();
// if the page was scrolling, stop it
if ( d->scrollTimer )
{
d->scrollIncrement = 0;
d->scrollTimer->stop();
}
}
}
else // only hovering the page
{
updateCursor( e->pos() );
}
break;
case MouseZoom:
case MouseSelect:
// set second corner of selection in selection pageItem
if ( leftButton && !d->mouseSelectionRect.isNull() )
selectionEndPoint( e->x(), e->y() );
break;
case MouseEdit: // ? update graphics ?
break;
}
}
void PageView::contentsMousePressEvent( QMouseEvent * e )
{
// if pressing mid mouse button while not doing other things, begin 'comtinous zoom' mode
if ( (e->button() & MidButton) && d->mouseSelectionRect.isNull() )
{
d->mouseMidStartY = e->globalPos().y();
setCursor( sizeVerCursor );
return;
}
// handle mode dependant mouse press actions
bool leftButton = e->button() & LeftButton;
switch ( d->mouseMode )
{
case MouseNormal: // drag start / click / link following
if ( leftButton )
{
d->mouseStartPos = e->globalPos();
d->mouseGrabPos = d->mouseOnRect ? QPoint() : d->mouseStartPos;
if ( !d->mouseOnRect )
setCursor( sizeAllCursor );
}
break;
case MouseZoom:
case MouseSelect: // set first corner of the selection rect
if ( leftButton )
selectionStart( e->x(), e->y(), false );
break;
case MouseEdit: // ? place the beginning of [tool] ?
break;
}
}
void PageView::contentsMouseReleaseEvent( QMouseEvent * e )
{
// handle mode indepent mid buttom zoom
if ( (e->state() & MidButton) && d->mouseMidStartY > 0 )
{
d->mouseMidStartY = -1;
setCursor( arrowCursor );
return;
}
bool leftButton = e->button() & LeftButton,
rightButton = e->button() & RightButton;
switch ( d->mouseMode )
{
case MouseNormal:{ // do Follow Link or Display RMB
setCursor( arrowCursor );
PageViewItem * pageItem = pickItemOnPoint( e->x(), e->y() );
if ( leftButton && pageItem )
{
const KPDFPageRect * rect = pageItem->page()->getRect(
e->x() - pageItem->geometry().left(),
e->y() - pageItem->geometry().top()
);
if ( rect )
{
// release over a link
if ( rect->pointerType() == KPDFPageRect::Link )
{
const KPDFLink * link = static_cast< const KPDFLink * >( rect->pointer() );
d->document->processLink( link );
}
// release over an image
if ( rect->pointerType() == KPDFPageRect::Image )
{
}
}
else
{
// mouse not moved since press, so we have a click. select the page.
if ( e->globalPos() == d->mouseStartPos )
d->document->setCurrentPage( pageItem->pageNumber() );
}
}
else if ( rightButton )
{
if (pageItem) emit rightClick(pageItem->page(), e->globalPos());
else emit rightClick(0, e->globalPos());
}
// reset start position
d->mouseStartPos = QPoint();
}break;
case MouseZoom: // do ZOOM
if ( leftButton && !d->mouseSelectionRect.isNull() )
{
QRect selRect = d->mouseSelectionRect.normalize();
if ( selRect.width() < 4 || selRect.height() < 4 )
break;
// find out new zoom ratio and normalized view center (relative to the contentsRect)
double zoom = QMIN( (double)visibleWidth() / (double)selRect.width(), (double)visibleHeight() / (double)selRect.height() );
double nX = (double)(selRect.left() + selRect.right()) / (2.0 * (double)contentsWidth());
double nY = (double)(selRect.top() + selRect.bottom()) / (2.0 * (double)contentsHeight());
// zoom up to 400%
if ( d->zoomFactor <= 4.0 || zoom <= 1.0 )
{
d->zoomFactor *= zoom;
viewport()->setUpdatesEnabled( false );
updateZoom( ZoomRefreshCurrent );
viewport()->setUpdatesEnabled( true );
}
// recenter view and update the viewport
center( (int)(nX * contentsWidth()), (int)(nY * contentsHeight()) );
updateContents();
// hide message box and delete overlay window
selectionClear();
return;
}
// if in ZoomRect mode, right click zooms out
else if ( rightButton )
{
updateZoom( ZoomOut );
return;
}
break;
case MouseSelect:{ // do SELECT
if ( !leftButton || d->mouseSelectionRect.isNull() )
break;
QRect selectionRect = d->mouseSelectionRect.normalize();
if ( selectionRect.width() < 5 || selectionRect.height() < 5 )
break;
// grab text in selection by extracting it from all intersected pages
QString selectedText;
QValueVector< PageViewItem * >::iterator iIt = d->items.begin(), iEnd = d->items.end();
for ( ; iIt != iEnd; ++iIt )
{
PageViewItem * item = *iIt;
const QRect & itemRect = item->geometry();
if ( selectionRect.intersects( itemRect ) )
{
// request the textpage if there isn't one
const KPDFPage * kpdfPage = item->page();
if ( !kpdfPage->hasSearchPage() )
d->document->requestTextPage( kpdfPage->number() );
// grab text
QRect relativeRect = selectionRect.intersect( itemRect );
relativeRect.moveBy( -itemRect.left(), -itemRect.top() );
selectedText += kpdfPage->getTextInRect( relativeRect, item->zoomFactor() );
}
}
// popup that ask to copy:text and copy/save:image
KPopupMenu menu( this );
if ( !selectedText.isEmpty() )
{
menu.insertTitle( i18n( "Text ( %1 characters )" ).arg( selectedText.length() ) );
menu.insertItem( SmallIcon("editcopy"), i18n( "Copy to Clipboard" ), 1 );
}
menu.insertTitle( i18n( "Image ( %1 by %2 pixels )" ).arg( selectionRect.width() ).arg( selectionRect.height() ) );
menu.insertItem( SmallIcon("image"), i18n( "Copy to Clipboard" ), 2 );
menu.insertItem( SmallIcon("filesave"), i18n( "Save to File ..." ), 3 );
int choice = menu.exec( e->globalPos() );
// IMAGE operation choosen
if ( choice > 1 )
{
// renders page into a pixmap
QPixmap copyPix( selectionRect.width(), selectionRect.height() );
QPainter copyPainter( &copyPix );
copyPainter.translate( -selectionRect.left(), -selectionRect.top() );
paintItems( &copyPainter, selectionRect );
if ( choice == 2 )
{
// [2] copy pixmap to clipboard
QClipboard *cb = QApplication::clipboard();
cb->setPixmap( copyPix, QClipboard::Clipboard );
if ( cb->supportsSelection() )
cb->setPixmap( copyPix, QClipboard::Selection );
d->messageWindow->display( i18n( "Image [%1x%2] copied to clipboard." ).arg( copyPix.width() ).arg( copyPix.height() ) );
}
else
{
// [3] save pixmap to file
QString fileName = KFileDialog::getSaveFileName( QString::null, "image/png image/jpeg", this );
if ( fileName.isNull() )
d->messageWindow->display( i18n( "File not saved." ), PageViewMessage::Warning );
else
{
QString type( KImageIO::type( fileName ) );
if ( type.isNull() )
type = "PNG";
copyPix.save( fileName, type.latin1() );
d->messageWindow->display( i18n( "Image [%1x%2] saved to %3 file." ).arg( copyPix.width() ).arg( copyPix.height() ).arg( type ) );
}
}
}
// TEXT operation choosen
else if ( choice == 1 )
{
QClipboard *cb = QApplication::clipboard();
cb->setText( selectedText, QClipboard::Clipboard );
if ( cb->supportsSelection() )
cb->setText( selectedText, QClipboard::Selection );
}
// clear widget selection and invalidate rect
selectionClear();
}break;
case MouseEdit: // ? apply [tool] ?
break;
}
}
void PageView::wheelEvent( QWheelEvent *e )
{
int delta = e->delta(),
vScroll = verticalScrollBar()->value();
e->accept();
if ( (e->state() & ControlButton) == ControlButton ) {
if ( e->delta() < 0 )
slotZoomOut();
else
slotZoomIn();
}
else if ( delta <= -120 && !Settings::viewContinous() && vScroll == verticalScrollBar()->maxValue() )
{
// go to next page
if ( d->vectorIndex < (int)d->items.count() - 1 )
d->document->setCurrentPage( d->items[ d->vectorIndex + 1 ]->pageNumber() );
}
else if ( delta >= 120 && !Settings::viewContinous() && vScroll == verticalScrollBar()->minValue() )
{
// go to prev page
if ( d->vectorIndex > 0 )
{
d->document->setCurrentPage( d->items[ d->vectorIndex - 1 ]->pageNumber() );
verticalScrollBar()->setValue(verticalScrollBar()->maxValue());
}
}
else
QScrollView::wheelEvent( e );
QPoint cp = viewportToContents(e->pos());
updateCursor(cp);
}
void PageView::dragEnterEvent( QDragEnterEvent * ev )
{
ev->accept();
}
void PageView::dropEvent( QDropEvent * ev )
{
KURL::List lst;
if ( KURLDrag::decode( ev, lst ) )
emit urlDropped( lst.first() );
}
//END widget events
void PageView::paintItems( QPainter * p, const QRect & contentsRect )
{
// when checking if an Item is contained in contentsRect, instead of
// growing PageViewItems rects (for keeping outline into account), we
// grow the contentsRect
QRect checkRect = contentsRect;
checkRect.addCoords( -3, -3, 1, 1 );
// create a region from wich we'll subtract painted rects
QRegion remainingArea( contentsRect );
QValueVector< PageViewItem * >::iterator iIt = d->items.begin(), iEnd = d->items.end();
for ( ; iIt != iEnd; ++iIt )
{
// check if a piece of the page intersects the contents rect
if ( !(*iIt)->geometry().intersects( checkRect ) )
continue;
PageViewItem * item = *iIt;
QRect pixmapGeometry = item->geometry();
// translate the painter so we draw top-left pixmap corner in 0,0
p->save();
p->translate( pixmapGeometry.left(), pixmapGeometry.top() );
// item pixmap and outline geometry
QRect outlineGeometry = pixmapGeometry;
outlineGeometry.addCoords( -1, -1, 3, 3 );
// draw the page outline (little black border and 2px shadow)
if ( !pixmapGeometry.contains( contentsRect ) )
{
int pixmapWidth = pixmapGeometry.width(),
pixmapHeight = pixmapGeometry.height();
// draw simple outline
p->setPen( Qt::black );
p->drawRect( -1, -1, pixmapWidth + 2, pixmapHeight + 2 );
// draw bottom/right gradient
int levels = 2;
int r = Qt::gray.red() / (levels + 2),
g = Qt::gray.green() / (levels + 2),
b = Qt::gray.blue() / (levels + 2);
for ( int i = 0; i < levels; i++ )
{
p->setPen( QColor( r * (i+2), g * (i+2), b * (i+2) ) );
p->drawLine( i, i + pixmapHeight + 1, i + pixmapWidth + 1, i + pixmapHeight + 1 );
p->drawLine( i + pixmapWidth + 1, i, i + pixmapWidth + 1, i + pixmapHeight );
p->setPen( Qt::gray );
p->drawLine( -1, i + pixmapHeight + 1, i - 1, i + pixmapHeight + 1 );
p->drawLine( i + pixmapWidth + 1, -1, i + pixmapWidth + 1, i - 1 );
}
}
// draw the pixmap (note: this modifies the painter (not saved for performance))
if ( contentsRect.intersects( pixmapGeometry ) )
{
QRect pixmapRect = contentsRect.intersect( pixmapGeometry );
pixmapRect.moveBy( -pixmapGeometry.left(), -pixmapGeometry.top() );
int flags = PagePainter::Accessibility | PagePainter::EnhanceLinks |
PagePainter::EnhanceImages | PagePainter::Highlight;
PagePainter::paintPageOnPainter( item->page(), PAGEVIEW_ID, flags, p, pixmapRect,
pixmapGeometry.width(), pixmapGeometry.height() );
}
// remove painted area from 'remainingArea' and restore painter
remainingArea -= outlineGeometry.intersect( contentsRect );
p->restore();
}
// paint with background color the unpainted area
QMemArray<QRect> backRects = remainingArea.rects();
uint backRectsNumber = backRects.count();
for ( uint jr = 0; jr < backRectsNumber; jr++ )
p->fillRect( backRects[ jr ], Qt::gray );
}
void PageView::updateItemSize( PageViewItem * item, int colWidth, int rowHeight )
{
const KPDFPage * kpdfPage = item->page();
double width = kpdfPage->width(),
height = kpdfPage->height(),
zoom = d->zoomFactor;
if ( d->zoomMode == ZoomFixed )
{
width *= zoom;
height *= zoom;
item->setWHZ( (int)width, (int)height, d->zoomFactor );
}
else if ( d->zoomMode == ZoomFitWidth )
{
height = kpdfPage->ratio() * colWidth;
item->setWHZ( colWidth, (int)height, (double)colWidth / width );
}
else if ( d->zoomMode == ZoomFitPage )
{
double scaleW = (double)colWidth / (double)width;
double scaleH = (double)rowHeight / (double)height;
zoom = QMIN( scaleW, scaleH );
item->setWHZ( (int)(zoom * width), (int)(zoom * height), zoom );
}
#ifndef NDEBUG
else
kdDebug() << "calling updateItemSize with unrecognized d->zoomMode!" << endl;
#endif
}
PageViewItem * PageView::pickItemOnPoint( int x, int y )
{
PageViewItem * item = 0;
QValueVector< PageViewItem * >::iterator iIt = d->items.begin(), iEnd = d->items.end();
for ( ; iIt != iEnd; ++iIt )
{
PageViewItem * i = *iIt;
const QRect & r = i->geometry();
if ( x < r.right() && x > r.left() && y < r.bottom() )
{
if ( y > r.top() )
item = i;
break;
}
}
return item;
}
void PageView::selectionStart( int x, int y, bool /*aboveAll*/ )
{
d->mouseSelectionRect.setRect( x, y, 1, 1 );
// ensures page doesn't scroll
if ( d->scrollTimer )
{
d->scrollIncrement = 0;
d->scrollTimer->stop();
}
}
void PageView::selectionEndPoint( int x, int y )
{
// clip selection to the viewport
QRect viewportRect( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
x = QMAX( QMIN( x, viewportRect.right() ), viewportRect.left() ),
y = QMAX( QMIN( y, viewportRect.bottom() ), viewportRect.top() );
// if selection changed update rect
if ( d->mouseSelectionRect.right() != x || d->mouseSelectionRect.bottom() != y )
{
// send incremental paint events
QRect oldRect = d->mouseSelectionRect.normalize();
d->mouseSelectionRect.setRight( x );
d->mouseSelectionRect.setBottom( y );
QRect newRect = d->mouseSelectionRect.normalize();
// generate diff region: [ OLD.unite(NEW) - OLD.intersect(NEW) ]
QRegion compoundRegion = QRegion( oldRect ).unite( newRect );
if ( oldRect.intersects( newRect ) )
{
QRect intersection = oldRect.intersect( newRect );
intersection.addCoords( 1, 1, -1, -1 );
if ( intersection.width() > 20 && intersection.height() > 20 )
compoundRegion -= intersection;
}
// tassellate region with rects and enqueue paint events
QMemArray<QRect> rects = compoundRegion.rects();
for ( uint i = 0; i < rects.count(); i++ )
updateContents( rects[i] );
}
}
void PageView::selectionClear()
{
updateContents( d->mouseSelectionRect.normalize() );
d->mouseSelectionRect.setCoords( 0, 0, -1, -1 );
}
void PageView::updateZoom( ZoomMode newZoomMode )
{
if ( newZoomMode == ZoomFixed )
{
if ( d->aZoom->currentItem() == 0 )
newZoomMode = ZoomFitWidth;
else if ( d->aZoom->currentItem() == 1 )
newZoomMode = ZoomFitPage;
}
float newFactor = d->zoomFactor;
KAction * checkedZoomAction = 0;
switch ( newZoomMode )
{
case ZoomFixed:{ //ZoomFixed case
QString z = d->aZoom->currentText();
newFactor = KGlobal::locale()->readNumber( z.remove( z.find( '%' ), 1 ) ) / 100.0;
}break;
case ZoomIn:
newFactor += (newFactor > 0.99) ? ( newFactor > 1.99 ? 0.5 : 0.2 ) : 0.1;
newZoomMode = ZoomFixed;
break;
case ZoomOut:
newFactor -= (newFactor > 0.99) ? ( newFactor > 1.99 ? 0.5 : 0.2 ) : 0.1;
newZoomMode = ZoomFixed;
break;
case ZoomFitWidth:
checkedZoomAction = d->aZoomFitWidth;
break;
case ZoomFitPage:
checkedZoomAction = d->aZoomFitPage;
break;
case ZoomFitText:
checkedZoomAction = d->aZoomFitText;
break;
case ZoomRefreshCurrent:
newZoomMode = ZoomFixed;
d->zoomFactor = -1;
break;
}
if ( newFactor > 4.0 )
newFactor = 4.0;
if ( newFactor < 0.1 )
newFactor = 0.1;
if ( newZoomMode != d->zoomMode || (newZoomMode == ZoomFixed && newFactor != d->zoomFactor ) )
{
// rebuild layout and update the whole viewport
d->zoomMode = newZoomMode;
d->zoomFactor = newFactor;
slotRelayoutPages();
// request pixmaps
slotRequestVisiblePixmaps();
// update zoom text
updateZoomText();
// update actions checked state
d->aZoomFitWidth->setChecked( checkedZoomAction == d->aZoomFitWidth );
d->aZoomFitPage->setChecked( checkedZoomAction == d->aZoomFitPage );
d->aZoomFitText->setChecked( checkedZoomAction == d->aZoomFitText );
}
}
void PageView::updateZoomText()
{
// use current page zoom as zoomFactor if in ZoomFit/* mode
if ( d->zoomMode != ZoomFixed && d->items.count() > 0 )
d->zoomFactor = d->activeItem ? d->activeItem->zoomFactor() : d->items[0]->zoomFactor();
float newFactor = d->zoomFactor;
d->aZoom->clear();
// add items that describe fit actions
QStringList translated;
translated << i18n("Fit Width") << i18n("Fit Page"); // << i18n("Fit Text");
// add percent items
QString double_oh( "00" );
const float zoomValue[10] = { 0.125, 0.25, 0.333, 0.5, 0.667, 0.75, 1, 1.25, 1.50, 2 };
int idx = 0,
selIdx = 2; // use 3 if "fit text" present
bool inserted = false; //use: "d->zoomMode != ZoomFixed" to hide Fit/* zoom ratio
while ( idx < 10 || !inserted )
{
float value = idx < 10 ? zoomValue[ idx ] : newFactor;
if ( !inserted && newFactor < (value - 0.0001) )
value = newFactor;
else
idx ++;
if ( value > (newFactor - 0.0001) && value < (newFactor + 0.0001) )
inserted = true;
if ( !inserted )
selIdx++;
QString localValue( KGlobal::locale()->formatNumber( value * 100.0, 2 ) );
localValue.remove( KGlobal::locale()->decimalSymbol() + double_oh );
translated << QString( "%1%" ).arg( localValue );
}
d->aZoom->setItems( translated );
// select current item in list
if ( d->zoomMode == ZoomFitWidth )
selIdx = 0;
else if ( d->zoomMode == ZoomFitPage )
selIdx = 1;
else if ( d->zoomMode == ZoomFitText )
selIdx = 2;
d->aZoom->setCurrentItem( selIdx );
}
void PageView::updateCursor( const QPoint &p )
{
// detect the underlaying page (if present)
PageViewItem * pageItem = pickItemOnPoint( p.x(), p.y() );
if ( pageItem )
{
int pageX = p.x() - pageItem->geometry().left(),
pageY = p.y() - pageItem->geometry().top();
// check if over a KPDFPageRect
bool onRect = pageItem->page()->hasLink( pageX, pageY );
if ( onRect != d->mouseOnRect )
setCursor( (d->mouseOnRect = onRect) ? pointingHandCursor : arrowCursor );
}
else
{
// if there's no page over the cursor and we were showing the pointingHandCursor
// go back to the normal one
if ( d->mouseOnRect )
{
d->mouseOnRect = false;
setCursor( arrowCursor );
}
}
}
//BEGIN private SLOTS
void PageView::slotRelayoutPages()
// called by: pageSetup, viewportResizeEvent, slotTwoPagesToggled, slotContinousToggled, updateZoom
{
// set an empty container if we have no pages
int pageCount = d->items.count();
if ( pageCount < 1 )
{
resizeContents( 0, 0 );
return;
}
// common iterator used in this method and viewport parameters
QValueVector< PageViewItem * >::iterator iIt, iEnd = d->items.end();
int viewportWidth = visibleWidth(),
viewportHeight = visibleHeight(),
viewportCenterX = contentsX() + viewportWidth / 2,
viewportCenterY = contentsY() + viewportHeight / 2,
fullWidth = 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;
double 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
double distance = hypot( 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 = (double)( viewportCenterX - geometry.left() ) / (double)geometry.width();
focusedY = (double)( viewportCenterY - geometry.top() ) / (double)geometry.height();
}
}
}
// set all items geometry and resize contents. handle 'continous' and 'single' modes separately
if ( Settings::viewContinous() )
{
// Here we find out column's width and row's height to compute a table
// so we can place widgets 'centered in virtual cells'.
int nCols = Settings::viewColumns(),
nRows = (int)ceilf( (float)pageCount / (float)nCols ),
* colWidth = new int[ nCols ],
* rowHeight = new int[ nRows ],
cIdx = 0,
rIdx = 0;
for ( int i = 0; i < nCols; i++ )
colWidth[ i ] = viewportWidth / nCols;
for ( int i = 0; i < nRows; i++ )
rowHeight[ i ] = 0;
// 1) find the maximum columns width and rows height for a grid in
// which each page must well-fit inside a cell
for ( iIt = d->items.begin(); iIt != iEnd; ++iIt )
{
PageViewItem * item = *iIt;
// update internal page size (leaving a little margin in case of Fit* modes)
updateItemSize( item, colWidth[ cIdx ] - 10, viewportHeight - 10 );
// find row's maximum height and column's max width
if ( item->width() > colWidth[ cIdx ] )
colWidth[ cIdx ] = item->width();
if ( item->height() > rowHeight[ rIdx ] )
rowHeight[ rIdx ] = item->height();
// update col/row indices
if ( ++cIdx == nCols )
{
cIdx = 0;
rIdx++;
}
}
// 2) arrange widgets inside cells
int insertX = 0,
insertY = 10; //TODO take d->zoomFactor into account (2+4*x)
cIdx = 0;
rIdx = 0;
for ( iIt = d->items.begin(); iIt != iEnd; ++iIt )
{
PageViewItem * item = *iIt;
int cWidth = colWidth[ cIdx ],
rHeight = rowHeight[ rIdx ];
// center widget inside 'cells'
item->moveTo( insertX + (cWidth - item->width()) / 2,
insertY + (rHeight - item->height()) / 2 );
// advance col/row index
insertX += cWidth;
if ( ++cIdx == nCols )
{
cIdx = 0;
rIdx++;
insertX = 0;
insertY += rHeight + 15; //(int)(5.0 + 15.0 * d->zoomFactor);
}
}
fullHeight = cIdx ? (insertY + rowHeight[ rIdx ] + 10) : insertY;
for ( int i = 0; i < nCols; i++ )
fullWidth += colWidth[ i ];
delete [] colWidth;
delete [] rowHeight;
}
else // viewContinous is FALSE
{
PageViewItem * currentItem = d->activeItem ? d->activeItem : d->items[0];
// setup varialbles for a 1(row) x N(columns) grid
int nCols = Settings::viewColumns(),
* colWidth = new int[ nCols ],
cIdx = 0;
fullHeight = viewportHeight;
for ( int i = 0; i < nCols; i++ )
colWidth[ i ] = viewportWidth / nCols;
// 1) find out maximum area extension for the pages
for ( iIt = d->items.begin(); iIt != iEnd; ++iIt )
{
PageViewItem * item = *iIt;
if ( item == currentItem || (cIdx > 0 && cIdx < nCols) )
{
// update internal page size (leaving a little margin in case of Fit* modes)
updateItemSize( item, colWidth[ cIdx ] - 10, viewportHeight - 10 );
// find row's maximum height and column's max width
if ( item->width() > colWidth[ cIdx ] )
colWidth[ cIdx ] = item->width();
if ( item->height() > fullHeight )
fullHeight = item->height();
cIdx++;
}
}
// 2) hide all widgets except the displayable ones and dispose those
int insertX = 0;
cIdx = 0;
for ( iIt = d->items.begin(); iIt != iEnd; ++iIt )
{
PageViewItem * item = *iIt;
if ( item == currentItem || (cIdx > 0 && cIdx < nCols) )
{
// center widget inside 'cells'
item->moveTo( insertX + (colWidth[ cIdx ] - item->width()) / 2,
(fullHeight - item->height()) / 2 );
// advance col index
insertX += colWidth[ cIdx ];
cIdx++;
} else
item->setGeometry( 0, 0, -1, -1 );
}
for ( int i = 0; i < nCols; i++ )
fullWidth += colWidth[ i ];
delete [] colWidth;
}
// 3) reset dirty state
d->dirtyLayout = false;
// 4) update scrollview's contents size and recenter view
if ( fullWidth != contentsWidth() || fullHeight != contentsHeight() )
{
bool prevUpdatesState = viewport()->isUpdatesEnabled();
viewport()->setUpdatesEnabled( false );
resizeContents( fullWidth, fullHeight );
if ( focusedPage )
{
const QRect & geometry = focusedPage->geometry();
center( geometry.left() + ROUND( focusedX * (double)geometry.width() ),
geometry.top() + ROUND( focusedY * (double)geometry.height() ) );
}
else
center( fullWidth / 2, 0 );
viewport()->setUpdatesEnabled( prevUpdatesState );
}
// 5) update the whole viewport
updateContents();
}
void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop )
{
// precalc view limits for intersecting with page coords inside the lOOp
QRect viewportRect( newLeft == -1 ? contentsX() : newLeft,
newTop == -1 ? contentsY() : newTop,
visibleWidth(), visibleHeight() );
// for each item, check if it intersects the viewport
d->visibleItems.clear();
QValueList< PixmapRequest * > requestedPixmaps;
QValueVector< PageViewItem * >::iterator iIt = d->items.begin(), iEnd = d->items.end();
for ( ; iIt != iEnd; ++iIt )
{
PageViewItem * i = *iIt;
if ( !viewportRect.intersects( i->geometry() ) )
continue;
d->visibleItems.push_back( i );
if ( !i->page()->hasPixmap( PAGEVIEW_ID, i->width(), i->height() ) )
requestedPixmaps.push_back( new PixmapRequest( PAGEVIEW_ID, i->pageNumber(), i->width(), i->height() ) );
}
// actually request pixmaps
if ( !requestedPixmaps.isEmpty() )
d->document->requestPixmaps( requestedPixmaps, true /*ASYNC*/ );
}
void PageView::slotAutoScoll()
{
// the first time create the timer
if ( !d->scrollTimer )
{
d->scrollTimer = new QTimer( this );
connect( d->scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScoll() ) );
}
// if scrollIncrement is zero, stop the timer
if ( !d->scrollIncrement )
{
d->scrollTimer->stop();
return;
}
// compute delay between timer ticks and scroll amount per tick
int index = abs( d->scrollIncrement ) - 1; // 0..9
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 };
d->scrollTimer->changeInterval( scrollDelay[ index ] );
scrollBy( 0, d->scrollIncrement > 0 ? scrollOffset[ index ] : -scrollOffset[ index ] );
}
void PageView::slotZoom()
{
setFocus();
updateZoom( ZoomFixed );
}
void PageView::slotZoomIn()
{
updateZoom( ZoomIn );
}
void PageView::slotZoomOut()
{
updateZoom( ZoomOut );
}
void PageView::slotFitToWidthToggled( bool on )
{
if ( on ) updateZoom( ZoomFitWidth );
}
void PageView::slotFitToPageToggled( bool on )
{
if ( on ) updateZoom( ZoomFitPage );
}
void PageView::slotFitToTextToggled( bool on )
{
if ( on ) updateZoom( ZoomFitText );
}
void PageView::slotTwoPagesToggled( bool on )
{
uint newColumns = on ? 2 : 1;
if ( Settings::viewColumns() != newColumns )
{
Settings::setViewColumns( newColumns );
if ( d->document->pages() > 0 )
slotRelayoutPages();
}
}
void PageView::slotContinousToggled( bool on )
{
if ( Settings::viewContinous() != on )
{
Settings::setViewContinous( on );
if ( d->document->pages() > 0 )
slotRelayoutPages();
}
}
void PageView::slotSetMouseNormal()
{
d->mouseMode = MouseNormal;
d->messageWindow->hide();
}
void PageView::slotSetMouseZoom()
{
d->mouseMode = MouseZoom;
d->messageWindow->display( i18n( "Select Zooming Area. Right-Click to zoom out." ), PageViewMessage::Info, -1 );
}
void PageView::slotSetMouseSelect()
{
d->mouseMode = MouseSelect;
d->messageWindow->display( i18n( "Draw a rectangle around the text/gfx to copy." ), PageViewMessage::Info, -1 );
}
void PageView::slotSetMouseDraw()
{
d->mouseMode = MouseEdit;
d->aMouseEdit->setChecked( true );
d->messageWindow->hide();
}
void PageView::slotScrollUp()
{
if ( d->scrollIncrement < -9 )
return;
d->scrollIncrement--;
slotAutoScoll();
setFocus();
}
void PageView::slotScrollDown()
{
if ( d->scrollIncrement > 9 )
return;
d->scrollIncrement++;
slotAutoScoll();
setFocus();
}
//END private SLOTS
#include "pageview.moc"