2004-09-26 23:39:39 +00:00
|
|
|
/***************************************************************************
|
2004-09-27 21:36:25 +00:00
|
|
|
* Copyright (C) 2004 by Enrico Ros <eros.kde@email.it> *
|
2004-09-26 23:39:39 +00:00
|
|
|
* Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es> *
|
2004-09-27 21:36:25 +00:00
|
|
|
* *
|
|
|
|
* 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> *
|
2004-09-26 23:39:39 +00:00
|
|
|
* *
|
|
|
|
* 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>
|
2004-10-14 20:21:59 +00:00
|
|
|
#include <qapplication.h>
|
|
|
|
#include <qclipboard.h>
|
2004-09-26 23:39:39 +00:00
|
|
|
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <kurldrag.h>
|
|
|
|
#include <kaction.h>
|
|
|
|
#include <kactioncollection.h>
|
2004-09-28 13:53:47 +00:00
|
|
|
#include <kpopupmenu.h>
|
2004-09-26 23:39:39 +00:00
|
|
|
#include <klocale.h>
|
|
|
|
#include <kconfigbase.h>
|
|
|
|
|
|
|
|
#include <math.h>
|
2004-10-06 00:05:49 +00:00
|
|
|
#include <stdlib.h>
|
2004-09-26 23:39:39 +00:00
|
|
|
|
|
|
|
#include "pageview.h"
|
|
|
|
#include "pixmapwidget.h"
|
|
|
|
#include "page.h"
|
|
|
|
|
|
|
|
|
|
|
|
// structure used internally by PageView for data storage
|
|
|
|
class PageViewPrivate
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// the document, current page and pages indices vector
|
|
|
|
KPDFDocument * document;
|
2004-09-27 21:36:25 +00:00
|
|
|
PageWidget * page; //equal to pages[vectorIndex]
|
2004-09-26 23:39:39 +00:00
|
|
|
QValueVector< PageWidget * > pages;
|
|
|
|
int vectorIndex;
|
|
|
|
|
|
|
|
// view layout, zoom and mouse
|
2004-09-27 21:36:25 +00:00
|
|
|
int viewColumns;
|
|
|
|
bool viewContinous;
|
2004-09-26 23:39:39 +00:00
|
|
|
PageView::ZoomMode zoomMode;
|
|
|
|
float zoomFactor;
|
|
|
|
PageView::MouseMode mouseMode;
|
|
|
|
QPoint mouseGrabPos;
|
2004-09-28 13:53:47 +00:00
|
|
|
QPoint mouseStartPos;
|
2004-09-26 23:39:39 +00:00
|
|
|
bool mouseOnLink;
|
2004-10-07 20:34:27 +00:00
|
|
|
PageWidget * mouseSelectionWidget;
|
2004-09-27 21:36:25 +00:00
|
|
|
|
|
|
|
// other stuff
|
2004-09-26 23:39:39 +00:00
|
|
|
QTimer *delayTimer;
|
2004-10-06 00:05:49 +00:00
|
|
|
QTimer *scrollTimer;
|
|
|
|
int scrollIncrement;
|
2004-09-30 18:04:09 +00:00
|
|
|
bool dirtyLayout;
|
2004-09-26 23:39:39 +00:00
|
|
|
|
|
|
|
// actions
|
|
|
|
KSelectAction *aZoom;
|
|
|
|
KToggleAction *aZoomFitWidth;
|
|
|
|
KToggleAction *aZoomFitPage;
|
|
|
|
KToggleAction *aZoomFitText;
|
2004-09-27 21:36:25 +00:00
|
|
|
KToggleAction *aViewTwoPages;
|
|
|
|
KToggleAction *aViewContinous;
|
2004-09-26 23:39:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2004-09-30 18:16:12 +00:00
|
|
|
/* 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 pickPageOnPoint noticeable,
|
|
|
|
* and many insignificant stuff like this comment :-)
|
2004-09-26 23:39:39 +00:00
|
|
|
*/
|
|
|
|
PageView::PageView( QWidget *parent, KPDFDocument *document )
|
2004-09-27 21:36:25 +00:00
|
|
|
: QScrollView( parent, "KPDF::pageView", WNoAutoErase | WStaticContents )
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
|
|
|
// create and initialize private storage structure
|
|
|
|
d = new PageViewPrivate();
|
|
|
|
d->document = document;
|
|
|
|
d->page = 0;
|
2004-10-02 14:30:30 +00:00
|
|
|
d->vectorIndex = -1;
|
2004-09-27 21:36:25 +00:00
|
|
|
d->viewColumns = 1;
|
|
|
|
d->viewContinous = false;
|
2004-10-02 14:30:30 +00:00
|
|
|
d->zoomMode = ZoomFixed;
|
2004-09-30 18:04:09 +00:00
|
|
|
d->zoomFactor = 1.0;
|
2004-09-26 23:39:39 +00:00
|
|
|
d->mouseMode = MouseNormal;
|
|
|
|
d->mouseOnLink = false;
|
2004-10-07 20:34:27 +00:00
|
|
|
d->mouseSelectionWidget = 0;
|
2004-09-26 23:39:39 +00:00
|
|
|
d->delayTimer = 0;
|
2004-10-06 00:05:49 +00:00
|
|
|
d->scrollTimer = 0;
|
|
|
|
d->scrollIncrement = 0;
|
2004-09-30 18:04:09 +00:00
|
|
|
d->dirtyLayout = false;
|
2004-09-27 21:36:25 +00:00
|
|
|
|
|
|
|
// dealing with (very) large areas so enable clipper
|
|
|
|
enableClipper( true );
|
2004-09-26 23:39:39 +00:00
|
|
|
|
2004-09-27 21:36:25 +00:00
|
|
|
// widget setup: setup focus, accept drops and track mouse
|
|
|
|
viewport()->setFocusProxy( this );
|
|
|
|
viewport()->setFocusPolicy( StrongFocus );
|
|
|
|
viewport()->setPaletteBackgroundColor( Qt::gray );
|
|
|
|
setResizePolicy( Manual );
|
2004-09-26 23:39:39 +00:00
|
|
|
setAcceptDrops( true );
|
2004-09-30 18:16:12 +00:00
|
|
|
setDragAutoScroll( false );
|
2004-09-26 23:39:39 +00:00
|
|
|
viewport()->setMouseTracking( true );
|
2004-09-27 21:36:25 +00:00
|
|
|
|
|
|
|
// conntect the padding of the viewport to pixmaps requests
|
|
|
|
connect( this, SIGNAL(contentsMoving(int, int)), this, SLOT(slotRequestVisiblePixmaps(int, int)) );
|
2004-09-26 23:39:39 +00:00
|
|
|
|
|
|
|
// set a corner button to resize the view to the page size
|
|
|
|
QPushButton * resizeButton = new QPushButton( viewport() );
|
2004-09-27 21:36:25 +00:00
|
|
|
resizeButton->setPixmap( SmallIcon("crop") );
|
2004-09-26 23:39:39 +00:00
|
|
|
setCornerWidget( resizeButton );
|
|
|
|
resizeButton->setEnabled( false );
|
|
|
|
// connect(...);
|
|
|
|
}
|
|
|
|
|
|
|
|
PageView::~PageView()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::setupActions( KActionCollection * ac, KConfigGroup * config )
|
|
|
|
{
|
2004-09-30 18:04:09 +00:00
|
|
|
// Zoom actions ( higher scales takes lots of memory! )
|
2004-09-30 18:16:12 +00:00
|
|
|
d->aZoom = new KSelectAction( i18n( "Zoom" ), "viewmag", 0, this, SLOT( slotZoom() ), ac, "zoom_to" );
|
2004-09-30 18:04:09 +00:00
|
|
|
d->aZoom->setEditable( true );
|
|
|
|
updateZoomText();
|
2004-09-26 23:39:39 +00:00
|
|
|
|
|
|
|
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 ) ) );
|
|
|
|
|
2004-09-30 18:16:12 +00:00
|
|
|
d->aZoomFitText = new KToggleAction( i18n("Fit to &Text"), "viewmagfit", 0, ac, "zoom_fit_text" );
|
2004-09-30 18:04:09 +00:00
|
|
|
connect( d->aZoomFitText, SIGNAL( toggled( bool ) ), SLOT( slotFitToTextToggled( bool ) ) );
|
|
|
|
|
2004-09-26 23:39:39 +00:00
|
|
|
// View-Layout actions
|
2004-09-27 21:36:25 +00:00
|
|
|
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( config->readBoolEntry( "ViewTwoPages", false ) );
|
|
|
|
slotTwoPagesToggled( d->aViewTwoPages->isChecked() );
|
2004-09-26 23:39:39 +00:00
|
|
|
|
2004-09-27 21:36:25 +00:00
|
|
|
d->aViewContinous = new KToggleAction( i18n("Continous"), "view_text", 0, ac, "view_continous" );
|
|
|
|
connect( d->aViewContinous, SIGNAL( toggled( bool ) ), SLOT( slotContinousToggled( bool ) ) );
|
|
|
|
d->aViewContinous->setChecked( config->readBoolEntry( "ViewContinous", true ) );
|
|
|
|
slotContinousToggled( d->aViewContinous->isChecked() );
|
2004-09-26 23:39:39 +00:00
|
|
|
|
|
|
|
// Mouse-Mode actions
|
2004-09-30 18:16:12 +00:00
|
|
|
KToggleAction * mn = new KRadioAction( i18n("Normal"), "mouse", 0, this, SLOT( slotSetMouseNormal() ), ac, "mouse_drag" );
|
2004-09-26 23:39:39 +00:00
|
|
|
mn->setExclusiveGroup("MouseType");
|
|
|
|
mn->setChecked( true );
|
|
|
|
|
2004-09-30 18:16:12 +00:00
|
|
|
KToggleAction * ms = new KRadioAction( i18n("Select"), "frame_edit", 0, this, SLOT( slotSetMouseSelect() ), ac, "mouse_select" );
|
2004-09-26 23:39:39 +00:00
|
|
|
ms->setExclusiveGroup("MouseType");
|
2004-09-30 18:16:12 +00:00
|
|
|
//ms->setEnabled( false ); // implement feature before removing this line
|
2004-09-26 23:39:39 +00:00
|
|
|
|
2004-09-30 18:16:12 +00:00
|
|
|
KToggleAction * md = new KRadioAction( i18n("Draw"), "edit", 0, this, SLOT( slotSetMouseDraw() ), ac, "mouse_draw" );
|
2004-09-26 23:39:39 +00:00
|
|
|
md->setExclusiveGroup("MouseType");
|
2004-09-30 18:16:12 +00:00
|
|
|
//md->setEnabled( false ); // implement feature before removing this line
|
2004-09-26 23:39:39 +00:00
|
|
|
|
|
|
|
// Other actions
|
2004-10-06 00:05:49 +00:00
|
|
|
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" );
|
|
|
|
|
2004-09-26 23:39:39 +00:00
|
|
|
KToggleAction * ss = new KToggleAction( i18n( "Show &Scrollbars" ), 0, ac, "show_scrollbars" );
|
|
|
|
ss->setCheckedState(i18n("Hide &Scrollbars"));
|
|
|
|
connect( ss, SIGNAL( toggled( bool ) ), SLOT( slotToggleScrollBars( bool ) ) );
|
|
|
|
|
|
|
|
ss->setChecked( config->readBoolEntry( "ShowScrollBars", true ) );
|
|
|
|
slotToggleScrollBars( ss->isChecked() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::saveSettings( KConfigGroup * config )
|
|
|
|
{
|
|
|
|
config->writeEntry( "ShowScrollBars", hScrollBarMode() == AlwaysOn );
|
2004-09-27 21:36:25 +00:00
|
|
|
config->writeEntry( "ViewTwoPages", d->aViewTwoPages->isChecked() );
|
|
|
|
config->writeEntry( "ViewContinous", d->aViewContinous->isChecked() );
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-10 12:42:42 +00:00
|
|
|
//BEGIN KPDFDocumentObserver inherited methods
|
2004-10-10 13:21:30 +00:00
|
|
|
void PageView::pageSetup( const QValueVector<KPDFPage*> & pageSet, bool documentChanged )
|
|
|
|
{
|
|
|
|
// reuse current pages if nothing new
|
|
|
|
if ( ( pageSet.count() == d->pages.count() ) && !documentChanged )
|
|
|
|
{
|
|
|
|
int count = pageSet.count();
|
|
|
|
for ( int i = 0; (i < count) && !documentChanged; i++ )
|
|
|
|
if ( (int)pageSet[i]->number() != d->pages[i]->pageNumber() )
|
|
|
|
documentChanged = true;
|
|
|
|
if ( !documentChanged )
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// delete all widgets (one for each page in pageSet)
|
2004-09-26 23:39:39 +00:00
|
|
|
QValueVector< PageWidget * >::iterator dIt = d->pages.begin(), dEnd = d->pages.end();
|
|
|
|
for ( ; dIt != dEnd; ++dIt )
|
|
|
|
delete *dIt;
|
|
|
|
d->pages.clear();
|
|
|
|
d->page = 0;
|
|
|
|
|
|
|
|
// create children widgets
|
|
|
|
QValueVector< KPDFPage * >::const_iterator setIt = pageSet.begin(), setEnd = pageSet.end();
|
|
|
|
for ( ; setIt != setEnd; ++setIt )
|
|
|
|
{
|
2004-09-27 21:36:25 +00:00
|
|
|
PageWidget * p = new PageWidget( viewport(), *setIt );
|
|
|
|
p->setFocusProxy( this );
|
2004-09-30 18:16:12 +00:00
|
|
|
p->setMouseTracking( true );
|
2004-09-26 23:39:39 +00:00
|
|
|
d->pages.push_back( p );
|
|
|
|
}
|
|
|
|
|
2004-09-27 21:36:25 +00:00
|
|
|
// invalidate layout
|
2004-09-30 18:04:09 +00:00
|
|
|
d->dirtyLayout = true;
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
2004-10-10 13:21:30 +00:00
|
|
|
void PageView::pageSetCurrent( int pageNumber, const QRect & /*viewport*/ )
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
2004-09-27 21:36:25 +00:00
|
|
|
// select next page
|
|
|
|
d->vectorIndex = 0;
|
|
|
|
d->page = 0;
|
2004-09-26 23:39:39 +00:00
|
|
|
QValueVector< PageWidget * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end();
|
|
|
|
for ( ; pIt != pEnd; ++pIt )
|
|
|
|
{
|
2004-09-27 21:36:25 +00:00
|
|
|
if ( (*pIt)->pageNumber() == pageNumber )
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
2004-09-27 21:36:25 +00:00
|
|
|
d->page = *pIt;
|
2004-09-26 23:39:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2004-09-27 21:36:25 +00:00
|
|
|
d->vectorIndex ++;
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
2004-09-30 18:16:12 +00:00
|
|
|
if ( !d->page )
|
|
|
|
return;
|
2004-09-26 23:39:39 +00:00
|
|
|
|
2004-10-10 13:21:30 +00:00
|
|
|
// relayout in "Single Pages" mode or if a relayout is pending
|
|
|
|
if ( !d->viewContinous || d->dirtyLayout )
|
2004-09-30 18:16:12 +00:00
|
|
|
slotRelayoutPages();
|
|
|
|
|
|
|
|
// center the view to see the selected page
|
2004-10-10 13:21:30 +00:00
|
|
|
// FIXME take care of viewport
|
2004-09-30 18:16:12 +00:00
|
|
|
int xPos = childX( d->page ) + d->page->widthHint() / 2,
|
2004-10-10 13:21:30 +00:00
|
|
|
yPos = childY( d->page );
|
2004-09-30 18:16:12 +00:00
|
|
|
center( xPos, yPos + visibleHeight() / 2 - 10 );
|
|
|
|
slotRequestVisiblePixmaps();
|
|
|
|
|
|
|
|
// update zoom text if in a ZoomFit/* zoom mode
|
|
|
|
if ( d->zoomMode != ZoomFixed )
|
|
|
|
updateZoomText();
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
2004-09-27 21:36:25 +00:00
|
|
|
void PageView::notifyPixmapChanged( int pageNumber )
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
2004-09-27 21:36:25 +00:00
|
|
|
QValueVector< PageWidget * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end();
|
|
|
|
for ( ; pIt != pEnd; ++pIt )
|
|
|
|
if ( (*pIt)->pageNumber() == pageNumber )
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
2004-09-27 21:36:25 +00:00
|
|
|
(*pIt)->update();
|
2004-09-26 23:39:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//END KPDFDocumentObserver inherited methods
|
|
|
|
|
2004-10-10 12:42:42 +00:00
|
|
|
//BEGIN widget events
|
2004-09-26 23:39:39 +00:00
|
|
|
void PageView::contentsMousePressEvent( QMouseEvent * e )
|
|
|
|
{
|
2004-10-06 00:05:49 +00:00
|
|
|
bool leftButton = e->button() & LeftButton,
|
|
|
|
rightButton = e->button() & RightButton;
|
2004-09-26 23:39:39 +00:00
|
|
|
switch ( d->mouseMode )
|
|
|
|
{
|
2004-10-06 00:05:49 +00:00
|
|
|
case MouseNormal: // drag start / click / link following
|
|
|
|
if ( leftButton )
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
2004-09-30 18:16:12 +00:00
|
|
|
d->mouseStartPos = e->globalPos();
|
2004-10-06 00:05:49 +00:00
|
|
|
if ( d->mouseOnLink )
|
2004-09-30 18:16:12 +00:00
|
|
|
d->mouseGrabPos = QPoint();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d->mouseGrabPos = d->mouseStartPos;
|
|
|
|
setCursor( sizeAllCursor );
|
|
|
|
}
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
2004-10-06 00:05:49 +00:00
|
|
|
else if ( rightButton )
|
2004-09-26 23:39:39 +00:00
|
|
|
emit rightClick();
|
|
|
|
break;
|
|
|
|
|
2004-10-07 20:34:27 +00:00
|
|
|
case MouseSelection: // set first corner of the selection rect
|
|
|
|
if ( leftButton )
|
|
|
|
{
|
|
|
|
if ( d->mouseSelectionWidget )
|
|
|
|
d->mouseSelectionWidget->clearSelection();
|
|
|
|
d->mouseSelectionWidget = 0;
|
|
|
|
PageWidget * page = pickPageOnPoint( e->x(), e->y() );
|
|
|
|
if ( page )
|
|
|
|
{
|
|
|
|
page->setBeginCorner( e->x() - childX( page ), e->y() - childY( page ) );
|
|
|
|
d->mouseSelectionWidget = page;
|
|
|
|
}
|
|
|
|
}
|
2004-09-30 18:16:12 +00:00
|
|
|
break;
|
2004-09-26 23:39:39 +00:00
|
|
|
|
|
|
|
case MouseEdit: // ? place the beginning of [tool] ?
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-28 13:53:47 +00:00
|
|
|
void PageView::contentsMouseReleaseEvent( QMouseEvent * e )
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
2004-10-06 00:05:49 +00:00
|
|
|
bool leftButton = e->button() & LeftButton,
|
|
|
|
rightButton = e->button() & RightButton;
|
2004-10-09 08:10:56 +00:00
|
|
|
PageWidget * pageWidget = pickPageOnPoint( e->x(), e->y() );
|
2004-09-26 23:39:39 +00:00
|
|
|
switch ( d->mouseMode )
|
|
|
|
{
|
|
|
|
case MouseNormal: // end drag / follow link
|
2004-10-06 00:05:49 +00:00
|
|
|
if ( leftButton )
|
2004-09-28 13:53:47 +00:00
|
|
|
{
|
|
|
|
setCursor( arrowCursor );
|
2004-10-06 00:05:49 +00:00
|
|
|
// check if over a link
|
2004-10-09 08:10:56 +00:00
|
|
|
if ( d->mouseOnLink && pageWidget )
|
2004-10-02 14:30:30 +00:00
|
|
|
{
|
2004-10-09 08:10:56 +00:00
|
|
|
int linkX = e->x() - childX( pageWidget ),
|
|
|
|
linkY = e->y() - childY( pageWidget );
|
|
|
|
d->document->slotProcessLink( pageWidget->page()->getLink( linkX, linkY ) );
|
2004-10-02 14:30:30 +00:00
|
|
|
}
|
2004-10-06 00:05:49 +00:00
|
|
|
// check if it was a click, in that case select the page
|
2004-10-09 08:10:56 +00:00
|
|
|
else if ( e->globalPos() == d->mouseStartPos && pageWidget )
|
|
|
|
d->document->slotSetCurrentPage( pageWidget->pageNumber() );
|
2004-10-06 00:05:49 +00:00
|
|
|
// check wether to restore the hand cursor
|
|
|
|
else if ( d->mouseOnLink )
|
|
|
|
setCursor( pointingHandCursor );
|
2004-09-28 13:53:47 +00:00
|
|
|
}
|
2004-10-09 08:10:56 +00:00
|
|
|
else if ( rightButton && pageWidget )
|
2004-09-28 13:53:47 +00:00
|
|
|
{
|
|
|
|
// If over a page display a popup menu
|
2004-10-09 08:10:56 +00:00
|
|
|
const KPDFPage * kpdfPage = pageWidget->page();
|
2004-09-28 13:53:47 +00:00
|
|
|
KPopupMenu * m_popup = new KPopupMenu( this, "rmb popup" );
|
2004-10-09 08:10:56 +00:00
|
|
|
m_popup->insertTitle( i18n( "Page %1" ).arg( kpdfPage->number() + 1 ) );
|
2004-09-28 13:53:47 +00:00
|
|
|
if ( kpdfPage->isBookmarked() )
|
|
|
|
m_popup->insertItem( SmallIcon("bookmark"), i18n("Remove Bookmark"), 1 );
|
|
|
|
else
|
|
|
|
m_popup->insertItem( SmallIcon("bookmark"), i18n("Add Bookmark"), 1 );
|
|
|
|
m_popup->insertItem( SmallIcon("viewmagfit"), i18n("Fit Page"), 2 );
|
|
|
|
m_popup->insertItem( SmallIcon("pencil"), i18n("Edit"), 3 );
|
2004-10-10 12:42:42 +00:00
|
|
|
switch ( m_popup->exec(e->globalPos()) )
|
2004-09-28 13:53:47 +00:00
|
|
|
{
|
|
|
|
case 1:
|
2004-10-09 08:10:56 +00:00
|
|
|
d->document->slotBookmarkPage( kpdfPage->number(), !kpdfPage->isBookmarked() );
|
2004-09-28 13:53:47 +00:00
|
|
|
break;
|
2004-09-30 18:16:12 +00:00
|
|
|
case 2: // FIXME less hackish, please!
|
|
|
|
d->aZoomFitWidth->setChecked( true );
|
|
|
|
updateZoom( ZoomFitWidth );
|
|
|
|
d->aViewTwoPages->setChecked( false );
|
2004-09-28 13:53:47 +00:00
|
|
|
slotTwoPagesToggled( false );
|
2004-10-09 08:10:56 +00:00
|
|
|
d->document->slotSetCurrentPage( kpdfPage->number() );
|
2004-09-28 13:53:47 +00:00
|
|
|
break;
|
2004-09-30 18:16:12 +00:00
|
|
|
case 3: // TODO switch to edit mode
|
|
|
|
slotSetMouseDraw();
|
2004-09-28 13:53:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-09-26 23:39:39 +00:00
|
|
|
break;
|
|
|
|
|
2004-10-07 20:34:27 +00:00
|
|
|
case MouseSelection: // get text from the page
|
|
|
|
if ( leftButton && d->mouseSelectionWidget )
|
|
|
|
{
|
2004-10-14 20:21:59 +00:00
|
|
|
// request the textpage if there isn't one
|
2004-10-09 08:10:56 +00:00
|
|
|
const KPDFPage * kpdfPage = d->mouseSelectionWidget->page();
|
|
|
|
if ( !kpdfPage->hasSearchPage() )
|
|
|
|
d->document->requestTextPage( kpdfPage->number() );
|
2004-10-14 20:21:59 +00:00
|
|
|
// copy text into the clipboard
|
|
|
|
QClipboard *cb = QApplication::clipboard();
|
|
|
|
const QString & selection = d->mouseSelectionWidget->selectedText();
|
|
|
|
cb->setText( selection, QClipboard::Clipboard );
|
|
|
|
if ( cb->supportsSelection() )
|
|
|
|
cb->setText( selection, QClipboard::Selection );
|
|
|
|
// clear widget selection
|
2004-10-07 20:34:27 +00:00
|
|
|
d->mouseSelectionWidget->clearSelection();
|
|
|
|
d->mouseSelectionWidget = 0;
|
|
|
|
}
|
|
|
|
break;
|
2004-09-26 23:39:39 +00:00
|
|
|
|
|
|
|
case MouseEdit: // ? apply [tool] ?
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::contentsMouseMoveEvent( QMouseEvent * e )
|
|
|
|
{
|
2004-09-30 18:16:12 +00:00
|
|
|
bool leftButton = e->state() & LeftButton;
|
2004-09-26 23:39:39 +00:00
|
|
|
switch ( d->mouseMode )
|
|
|
|
{
|
2004-10-06 00:05:49 +00:00
|
|
|
case MouseNormal: // drag page / change mouse cursor if over links
|
2004-09-30 18:16:12 +00:00
|
|
|
if ( leftButton && !d->mouseGrabPos.isNull() )
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
|
|
|
QPoint delta = d->mouseGrabPos - e->globalPos();
|
|
|
|
scrollBy( delta.x(), delta.y() );
|
|
|
|
d->mouseGrabPos = e->globalPos();
|
|
|
|
}
|
2004-10-06 00:05:49 +00:00
|
|
|
else
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
|
|
|
// set cursor only when entering / leaving (setCursor has not an internal cache)
|
2004-09-30 18:16:12 +00:00
|
|
|
PageWidget * pageWidget = pickPageOnPoint( e->x(), e->y() );
|
2004-10-06 00:05:49 +00:00
|
|
|
if ( !pageWidget )
|
|
|
|
break;
|
|
|
|
bool onLink = pageWidget->page()->hasLink( e->x() - childX( pageWidget ), e->y() - childY( pageWidget ) );
|
|
|
|
if ( onLink != d->mouseOnLink )
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
2004-10-06 00:05:49 +00:00
|
|
|
d->mouseOnLink = onLink;
|
|
|
|
setCursor( onLink ? pointingHandCursor : arrowCursor );
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-10-07 20:34:27 +00:00
|
|
|
case MouseSelection: // set selection's second corner
|
|
|
|
if ( leftButton && d->mouseSelectionWidget )
|
|
|
|
// continue selecting on current page
|
|
|
|
d->mouseSelectionWidget->setEndCorner(
|
|
|
|
e->x() - childX( d->mouseSelectionWidget ),
|
|
|
|
e->y() - childY( d->mouseSelectionWidget ) );
|
|
|
|
break;
|
2004-09-26 23:39:39 +00:00
|
|
|
|
|
|
|
case MouseEdit: // ? update graphics ?
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::keyPressEvent( QKeyEvent * e )
|
|
|
|
{
|
|
|
|
switch ( e->key() )
|
|
|
|
{
|
|
|
|
case Key_Up:
|
|
|
|
if ( atTop() )
|
|
|
|
scrollUp();
|
|
|
|
else
|
|
|
|
verticalScrollBar()->subtractLine();
|
|
|
|
break;
|
|
|
|
case Key_Down:
|
|
|
|
if ( atBottom() )
|
|
|
|
scrollDown();
|
|
|
|
else
|
|
|
|
verticalScrollBar()->addLine();
|
|
|
|
break;
|
|
|
|
case Key_Left:
|
|
|
|
horizontalScrollBar()->subtractLine();
|
|
|
|
break;
|
|
|
|
case Key_Right:
|
|
|
|
horizontalScrollBar()->addLine();
|
|
|
|
break;
|
2004-09-27 21:36:25 +00:00
|
|
|
case Key_PageUp:
|
|
|
|
verticalScrollBar()->subtractPage();
|
|
|
|
break;
|
|
|
|
case Key_PageDown:
|
|
|
|
verticalScrollBar()->addPage();
|
2004-09-26 23:39:39 +00:00
|
|
|
break;
|
2004-10-06 00:05:49 +00:00
|
|
|
case Key_Shift:
|
|
|
|
case Key_Control:
|
|
|
|
if ( d->scrollTimer )
|
|
|
|
{
|
|
|
|
if ( d->scrollTimer->isActive() )
|
|
|
|
d->scrollTimer->stop();
|
|
|
|
else
|
|
|
|
slotAutoScoll();
|
|
|
|
e->accept();
|
|
|
|
return;
|
|
|
|
}
|
2004-09-26 23:39:39 +00:00
|
|
|
default:
|
|
|
|
e->ignore();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
e->accept();
|
2004-10-06 00:05:49 +00:00
|
|
|
|
|
|
|
if ( d->scrollTimer )
|
|
|
|
{
|
|
|
|
d->scrollIncrement = 0;
|
|
|
|
d->scrollTimer->stop();
|
|
|
|
}
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::wheelEvent( QWheelEvent *e )
|
|
|
|
{
|
|
|
|
int delta = e->delta();
|
|
|
|
e->accept();
|
|
|
|
if ( (e->state() & ControlButton) == ControlButton ) {
|
|
|
|
if ( e->delta() > 0 )
|
|
|
|
slotZoomOut();
|
|
|
|
else
|
|
|
|
slotZoomIn();
|
|
|
|
}
|
2004-09-27 21:36:25 +00:00
|
|
|
else if ( delta <= -120 && atBottom() && !d->viewContinous )
|
2004-09-26 23:39:39 +00:00
|
|
|
scrollDown();
|
2004-09-27 21:36:25 +00:00
|
|
|
else if ( delta >= 120 && atTop() && !d->viewContinous )
|
2004-09-26 23:39:39 +00:00
|
|
|
scrollUp();
|
|
|
|
else
|
|
|
|
QScrollView::wheelEvent( e );
|
|
|
|
}
|
|
|
|
|
2004-09-30 18:16:12 +00:00
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
2004-09-26 23:39:39 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
//BEGIN internal SLOTS
|
2004-09-30 18:16:12 +00:00
|
|
|
void PageView::slotZoom()
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
2004-09-30 18:04:09 +00:00
|
|
|
updateZoom( ZoomFixed );
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::slotZoomIn()
|
|
|
|
{
|
2004-09-30 18:04:09 +00:00
|
|
|
updateZoom( ZoomIn );
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::slotZoomOut()
|
|
|
|
{
|
2004-09-30 18:04:09 +00:00
|
|
|
updateZoom( ZoomOut );
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::slotFitToWidthToggled( bool on )
|
|
|
|
{
|
2004-09-30 18:04:09 +00:00
|
|
|
if ( on ) updateZoom( ZoomFitWidth );
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::slotFitToPageToggled( bool on )
|
|
|
|
{
|
2004-09-30 18:04:09 +00:00
|
|
|
if ( on ) updateZoom( ZoomFitPage );
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::slotFitToTextToggled( bool on )
|
|
|
|
{
|
2004-09-30 18:04:09 +00:00
|
|
|
if ( on ) updateZoom( ZoomFitText );
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
2004-09-27 21:36:25 +00:00
|
|
|
void PageView::slotTwoPagesToggled( bool on )
|
|
|
|
{
|
2004-09-28 13:53:47 +00:00
|
|
|
int newColumns = on ? 2 : 1;
|
|
|
|
if ( d->viewColumns != newColumns )
|
|
|
|
{
|
|
|
|
d->viewColumns = newColumns;
|
2004-09-30 18:04:09 +00:00
|
|
|
slotRelayoutPages();
|
2004-09-28 13:53:47 +00:00
|
|
|
}
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
2004-09-27 21:36:25 +00:00
|
|
|
void PageView::slotContinousToggled( bool on )
|
|
|
|
{
|
2004-09-28 13:53:47 +00:00
|
|
|
if ( d->viewContinous != on )
|
|
|
|
{
|
|
|
|
d->viewContinous = on;
|
2004-09-30 18:04:09 +00:00
|
|
|
slotRelayoutPages();
|
2004-09-28 13:53:47 +00:00
|
|
|
}
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::slotSetMouseNormal()
|
|
|
|
{
|
|
|
|
d->mouseMode = MouseNormal;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::slotSetMouseSelect()
|
|
|
|
{
|
|
|
|
d->mouseMode = MouseSelection;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::slotSetMouseDraw()
|
|
|
|
{
|
|
|
|
d->mouseMode = MouseEdit;
|
|
|
|
}
|
|
|
|
|
2004-10-06 00:05:49 +00:00
|
|
|
void PageView::slotScrollUp()
|
|
|
|
{
|
|
|
|
if ( d->scrollIncrement < -9 )
|
|
|
|
return;
|
|
|
|
d->scrollIncrement--;
|
|
|
|
slotAutoScoll();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::slotScrollDown()
|
|
|
|
{
|
|
|
|
if ( d->scrollIncrement > 9 )
|
|
|
|
return;
|
|
|
|
d->scrollIncrement++;
|
|
|
|
slotAutoScoll();
|
|
|
|
}
|
|
|
|
|
2004-09-26 23:39:39 +00:00
|
|
|
void PageView::slotToggleScrollBars( bool on )
|
|
|
|
{
|
|
|
|
setHScrollBarMode( on ? AlwaysOn : AlwaysOff );
|
|
|
|
setVScrollBarMode( on ? AlwaysOn : AlwaysOff );
|
|
|
|
}
|
|
|
|
|
2004-09-30 18:04:09 +00:00
|
|
|
void PageView::slotRelayoutPages()
|
|
|
|
// called by: pageSetup, viewportResizeEvent, slotTwoPagesToggled, slotContinousToggled, updateZoom
|
2004-09-27 21:36:25 +00:00
|
|
|
{
|
|
|
|
// set an empty container if we have no pages
|
|
|
|
int pageCount = d->pages.count();
|
|
|
|
if ( pageCount < 1 )
|
|
|
|
{
|
|
|
|
resizeContents( 0,0 );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int viewportWidth = clipper()->width(),
|
2004-09-30 18:16:12 +00:00
|
|
|
viewportHeight = clipper()->height(),
|
|
|
|
fullWidth = 0,
|
|
|
|
fullHeight = 0;
|
2004-09-27 21:36:25 +00:00
|
|
|
|
|
|
|
if ( d->viewContinous == TRUE )
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
2004-09-27 21:36:25 +00:00
|
|
|
// 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 = d->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
|
|
|
|
QValueVector< PageWidget * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end();
|
|
|
|
for ( ; pIt != pEnd; ++pIt )
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
2004-09-27 21:36:25 +00:00
|
|
|
PageWidget * p = *pIt;
|
|
|
|
// update internal page geometry
|
|
|
|
if ( d->zoomMode == ZoomFixed )
|
|
|
|
p->setZoomFixed( d->zoomFactor );
|
|
|
|
else if ( d->zoomMode == ZoomFitWidth )
|
|
|
|
p->setZoomFitWidth( colWidth[ cIdx ] - 10 );
|
|
|
|
else
|
|
|
|
p->setZoomFitRect( colWidth[ cIdx ] - 10, viewportHeight - 10 );
|
|
|
|
// find row's maximum height and column's max width
|
|
|
|
int pWidth = p->widthHint(),
|
|
|
|
pHeight = p->heightHint();
|
|
|
|
if ( pWidth > colWidth[ cIdx ] )
|
|
|
|
colWidth[ cIdx ] = pWidth;
|
|
|
|
if ( pHeight > rowHeight[ rIdx ] )
|
|
|
|
rowHeight[ rIdx ] = pHeight;
|
|
|
|
// update col/row indices
|
|
|
|
if ( ++cIdx == nCols )
|
2004-09-26 23:39:39 +00:00
|
|
|
{
|
2004-09-27 21:36:25 +00:00
|
|
|
cIdx = 0;
|
|
|
|
rIdx++;
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
}
|
2004-09-27 21:36:25 +00:00
|
|
|
|
|
|
|
// 2) arrange widgets inside cells
|
|
|
|
int insertX = 0,
|
2004-09-30 18:16:12 +00:00
|
|
|
insertY = (int)(2.0 + 4.0 * d->zoomFactor);
|
2004-09-27 21:36:25 +00:00
|
|
|
cIdx = 0;
|
|
|
|
rIdx = 0;
|
|
|
|
for ( pIt = d->pages.begin(); pIt != pEnd; ++pIt )
|
|
|
|
{
|
|
|
|
PageWidget * p = *pIt;
|
|
|
|
int pWidth = p->widthHint(),
|
|
|
|
pHeight = p->heightHint(),
|
|
|
|
cWidth = colWidth[ cIdx ],
|
|
|
|
rHeight = rowHeight[ rIdx ];
|
|
|
|
// show, resize and center widget inside 'cells'
|
|
|
|
p->resize( pWidth, pHeight );
|
|
|
|
moveChild( p, insertX + (cWidth - pWidth) / 2,
|
2004-09-30 18:16:12 +00:00
|
|
|
insertY + (rHeight - pHeight) / 2 );
|
2004-09-27 21:36:25 +00:00
|
|
|
p->show();
|
|
|
|
// advance col/row index
|
|
|
|
insertX += cWidth;
|
|
|
|
if ( ++cIdx == nCols )
|
|
|
|
{
|
|
|
|
cIdx = 0;
|
|
|
|
rIdx++;
|
|
|
|
insertX = 0;
|
|
|
|
insertY += rHeight + (int)(5.0 + 15.0 * d->zoomFactor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-30 18:16:12 +00:00
|
|
|
fullHeight = cIdx ? (insertY + rowHeight[ rIdx ] + 10) : insertY;
|
2004-09-27 21:36:25 +00:00
|
|
|
for ( int i = 0; i < nCols; i++ )
|
|
|
|
fullWidth += colWidth[ i ];
|
|
|
|
|
|
|
|
delete [] colWidth;
|
|
|
|
delete [] rowHeight;
|
|
|
|
}
|
|
|
|
else // viewContinous is FALSE
|
|
|
|
{
|
2004-09-30 18:16:12 +00:00
|
|
|
PageWidget * currentPage = d->page ? d->page : d->pages[0];
|
|
|
|
|
|
|
|
// setup varialbles for a 1(row) x N(columns) grid
|
|
|
|
int nCols = d->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
|
|
|
|
QValueVector< PageWidget * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end();
|
|
|
|
for ( ; pIt != pEnd; ++pIt )
|
|
|
|
{
|
|
|
|
PageWidget * p = *pIt;
|
|
|
|
if ( p == currentPage || (cIdx > 0 && cIdx < nCols) )
|
|
|
|
{
|
|
|
|
if ( d->zoomMode == ZoomFixed )
|
|
|
|
p->setZoomFixed( d->zoomFactor );
|
|
|
|
else if ( d->zoomMode == ZoomFitWidth )
|
|
|
|
p->setZoomFitWidth( colWidth[ cIdx ] - 10 );
|
|
|
|
else
|
|
|
|
p->setZoomFitRect( colWidth[ cIdx ] - 10, viewportHeight - 10 );
|
|
|
|
if ( p->widthHint() > colWidth[ cIdx ] )
|
|
|
|
colWidth[ cIdx ] = p->widthHint();
|
|
|
|
fullHeight = QMAX( fullHeight, p->heightHint() );
|
|
|
|
cIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2) hide all widgets except the displayable ones and dispose those
|
|
|
|
int insertX = 0,
|
|
|
|
insertY = (int)(2.0 + 4.0 * d->zoomFactor);
|
|
|
|
cIdx = 0;
|
|
|
|
for ( pIt = d->pages.begin(); pIt != pEnd; ++pIt )
|
|
|
|
{
|
|
|
|
PageWidget * p = *pIt;
|
|
|
|
if ( p == currentPage || (cIdx > 0 && cIdx < nCols) )
|
|
|
|
{
|
|
|
|
int pWidth = p->widthHint(),
|
|
|
|
pHeight = p->heightHint();
|
|
|
|
// show, resize and center widget inside 'cells'
|
|
|
|
p->resize( pWidth, pHeight );
|
|
|
|
moveChild( p, insertX + (colWidth[ cIdx ] - pWidth) / 2,
|
|
|
|
insertY + (fullHeight - pHeight) / 2 );
|
|
|
|
p->show();
|
|
|
|
// advance col/row index
|
|
|
|
insertX += colWidth[ cIdx ];
|
|
|
|
cIdx++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
p->hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( int i = 0; i < nCols; i++ )
|
|
|
|
fullWidth += colWidth[ i ];
|
|
|
|
|
|
|
|
delete [] colWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 3) update scrollview's contents size and recenter view
|
|
|
|
int oldWidth = contentsWidth(),
|
|
|
|
oldHeight = contentsHeight();
|
|
|
|
if ( oldWidth != fullWidth || oldHeight != fullHeight )
|
|
|
|
{
|
|
|
|
resizeContents( fullWidth, fullHeight );
|
|
|
|
if ( oldWidth > 0 && oldHeight > 0 )
|
|
|
|
center( fullWidth * (contentsX() + visibleWidth() / 2) / oldWidth,
|
|
|
|
fullHeight * (contentsY() + visibleHeight() / 2) / oldHeight );
|
|
|
|
else
|
|
|
|
center( fullWidth / 2, 0 );
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
2004-09-27 21:36:25 +00:00
|
|
|
|
|
|
|
// reset dirty state
|
2004-09-30 18:04:09 +00:00
|
|
|
d->dirtyLayout = false;
|
|
|
|
}
|
|
|
|
|
2004-09-30 18:16:12 +00:00
|
|
|
void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop )
|
|
|
|
{
|
|
|
|
// precalc view limits for intersecting with page coords inside the lOOp
|
|
|
|
int vLeft = (newLeft == -1) ? contentsX() : newLeft,
|
|
|
|
vRight = vLeft + visibleWidth(),
|
|
|
|
vTop = (newTop == -1) ? contentsY() : newTop,
|
|
|
|
vBottom = vTop + visibleHeight();
|
|
|
|
|
|
|
|
// scroll from the top to the last visible thumbnail
|
|
|
|
QValueVector< PageWidget * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end();
|
|
|
|
for ( ; pIt != pEnd; ++pIt )
|
|
|
|
{
|
|
|
|
PageWidget * p = *pIt;
|
|
|
|
int pLeft = childX( p ),
|
|
|
|
pRight = pLeft + p->widthHint(),
|
|
|
|
pTop = childY( p ),
|
|
|
|
pBottom = pTop + p->heightHint();
|
|
|
|
if ( p->isShown() && pRight > vLeft && pLeft < vRight && pBottom > vTop && pTop < vBottom )
|
|
|
|
d->document->requestPixmap( PAGEVIEW_ID, p->pageNumber(), p->pixmapWidth(), p->pixmapHeight(), true );
|
|
|
|
}
|
|
|
|
}
|
2004-10-06 00:05:49 +00:00
|
|
|
|
|
|
|
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 ] );
|
|
|
|
}
|
2004-09-30 18:16:12 +00:00
|
|
|
//END internal SLOTS
|
|
|
|
|
2004-09-30 18:04:09 +00:00
|
|
|
void PageView::updateZoom( ZoomMode newZoomMode )
|
|
|
|
{
|
|
|
|
if ( newZoomMode == ZoomFixed )
|
|
|
|
{
|
2004-09-30 18:16:12 +00:00
|
|
|
if ( d->aZoom->currentItem() == 0 )
|
2004-09-30 18:04:09 +00:00
|
|
|
newZoomMode = ZoomFitWidth;
|
2004-09-30 18:16:12 +00:00
|
|
|
else if ( d->aZoom->currentItem() == 1 )
|
2004-09-30 18:04:09 +00:00
|
|
|
newZoomMode = ZoomFitPage;
|
|
|
|
}
|
|
|
|
|
|
|
|
float newFactor = d->zoomFactor;
|
|
|
|
KAction * checkedZoomAction = 0;
|
|
|
|
switch ( newZoomMode )
|
|
|
|
{
|
|
|
|
case ZoomFixed:{
|
|
|
|
QString z = d->aZoom->currentText();
|
|
|
|
newFactor = KGlobal::locale()->readNumber( z.remove( z.find( '%' ), 1 ) ) / 100.0;
|
|
|
|
if ( newFactor < 0.1 || newFactor > 8.0 )
|
|
|
|
return;
|
|
|
|
}break;
|
|
|
|
case ZoomIn:
|
|
|
|
newFactor += 0.1;
|
|
|
|
if ( newFactor >= 4.0 )
|
|
|
|
newFactor = 4.0;
|
|
|
|
newZoomMode = ZoomFixed;
|
|
|
|
break;
|
|
|
|
case ZoomOut:
|
|
|
|
newFactor -= 0.1;
|
|
|
|
if ( newFactor <= 0.125 )
|
|
|
|
newFactor = 0.125;
|
|
|
|
newZoomMode = ZoomFixed;
|
|
|
|
break;
|
|
|
|
case ZoomFitWidth:
|
|
|
|
checkedZoomAction = d->aZoomFitWidth;
|
|
|
|
break;
|
|
|
|
case ZoomFitPage:
|
|
|
|
checkedZoomAction = d->aZoomFitPage;
|
|
|
|
break;
|
|
|
|
case ZoomFitText:
|
|
|
|
checkedZoomAction = d->aZoomFitText;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( newZoomMode != d->zoomMode || (newZoomMode == ZoomFixed && newFactor != d->zoomFactor ) )
|
|
|
|
{
|
|
|
|
// rebuild layout and change the zoom selectAction contents
|
|
|
|
d->zoomMode = newZoomMode;
|
|
|
|
d->zoomFactor = newFactor;
|
|
|
|
slotRelayoutPages();
|
|
|
|
updateZoomText();
|
2004-09-30 18:16:12 +00:00
|
|
|
// update actions checked state
|
2004-09-30 18:04:09 +00:00
|
|
|
d->aZoomFitWidth->setChecked( checkedZoomAction == d->aZoomFitWidth );
|
|
|
|
d->aZoomFitPage->setChecked( checkedZoomAction == d->aZoomFitPage );
|
|
|
|
d->aZoomFitText->setChecked( checkedZoomAction == d->aZoomFitText );
|
|
|
|
// request pixmaps
|
|
|
|
slotRequestVisiblePixmaps();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::updateZoomText()
|
|
|
|
{
|
|
|
|
// use current page zoom as zoomFactor if in ZoomFit/* mode
|
|
|
|
if ( d->zoomMode != ZoomFixed && d->pages.count() > 0 )
|
|
|
|
d->zoomFactor = d->page ? d->page->zoomFactor() : d->pages[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.001) )
|
|
|
|
value = newFactor;
|
|
|
|
else
|
|
|
|
idx ++;
|
|
|
|
if ( value > (newFactor - 0.001) && value < (newFactor + 0.001) )
|
|
|
|
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 );
|
2004-09-26 23:39:39 +00:00
|
|
|
}
|
|
|
|
|
2004-09-28 13:53:47 +00:00
|
|
|
PageWidget * PageView::pickPageOnPoint( int x, int y )
|
|
|
|
{
|
|
|
|
PageWidget * page = 0;
|
|
|
|
QValueVector< PageWidget * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end();
|
|
|
|
for ( ; pIt != pEnd; ++pIt )
|
|
|
|
{
|
|
|
|
PageWidget * p = *pIt;
|
|
|
|
int pLeft = childX( p ),
|
|
|
|
pRight = pLeft + p->widthHint(),
|
|
|
|
pTop = childY( p ),
|
|
|
|
pBottom = pTop + p->heightHint();
|
|
|
|
// little optimized, stops if found or probably quits on the next row
|
2004-09-30 18:16:12 +00:00
|
|
|
if ( x > pLeft && x < pRight && y < pBottom && p->isShown() )
|
2004-09-28 13:53:47 +00:00
|
|
|
{
|
|
|
|
if ( y > pTop )
|
|
|
|
page = p;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return page;
|
|
|
|
}
|
|
|
|
|
2004-09-26 23:39:39 +00:00
|
|
|
bool PageView::atTop() const
|
|
|
|
{
|
|
|
|
return verticalScrollBar()->value() == verticalScrollBar()->minValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PageView::atBottom() const
|
|
|
|
{
|
|
|
|
return verticalScrollBar()->value() == verticalScrollBar()->maxValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::scrollUp()
|
|
|
|
{
|
|
|
|
if( atTop() && d->vectorIndex > 0 )
|
|
|
|
// go to the bottom of previous page
|
2004-10-10 13:21:30 +00:00
|
|
|
d->document->slotSetCurrentPage( d->pages[ d->vectorIndex - 1 ]->pageNumber() ); //TODO add position
|
2004-09-26 23:39:39 +00:00
|
|
|
else
|
|
|
|
{ // go towards the top of current page
|
|
|
|
int newValue = QMAX( verticalScrollBar()->value() - height() + 50,
|
|
|
|
verticalScrollBar()->minValue() );
|
|
|
|
verticalScrollBar()->setValue( newValue );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PageView::scrollDown()
|
|
|
|
{
|
|
|
|
if( atBottom() && d->vectorIndex < (int)d->pages.count() - 1 )
|
|
|
|
// go to the top of previous page
|
2004-10-10 13:21:30 +00:00
|
|
|
d->document->slotSetCurrentPage( d->pages[ d->vectorIndex + 1 ]->pageNumber() ); // TODO add position
|
2004-09-26 23:39:39 +00:00
|
|
|
else
|
|
|
|
{ // go towards the bottom of current page
|
|
|
|
int newValue = QMIN( verticalScrollBar()->value() + height() - 50,
|
|
|
|
verticalScrollBar()->maxValue() );
|
|
|
|
verticalScrollBar()->setValue( newValue );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "pageview.moc"
|