Continous/2-up modes done! :-) Need cleanups/smarter reLayouts but it's

fully functional now. Better and faster graphics in PageView and
ThumbnailList. I need the memory manager now.. mmm..

svn path=/branches/kpdf_experiments/kdegraphics/kpdf/; revision=349849
This commit is contained in:
Enrico Ros 2004-09-27 21:36:25 +00:00
parent 40cb0b1c93
commit 4175f13552
10 changed files with 364 additions and 355 deletions

View file

@ -15,14 +15,15 @@ More items
-> wrong zoom buttons order (BR74248) (check consistancy with kdvi/kghostview/.. (not konq))
Porting / In progress on the branch (first item comes first):
-> continous mode (BR74435)
-> multiple pages per view (BR80164)
-> restore single page mdoe (broke up)
-> zoom buttons in sync with text (BR69092)
-> porting Albert's link following
-> implementing async document generator using Albert's thread as the generation thread
-> reading aids (accessibility): mode: normal, invert, contrast, recolor bg/text
Done (sorted by inv.time)
-> continous mode
-> multiple pages per view
-> added the option to open password protected files (from head)
-> added the TOC from head (missing click and go functionality because it needs link following)
-> added a 'search bar' with prune-as-you-type feature
@ -61,4 +62,5 @@ BR72165: (showing a "scanned document PDF" is very slow). By running many tests
internal pixmap conversions). No noticeable difference.
BR89835: (PDF pages to be aligned centrally). Done in branch.
BR90026: (crash). Can't reproduce on branch.
BR74435: (smooth transition/continous mode) It's in from sept-27.
BR80164: (2-up view of pdf pages) It's in from sept-26.

View file

@ -102,6 +102,7 @@ Part::Part(QWidget *parentWidget, const char *widgetName,
QVBox * thumbsBox = new ThumbnailsBox( m_toolBox );
m_thumbnailList = new ThumbnailList( thumbsBox, document );
connect( m_thumbnailList, SIGNAL( urlDropped( const KURL& ) ), SLOT( openURL( const KURL & )));
m_searchWidget = new SearchWidget( thumbsBox, document );
m_toolBox->addItem( thumbsBox, QIconSet(SmallIcon("thumbnail")), i18n("Thumbnails") );
m_toolBox->setCurrentItem( thumbsBox );
@ -134,14 +135,16 @@ Part::Part(QWidget *parentWidget, const char *widgetName,
m_prevPage = KStdAction::prior(this, SLOT(slotPreviousPage()), ac, "previous_page");
m_prevPage->setWhatsThis( i18n( "Moves to the previous page of the document" ) );
m_prevPage->setShortcut( "Backspace" );
m_nextPage = KStdAction::next(this, SLOT(slotNextPage()), ac, "next_page" );
m_nextPage->setWhatsThis( i18n( "Moves to the next page of the document" ) );
m_nextPage->setShortcut( "Space" );
m_firstPage = KStdAction::firstPage( this, SLOT( slotGotoFirst() ), ac, "first_page" );
m_firstPage->setWhatsThis( i18n( "Moves to the first page of the document" ) );
m_lastPage = KStdAction::lastPage( this, SLOT( slotGotoLast() ), ac, "last_page" );
m_lastPage = KStdAction::lastPage( this, SLOT( slotGotoLast() ), ac, "last_page" );
m_lastPage->setWhatsThis( i18n( "Moves to the last page of the document" ) );
// Find and other actions
@ -155,6 +158,10 @@ Part::Part(QWidget *parentWidget, const char *widgetName,
KStdAction::printPreview( this, SLOT( slotPrintPreview() ), ac );
KToggleAction * sLp = new KToggleAction( i18n( "Show &Left Panel" ), 0, ac, "show_leftpanel" );
sLp->setCheckedState(i18n("Hide &Left Panel"));
connect( sLp, SIGNAL( toggled( bool ) ), SLOT( slotToggleLeftPanel( bool ) ) );
// attach the actions of the 2 children widgets too
KConfigGroup settings( KPDFPartFactory::instance()->config(), "General" );
m_pageView->setupActions( ac, &settings );
@ -163,6 +170,8 @@ Part::Part(QWidget *parentWidget, const char *widgetName,
// local settings
m_splitter->setSizes( settings.readIntListEntry( "SplitterSizes" ) );
sLp->setChecked( settings.readBoolEntry( "ShowLeftPanel", true ) );
slotToggleLeftPanel( sLp->isChecked() );
// set our XML-UI resource file
setXMLFile("kpdf_part.rc");
@ -176,6 +185,8 @@ Part::~Part()
m_searchWidget->saveSettings( &settings );
m_thumbnailList->saveSettings( &settings );
settings.writeEntry( "SplitterSizes", m_splitter->sizes() );
settings.writeEntry( "ShowLeftPanel", m_toolBox->isShown() );
settings.sync();
delete document;
if ( --m_count == 0 )
@ -552,6 +563,13 @@ void Part::doPrint( KPrinter& /*printer*/ )
*/
}
void Part::slotToggleLeftPanel( bool on )
{
// show/hide left qtoolbox
m_toolBox->setShown( on );
// this needs to be hidden explicitly to disable thumbnails gen
m_thumbnailList->setShown( on );
}
/*
* BrowserExtension class

View file

@ -93,6 +93,7 @@ namespace KPDF
void slotFindNext();
void slotSaveFileAs();
void slotPrintPreview();
void slotToggleLeftPanel( bool );
// can be connected to widget elements
void updateActions();
void enableTOC(bool enable);
@ -107,6 +108,7 @@ namespace KPDF
// main widgets
QSplitter *m_splitter;
QToolBox *m_toolBox;
ThumbnailList *m_thumbnailList;
PageView *m_pageView;
SearchWidget *m_searchWidget;
@ -114,8 +116,6 @@ namespace KPDF
// static instances counter
static unsigned int m_count;
QToolBox *m_toolBox;
// actions
KAction *m_gotoPage;
KAction *m_prevPage;

View file

@ -27,7 +27,7 @@
</Menu>
<Menu name="settings"><text>&amp;Settings</text>
<Action name="show_scrollbars" group="show_merge"/>
<Action name="show_thumbnails" group="show_merge"/>
<Action name="show_leftpanel" group="show_merge"/>
<Action name="show_searchbar" group="show_merge"/>
</Menu>
</MenuBar>
@ -42,8 +42,7 @@
<!--Action name="zoom_fit_width"/-->
<!--Action name="zoom_fit_page"/-->
<Separator/>
<Action name="view_single"/>
<Action name="view_double"/>
<Action name="view_twopages"/>
<Action name="view_continous"/>
<Separator/>
<Action name="mouse_drag"/>

View file

@ -1,11 +1,14 @@
/***************************************************************************
* 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 Enrico Ros <eros.kde@email.it> *
* Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es> *
* Copyright (C) 2004 by James Ots <kde@jamesots.com> *
* *
* 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 *
@ -18,7 +21,6 @@
#include <qtimer.h>
#include <qpushbutton.h>
#include <kglobalsettings.h>
#include <kiconloader.h>
#include <kurldrag.h>
#include <kaction.h>
@ -39,56 +41,69 @@ class PageViewPrivate
public:
// the document, current page and pages indices vector
KPDFDocument * document;
const KPDFPage * page; //equal to pages[vectorIndex]
PageWidget * page; //equal to pages[vectorIndex]
QValueVector< PageWidget * > pages;
int vectorIndex;
// view layout, zoom and mouse
PageView::ViewMode viewMode;
int viewColumns;
bool viewContinous;
PageView::ZoomMode zoomMode;
float zoomFactor;
PageView::MouseMode mouseMode;
QPoint mouseGrabPos;
bool mouseOnLink;
// other stuff
QTimer *delayTimer;
bool dirty;
// actions
KSelectAction *aZoom;
KToggleAction *aZoomFitWidth;
KToggleAction *aZoomFitPage;
KToggleAction *aZoomFitText;
//TODO ADD bool dirty;
KToggleAction *aViewTwoPages;
KToggleAction *aViewContinous;
};
/*
* PageView class
*/
PageView::PageView( QWidget *parent, KPDFDocument *document )
: QScrollView( parent, "KPDF::pageView", WRepaintNoErase | WStaticContents )
: QScrollView( parent, "KPDF::pageView", WNoAutoErase | WStaticContents )
{
// create and initialize private storage structure
d = new PageViewPrivate();
d->document = document;
d->page = 0;
d->viewColumns = 1;
d->viewContinous = false;
d->zoomMode = ZoomFitWidth;
d->zoomFactor = 0.999;
d->mouseMode = MouseNormal;
d->mouseOnLink = false;
d->zoomMode = ZoomFixed;
d->zoomFactor = 0.1; //FIXME REDEFAULT!!
d->delayTimer = 0;
d->dirty = false;
// widget setup
setAcceptDrops( true );
setFocusPolicy( QWidget::StrongFocus );
viewport()->setFocusPolicy( QWidget::WheelFocus );
viewport()->setMouseTracking( true );
// dealing with (very) large areas so enable clipper
enableClipper( true );
// widget setup: setup focus, accept drops and track mouse
viewport()->setFocusProxy( this );
viewport()->setFocusPolicy( StrongFocus );
viewport()->setPaletteBackgroundColor( Qt::gray );
setResizePolicy( Manual );
setAcceptDrops( true );
viewport()->setMouseTracking( true );
// conntect the padding of the viewport to pixmaps requests
connect( this, SIGNAL(contentsMoving(int, int)), this, SLOT(slotRequestVisiblePixmaps(int, int)) );
// set a corner button to resize the view to the page size
QPushButton * resizeButton = new QPushButton( viewport() );
resizeButton->setPixmap( SmallIcon("crop" /*"top"*/) );
resizeButton->setPixmap( SmallIcon("crop") );
setCornerWidget( resizeButton );
resizeButton->setEnabled( false );
// connect(...);
@ -119,7 +134,7 @@ void PageView::setupActions( KActionCollection * ac, KConfigGroup * config )
translated << QString( "%1%" ).arg( localValue );
}
d->aZoom->setItems( translated );
d->aZoom->setCurrentItem( 8 );
d->aZoom->setCurrentItem( 0 ); // 8 for 100%
KStdAction::zoomIn( this, SLOT( slotZoomIn() ), ac, "zoom_in" );
@ -132,17 +147,15 @@ void PageView::setupActions( KActionCollection * ac, KConfigGroup * config )
connect( d->aZoomFitPage, SIGNAL( toggled( bool ) ), SLOT( slotFitToPageToggled( bool ) ) );
// View-Layout actions
KToggleAction * vs = new KToggleAction( i18n("Single Page"), "view_remove", 0, this, SLOT( slotSetViewSingle() ), ac, "view_single" );
vs->setExclusiveGroup("ViewLayout");
vs->setChecked( true );
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() );
KToggleAction * vd = new KToggleAction( i18n("Two Pages"), "view_left_right", 0, this, SLOT( slotSetViewDouble() ), ac, "view_double" );
vd->setExclusiveGroup("ViewLayout");
vd->setEnabled( false ); // implement feature before removing this line
KToggleAction * vc = new KToggleAction( i18n("Continous"), "view_text", 0, this, SLOT( slotSetViewContinous() ), ac, "view_continous" );
vc->setExclusiveGroup("ViewLayout"); //TODO toggable with others or.. alone?
vc->setEnabled( false ); // implement feature before removing this line
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() );
// Mouse-Mode actions
KToggleAction * mn = new KToggleAction( i18n("Normal"), "mouse", 0, this, SLOT( slotSetMouseNormal() ), ac, "mouse_drag" );
@ -169,6 +182,8 @@ void PageView::setupActions( KActionCollection * ac, KConfigGroup * config )
void PageView::saveSettings( KConfigGroup * config )
{
config->writeEntry( "ShowScrollBars", hScrollBarMode() == AlwaysOn );
config->writeEntry( "ViewTwoPages", d->aViewTwoPages->isChecked() );
config->writeEntry( "ViewContinous", d->aViewContinous->isChecked() );
}
@ -186,169 +201,53 @@ void PageView::pageSetup( const QValueVector<KPDFPage*> & pageSet, bool /*docume
QValueVector< KPDFPage * >::const_iterator setIt = pageSet.begin(), setEnd = pageSet.end();
for ( ; setIt != setEnd; ++setIt )
{
PageWidget * p = new PageWidget( this, *setIt );
// add to the internal queue
PageWidget * p = new PageWidget( viewport(), *setIt );
p->setFocusProxy( this );
d->pages.push_back( p );
// add to the scrollview
addChild( p, 0, 0 );
}
// FIXME TEMP relayout
reLayoutPages();
// invalidate layout
d->dirty = true;
}
#define FIXME_COLS 3
void PageView::reLayoutPages()
void PageView::pageSetCurrent( int pageNumber, float position )
{
int pageCount = d->pages.count();
if ( pageCount < 1 )
{
resizeContents( 0,0 );
return;
}
if ( d->dirty )
reLayoutPages();
// 1) preprocess array (compute 'virtual grid' values)
// 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 = FIXME_COLS,
nRows = (int)ceilf( (float)pageCount / (float)nCols ),
cIdx = 0,
rIdx = 0,
vWidth = clipper()->width() / nCols,
vHeight = clipper()->height();
int * cSize = new int[ nCols ],
* rSize = new int[ nRows ];
for ( int i = 0; i < nCols; i++ )
cSize[ i ] = vWidth;
for ( int i = 0; i < nRows; i++ )
rSize[ i ] = 0;
QValueVector< PageWidget * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end();
for ( ; pIt != pEnd; ++pIt )
{
PageWidget * p = *pIt;
// update internal page geometry
switch ( d->zoomMode )
{
case ZoomFitWidth:
p->setZoomFitWidth( vWidth - 5 );
break;
case ZoomFitPage:
p->setZoomFitRect( vWidth - 5, vHeight - 5 );
break;
default:
p->setZoomFixed( d->zoomFactor );
}
// find maximum for 'col' / 'row'
int pWidth = p->widthHint(),
pHeight = p->heightHint();
if ( pWidth > cSize[ cIdx ] )
cSize[ cIdx ] = pWidth;
if ( pHeight > rSize[ rIdx ] )
rSize[ rIdx ] = pHeight;
// update col/row indices
if ( ++cIdx == nCols )
{
cIdx = 0;
rIdx++;
}
}
// 2) dispose widgets inside cells
int currentHeight = 0,
currentWidth = 0;
cIdx = 0;
rIdx = 0;
for ( pIt = d->pages.begin(); pIt != pEnd; ++pIt )
{
PageWidget * p = *pIt;
int pWidth = p->widthHint(),
pHeight = p->heightHint(),
cWidth = cSize[ cIdx ],
rHeight = rSize[ rIdx ];
// center widget inside 'cells'
moveChild( p, currentWidth + (cWidth - pWidth) / 2,
currentHeight + (rHeight - pHeight) / 2 );
// display the widget
p->show();
// advance col/row index
currentWidth += cWidth;
if ( ++cIdx == nCols )
{
cIdx = 0;
rIdx++;
currentWidth = 0;
currentHeight += rHeight + 10;
}
}
// update scrollview's contents size (sets scrollbars limits)
currentWidth = 0;
for ( int i = 0; i < nCols; i++ )
currentWidth += cSize[ i ];
if ( cIdx != 0 )
currentHeight += rSize[ rIdx ] + 10;
resizeContents( currentWidth, currentHeight );
delete [] cSize;
delete [] rSize;
/*
// request for thumbnail generation
// an update is already scheduled, so don't proceed
if ( m_delayTimer && m_delayTimer->isActive() )
return;
int vHeight = visibleHeight(),
vOffset = newContentsY == -1 ? contentsY() : newContentsY;
// scroll from the top to the last visible thumbnail
QValueVector<ThumbnailWidget *>::iterator thumbIt = m_thumbnails.begin();
QValueVector<ThumbnailWidget *>::iterator thumbEnd = m_thumbnails.end();
for ( ; thumbIt != thumbEnd; ++thumbIt )
{
ThumbnailWidget * t = *thumbIt;
int top = childY( t ) - vOffset;
if ( top > vHeight )
break;
else if ( top + t->height() > 0 )
m_document->requestPixmap( THUMBNAILS_ID, t->pageNumber(), t->pixmapWidth(), t->pixmapHeight(), true );
}
*/
}
void PageView::pageSetCurrent( int /*pageNumber*/, float /*position*/ )
{
// select next page
d->vectorIndex = 0;
d->page = 0;
/*
QValueVector<int>::iterator pagesIt = d->pages.begin();
QValueVector<int>::iterator pagesEnd = d->pages.end();
for ( ; pagesIt != pagesEnd; ++pagesIt )
QValueVector< PageWidget * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end();
for ( ; pIt != pEnd; ++pIt )
{
if ( *pagesIt == pageNumber )
if ( (*pIt)->pageNumber() == pageNumber )
{
d->page = d->document->page( pageNumber );
d->page = *pIt;
break;
}
d->vectorIndex++;
d->vectorIndex ++;
}
*/
//if ( !d->page || d->page->width() < 1 || d->page->height() < 1 )
// return;
//slotUpdateView();
//verticalScrollBar()->setValue( (int)(position * verticalScrollBar()->maxValue()) );
if ( d->page )
{
int xPos = childX( d->page ) + d->page->widthHint() / 2,
yPos = childY( d->page ) + (int)((float)d->page->heightHint() * position);
center( xPos, yPos + visibleHeight() / 2 - 10 );
slotRequestVisiblePixmaps();
}
}
void PageView::notifyPixmapChanged( int pageNumber )
{
// check if it's the preview we're waiting for and update it
if ( d->page && (int)d->page->number() == pageNumber )
slotUpdateView();
QValueVector< PageWidget * >::iterator pIt = d->pages.begin(), pEnd = d->pages.end();
for ( ; pIt != pEnd; ++pIt )
if ( (*pIt)->pageNumber() == pageNumber )
{
(*pIt)->update();
break;
}
}
//END KPDFDocumentObserver inherited methods
@ -454,8 +353,6 @@ void PageView::viewportResizeEvent( QResizeEvent * )
connect( d->delayTimer, SIGNAL( timeout() ), this, SLOT( slotUpdateView() ) );
}
d->delayTimer->start( 400, true );
// recalc coordinates
//slotUpdateView( false );
}
void PageView::keyPressEvent( QKeyEvent * e )
@ -480,9 +377,11 @@ void PageView::keyPressEvent( QKeyEvent * e )
case Key_Right:
horizontalScrollBar()->addLine();
break;
case Key_Space:
if( e->state() != ShiftButton )
scrollDown();
case Key_PageUp:
verticalScrollBar()->subtractPage();
break;
case Key_PageDown:
verticalScrollBar()->addPage();
break;
default:
e->ignore();
@ -501,9 +400,9 @@ void PageView::wheelEvent( QWheelEvent *e )
else
slotZoomIn();
}
else if ( delta <= -120 && atBottom() )
else if ( delta <= -120 && atBottom() && !d->viewContinous )
scrollDown();
else if ( delta >= 120 && atTop() )
else if ( delta >= 120 && atTop() && !d->viewContinous )
scrollUp();
else
QScrollView::wheelEvent( e );
@ -602,16 +501,16 @@ void PageView::slotFitToTextToggled( bool on )
d->aZoomFitWidth->setChecked( false );
}
void PageView::slotSetViewSingle()
{ //TODO this
void PageView::slotTwoPagesToggled( bool on )
{
d->viewColumns = on ? 2 : 1;
reLayoutPages();
}
void PageView::slotSetViewDouble()
{ //TODO this
}
void PageView::slotSetViewContinous()
{ //TODO this
void PageView::slotContinousToggled( bool on )
{
d->viewContinous = on;
reLayoutPages();
}
void PageView::slotSetMouseNormal()
@ -636,41 +535,152 @@ void PageView::slotToggleScrollBars( bool on )
}
void PageView::slotUpdateView( bool /*repaint*/ )
{ //TODO ASYNC autogeneration!
reLayoutPages();
/* if ( !d->page )
{ //TODO ASYNC autogeneration!
reLayoutPages();
}
void PageView::slotRequestVisiblePixmaps( int newLeft, int newTop )
{
// // if an update is already scheduled or the widget is hidden, don't proceed
// if ( (m_delayTimer && m_delayTimer->isActive()) || !isShown() )
// return;
// 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 )
{
d->pageRect.setRect( 0, 0, 0, 0 );
resizeContents( 0, 0 );
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 );
}
else
{
// Zoom / AutoFit-Width / AutoFit-Page
double scale = d->zoomFactor;
if ( d->zoomMode == ZoomFitWidth || d->zoomMode == ZoomFitPage )
{
scale = (double)viewport()->width() / (double)d->page->width();
if ( d->zoomMode == ZoomFitPage )
{
double scaleH = (double)viewport()->height() / (double)d->page->height();
if ( scaleH < scale )
scale = scaleH;
}
}
int pageW = (int)( scale * d->page->width() ),
pageH = (int)( scale * d->page->height() ),
viewW = QMAX( viewport()->width(), pageW ),
viewH = QMAX( viewport()->height(), pageH );
d->pageRect.setRect( (viewW - pageW) / 2, (viewH - pageH) / 2, pageW, pageH );
resizeContents( viewW, viewH );
d->document->requestPixmap( PAGEVIEW_ID, d->page->number(), pageW, pageH, true );
}
if ( repaint )
viewport()->update();
*/
}
//END internal SLOTS
void PageView::reLayoutPages()
{
// 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(),
viewportHeight = clipper()->height();
if ( d->viewContinous == TRUE )
{
// 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 )
{
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 )
{
cIdx = 0;
rIdx++;
}
}
// 2) arrange widgets inside cells
int insertX = 0,
insertY = (int)(5.0 + 10.0 * d->zoomFactor);
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,
insertY + (rHeight - pHeight) / 2 );
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);
}
}
// 3) update scrollview's contents size and recenter view
int fullWidth = 0,
fullHeight = cIdx ? (insertY + rowHeight[ rIdx ] + 10) : insertY,
oldWidth = contentsWidth(),
oldHeight = contentsHeight();
for ( int i = 0; i < nCols; i++ )
fullWidth += colWidth[ i ];
resizeContents( fullWidth, fullHeight );
if ( oldWidth > 0 && oldHeight > 0 )
center( fullWidth * (contentsX() + visibleWidth() / 2) / oldWidth,
fullHeight * (contentsY() + visibleHeight() / 2) / oldHeight );
else
center( fullWidth / 2, 0 );
delete [] colWidth;
delete [] rowHeight;
}
else // viewContinous is FALSE
{
// hide all widgets except the displayable ones
QValueVector< PageWidget * >::iterator dIt = d->pages.begin(), dEnd = d->pages.end();
for ( ; dIt != dEnd; ++dIt )
(*dIt)->hide();
//
resizeContents( viewportWidth, viewportHeight );
}
// reset dirty state
d->dirty = false;
}
bool PageView::atTop() const
{
return verticalScrollBar()->value() == verticalScrollBar()->minValue();

View file

@ -1,11 +1,14 @@
/***************************************************************************
* 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 Kurt Pfeifle <kpfeifle@danka.de> *
* 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.h 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 Kurt Pfeifle <kpfeifle@danka.de> *
* *
* 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 *
@ -40,7 +43,6 @@ public:
~PageView();
// some enums used to control view behavior
enum ViewMode { ViewSingle, ViewDouble, ViewContinous };
enum ZoomMode { ZoomFixed, ZoomFitWidth, ZoomFitPage, ZoomFitText };
enum MouseMode { MouseNormal, MouseSelection, MouseEdit };
@ -55,52 +57,52 @@ public:
void notifyPixmapChanged( int pageNumber );
protected:
void contentsMousePressEvent( QMouseEvent* );
void contentsMouseReleaseEvent( QMouseEvent* );
void contentsMouseMoveEvent( QMouseEvent* );
void contentsMousePressEvent( QMouseEvent* );
void contentsMouseReleaseEvent( QMouseEvent* );
void contentsMouseMoveEvent( QMouseEvent* );
void viewportResizeEvent( QResizeEvent * );
void keyPressEvent( QKeyEvent* );
void wheelEvent( QWheelEvent * );
void viewportResizeEvent( QResizeEvent* );
void keyPressEvent( QKeyEvent* );
void wheelEvent( QWheelEvent* );
void dragEnterEvent( QDragEnterEvent* );
void dropEvent( QDropEvent* );
void dragEnterEvent( QDragEnterEvent* );
void dropEvent( QDropEvent* );
private slots:
// connected to local actions
void slotZoom( const QString& );
void slotZoomIn();
void slotZoomOut();
void slotFitToWidthToggled( bool );
// connected to local actions
void slotZoom( const QString& );
void slotZoomIn();
void slotZoomOut();
void slotFitToWidthToggled( bool );
void slotFitToPageToggled( bool );
void slotFitToTextToggled( bool );
void slotTwoPagesToggled( bool );
void slotContinousToggled( bool );
void slotSetMouseNormal();
void slotSetMouseSelect();
void slotSetMouseDraw();
void slotToggleScrollBars( bool on );
void slotSetViewSingle();
void slotSetViewDouble();
void slotSetViewContinous();
void slotSetMouseNormal();
void slotSetMouseSelect();
void slotSetMouseDraw();
void slotToggleScrollBars( bool on );
// activated directly or via QTimer on the viewportResizeEvent
void slotUpdateView( bool repaint = true );
// activated either directly or via QTimer on the viewportResizeEvent
void slotUpdateView( bool repaint = true );
// activated either directly or via the contentsMoving(int,int) signal
void slotRequestVisiblePixmaps( int left = -1, int top = -1 );
signals:
void urlDropped( const KURL& );
void rightClick();
void urlDropped( const KURL& );
void rightClick();
private:
void reLayoutPages();
// FIXME REMOVE ME what does atTop() means if I see 4 tiled pages on screen ?
bool atTop() const;
bool atBottom() const;
void scrollUp();
void scrollDown();
// FIXME REMOVE ME what does atTop() means if I see 4 tiled pages on screen ?
bool atTop() const;
bool atBottom() const;
void scrollUp();
void scrollDown();
// don't want to expose classes in here
class PageViewPrivate * d;
class PageViewPrivate * d;
};
#endif

View file

@ -10,6 +10,7 @@
#include <qpainter.h>
#include <qsize.h>
#include <kglobalsettings.h>
#include "pixmapwidget.h"
#include "document.h"
@ -29,10 +30,6 @@ void PixmapWidget::setZoomFixed( double magFactor )
m_pixmapWidth = (int)( magFactor * m_page->width() );
m_pixmapHeight = (int)( magFactor * m_page->height() );
m_zoomFactor = magFactor;
// resize the widget FIXME REMOVE THIS; TEMPORARY, resize from the outside
resize( m_marginLeft + m_pixmapWidth + m_marginRight,
m_marginTop + m_pixmapHeight + m_marginBottom );
}
void PixmapWidget::setZoomFitWidth( int width )
@ -41,9 +38,6 @@ void PixmapWidget::setZoomFitWidth( int width )
m_pixmapHeight = (int)(m_page->ratio() * m_pixmapWidth);
// compute equivalent zoom factor
m_zoomFactor = m_page->width() / (float)m_pixmapWidth;
// resize the widget FIXME REMOVE THIS; TEMPORARY, resize from the outside
resize( width, m_marginTop + m_pixmapHeight + m_marginBottom );
}
void PixmapWidget::setZoomFitRect( int rectWidth, int rectHeight )
@ -55,12 +49,6 @@ void PixmapWidget::setZoomFitRect( int rectWidth, int rectHeight )
setZoomFixed( scaleW < scaleH ? scaleW : scaleH );
}
QSize PixmapWidget::sizeHint() const
{
return QSize( m_marginLeft + m_pixmapWidth + m_marginRight,
m_marginTop + m_pixmapHeight + m_marginBottom );
}
int PixmapWidget::widthHint() const
{
return m_marginLeft + m_pixmapWidth + m_marginRight;
@ -71,11 +59,6 @@ int PixmapWidget::heightHint() const
return m_marginTop + m_pixmapHeight + m_marginBottom;
}
QSize PixmapWidget::pixmapSize() const
{
return QSize( m_pixmapWidth, m_pixmapHeight );
}
int PixmapWidget::pageNumber() const
{
return m_page->number();
@ -98,7 +81,6 @@ ThumbnailWidget::ThumbnailWidget( QWidget *parent, const KPDFPage *page )
m_labelNumber = page->number() + 1;
m_labelHeight = QFontMetrics( font() ).height();
setPixmapMargins( 2, 1, 2, m_labelHeight + 2 );
setPaletteBackgroundColor( palette().active().base() );
}
void ThumbnailWidget::setSelected( bool selected )
@ -146,44 +128,40 @@ void ThumbnailWidget::paintEvent( QPaintEvent * e )
PageWidget::PageWidget( QWidget *parent, const KPDFPage *page )
: PixmapWidget( parent, page )
{
//
//
setPixmapMargins( 1,1,3,3 );
// keep bottom equal to right margin
setPixmapMargins( 1, 1, 4, 4 );
}
void PageWidget::paintEvent( QPaintEvent * e )
{
QColor bc( paletteBackgroundColor() /*KGlobalSettings::calculateAlternateBackgroundColor( KGlobalSettings::baseColor() )*/ );
QRect clip = e->rect();
QRect pageClip = clip.intersect( QRect( m_marginLeft, m_marginTop, m_pixmapWidth, m_pixmapHeight ) );
QPainter p( this );
// if drawn region includes an edge of the page
if ( pageClip != clip )
if ( pageClip != clip && m_pixmapWidth > 10 && m_pixmapWidth > 10 )
{
// draw the outline and adapt pageClip
p.setPen( Qt::black );
// draw the black outline
p.drawRect( QRect( 0,0, m_pixmapWidth + 2, m_pixmapHeight + 2 ) );
p.setPen( Qt::gray );
/*
p.drawLine( pageClip.left(), pageClip.bottom() + 1, pageClip.right() + 1, pageClip.bottom() + 1 );
p.drawLine( pageClip.right() + 1, pageClip.top(), pageClip.right() + 1, pageClip.bottom() + 1 );
p.setPen( Qt::lightGray );
p.drawLine( pageClip.left(), pageClip.bottom() + 2, pageClip.right() + 2, pageClip.bottom() + 2 );
p.drawLine( pageClip.right() + 2, pageClip.top(), pageClip.right() + 2, pageClip.bottom() + 2 );
p.setPen( bc );
p.drawPoint( pageClip.left(), pageClip.bottom() + 2 );
p.drawPoint( pageClip.right() + 2, pageClip.top() );
pageClip.setWidth( pageClip.width() + 2 );
pageClip.setHeight( pageClip.height() + 2 );
*/
// draws shadow on left and bottom edges
int levels = m_marginBottom - 1;
p.fillRect( 0, 2 + m_pixmapHeight, levels, levels, Qt::gray );
p.fillRect( 2 + m_pixmapWidth, 0, levels, levels, Qt::gray );
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( 1 + i, m_pixmapHeight+2 + i, m_pixmapWidth+2 + i, m_pixmapHeight+2 + i );
p.drawLine( m_pixmapWidth+2 + i, 1 + i, m_pixmapWidth+2 + i, m_pixmapHeight+2 + i );
}
}
// draw page (inside pageClip rectangle)
p.translate( m_marginLeft, m_marginTop );
pageClip.moveBy( -m_marginLeft, -m_marginTop );
// TODO: accessibility settings: p.setRasterOp( Qt::NotCopyROP );
m_page->drawPixmap( PAGEVIEW_ID, &p, pageClip, m_pixmapWidth, m_pixmapHeight );
p.translate( -m_marginLeft, -m_marginTop );

View file

@ -31,10 +31,8 @@ public:
float zoomFactor() const { return m_zoomFactor; }
// full size (for resizing) and inner pixmap size
QSize sizeHint() const;
int widthHint() const;
int heightHint() const;
QSize pixmapSize() const;
int pixmapWidth() const { return m_pixmapWidth; }
int pixmapHeight() const { return m_pixmapHeight; }

View file

@ -10,6 +10,8 @@
#include <qtimer.h>
#include <klocale.h>
#include <kconfigbase.h>
#include <kurl.h>
#include <kurldrag.h>
#include <kaction.h>
#include <kactioncollection.h>
@ -17,9 +19,9 @@
#include "pixmapwidget.h"
#include "page.h"
ThumbnailList::ThumbnailList(QWidget *parent, KPDFDocument *document)
: QScrollView(parent, "KPDF::Thumbnails", WNoAutoErase),
m_document(document), m_selected(0), m_delayTimer(0)
ThumbnailList::ThumbnailList( QWidget *parent, KPDFDocument *document )
: QScrollView( parent, "KPDF::Thumbnails", WNoAutoErase | WStaticContents ),
m_document( document ), m_selected( 0 ), m_delayTimer( 0 )
{
// set scrollbars
setHScrollBarMode( QScrollView::AlwaysOff );
@ -28,10 +30,12 @@ ThumbnailList::ThumbnailList(QWidget *parent, KPDFDocument *document)
// dealing with large areas so enable clipper
enableClipper( true );
// can be focused by tab and mouse click and grabs key events
// widget setup: can be focused by tab and mouse click (not wheel)
viewport()->setFocusProxy( this );
viewport()->setFocusPolicy( StrongFocus );
setFocusPolicy( NoFocus );
setInputMethodEnabled( true );
viewport()->setPaletteBackgroundColor( Qt::gray );
setResizePolicy( Manual );
setAcceptDrops( true );
// set contents background to the 'base' color
viewport()->setPaletteBackgroundColor( palette().active().base() );
@ -40,20 +44,10 @@ ThumbnailList::ThumbnailList(QWidget *parent, KPDFDocument *document)
connect( this, SIGNAL(contentsMoving(int, int)), this, SLOT(slotRequestPixmaps(int, int)) );
}
void ThumbnailList::setupActions( KActionCollection * /*ac*/, KConfigGroup * /*config*/ )
{
}
void ThumbnailList::saveSettings( KConfigGroup * /*config*/ )
{
}
//BEGIN KPDFDocumentObserver inherited methods
void ThumbnailList::pageSetup( const QValueVector<KPDFPage*> & pages, bool documentChanged )
void ThumbnailList::pageSetup( const QValueVector<KPDFPage*> & pages, bool /*documentChanged*/ )
{
//TODO
documentChanged = false;
//TODO
// delete all the Thumbnails
QValueVector<ThumbnailWidget *>::iterator thumbIt = m_thumbnails.begin();
QValueVector<ThumbnailWidget *>::iterator thumbEnd = m_thumbnails.end();
@ -83,12 +77,14 @@ documentChanged = false;
for (; pageIt != pageEnd ; ++pageIt)
if ( skipCheck || (*pageIt)->isHilighted() ) {
t = new ThumbnailWidget( viewport(), *pageIt );
t->setFocusProxy( this );
// add to the scrollview
addChild( t, 0, totalHeight );
// add to the internal queue
m_thumbnails.push_back( t );
// update total height (asking widget its own height)
t->setZoomFitWidth( width );
t->setZoomFitWidth( width );
t->resize( t->widthHint(), t->heightHint() );
totalHeight += t->heightHint() + 4;
t->show();
}
@ -127,8 +123,7 @@ void ThumbnailList::pageSetCurrent( int pageNumber, float /*position*/ )
void ThumbnailList::notifyPixmapChanged( int pageNumber )
{
QValueVector<ThumbnailWidget *>::iterator thumbIt = m_thumbnails.begin();
QValueVector<ThumbnailWidget *>::iterator thumbEnd = m_thumbnails.end();
QValueVector<ThumbnailWidget *>::iterator thumbIt = m_thumbnails.begin(), thumbEnd = m_thumbnails.end();
for (; thumbIt != thumbEnd; ++thumbIt)
if ( (*thumbIt)->pageNumber() == pageNumber )
{
@ -136,6 +131,18 @@ void ThumbnailList::notifyPixmapChanged( int pageNumber )
break;
}
}
void ThumbnailList::dragEnterEvent( QDragEnterEvent * ev )
{
ev->accept();
}
void ThumbnailList::dropEvent( QDropEvent * ev )
{
KURL::List lst;
if ( KURLDrag::decode( ev, lst ) )
emit urlDropped( lst.first() );
}
//END KPDFDocumentObserver inherited methods
//BEGIN widget events
@ -191,9 +198,9 @@ void ThumbnailList::contentsMousePressEvent( QMouseEvent * e )
}
}
void ThumbnailList::viewportResizeEvent(QResizeEvent *e)
void ThumbnailList::viewportResizeEvent( QResizeEvent * e )
{
if ( m_thumbnails.count() < 1 || width() < 1 || !isShown() )
if ( m_thumbnails.count() < 1 || width() < 1 )
return;
// if width changed resize all the Thumbnails, reposition them to the
// right place and recalculate the contents area
@ -211,10 +218,10 @@ void ThumbnailList::viewportResizeEvent(QResizeEvent *e)
{
ThumbnailWidget *t = *thumbIt;
moveChild( t, 0, totalHeight );
t->setZoomFitWidth( newWidth );
totalHeight += t->heightHint() + 4;
t->show();
}
t->setZoomFitWidth( newWidth );
t->resize( t->widthHint(), t->heightHint() );
totalHeight += t->heightHint() + 4;
}
// update scrollview's contents size (sets scrollbars limits)
resizeContents( newWidth, totalHeight );
@ -228,13 +235,13 @@ void ThumbnailList::viewportResizeEvent(QResizeEvent *e)
// update Thumbnails since width has changed or height has increased
requestPixmaps( 500 );
}
//END widget events
//END widget events
//BEGIN internal SLOTS
void ThumbnailList::slotRequestPixmaps( int /*newContentsX*/, int newContentsY )
{
// an update is already scheduled, so don't proceed
if ( m_delayTimer && m_delayTimer->isActive() )
// if an update is already scheduled or the widget is hidden, don't proceed
if ( (m_delayTimer && m_delayTimer->isActive()) || !isShown() )
return;
int vHeight = visibleHeight(),
@ -265,16 +272,4 @@ void ThumbnailList::requestPixmaps( int delayMs )
m_delayTimer->start( delayMs, true );
}
/** class ThumbnailsBox **/
ThumbnailsBox::ThumbnailsBox( QWidget * parent ) : QVBox( parent )
{
}
QSize ThumbnailsBox::sizeHint() const
{
return QSize();
}
#include "thumbnaillist.moc"

View file

@ -33,8 +33,8 @@ Q_OBJECT
// create actions that interact with this widget and load/save settings
uint observerId() { return THUMBNAILS_ID; }
void setupActions( KActionCollection * collection, KConfigGroup * config );
void saveSettings( KConfigGroup * config );
void setupActions( KActionCollection * collection, KConfigGroup * config ) {};
void saveSettings( KConfigGroup * config ) {};
// create thumbnails ( inherited as a DocumentObserver )
void pageSetup( const QValueVector<KPDFPage*> & pages, bool documentChanged );
@ -55,6 +55,13 @@ Q_OBJECT
// resize thumbnails to fit the width
void viewportResizeEvent( QResizeEvent * );
// file drop related events (an url may be dropped even here)
void dragEnterEvent( QDragEnterEvent* );
void dropEvent( QDropEvent* );
signals:
void urlDropped( const KURL& );
public slots:
// make requests for generating pixmaps for visible thumbnails
void slotRequestPixmaps( int newContentsX = -1, int newContentsY = -1 );
@ -69,13 +76,13 @@ Q_OBJECT
};
/**
* @short A vertical boxed container with zero size hint (for left toolbox)
* @short A vertical boxed container with zero size hint (for insertion on left toolbox)
*/
class ThumbnailsBox : public QVBox
{
public:
ThumbnailsBox( QWidget * parent );
QSize sizeHint() const;
ThumbnailsBox( QWidget * parent ) : QVBox( parent ) {};
QSize sizeHint() const { return QSize(); }
};
#endif