Thumbnail and ThumbnailList classes completed. Optimized a lot! Too fast

now.. thre will be room for eye-candy in the future :-P. Drawing is scaled
via a qpainter xForm while resizing and a regeneration is performed
asyncronously when thumbnaillist's resizing is done.

svn path=/branches/kpdf_experiments/kdegraphics/kpdf/; revision=345459
remotes/origin/kpdf-experiments
Enrico Ros 22 years ago
parent daa42b1d56
commit 69bb375c49
  1. 13
      kpdf/TODO
  2. 142
      kpdf/kpdf_pagewidget.cc
  3. 20
      kpdf/kpdf_pagewidget.h
  4. 4
      kpdf/kpdf_part.cpp
  5. 34
      kpdf/page.cpp
  6. 5
      kpdf/page.h
  7. 85
      kpdf/thumbnail.cpp
  8. 27
      kpdf/thumbnail.h
  9. 25
      kpdf/thumbnaillist.cpp

@ -1,13 +1,18 @@
Personal Albert's list Personal Albert's list
-> make links functional -> make links functional
-> improve thumbnail generation to make it non-gui blocking
More items More items
-> merge lots of kpdf_part and part (centralview) code (to simplify/clenup)
-> previews sorted by visible areas (prioritize items where the scrollbar is)
-> maybe: use local instead of X memory for thumbnails (..)
-> screen editing: framework -> screen editing: framework
-> screen editing: tools -> screen editing: tools
Porting / In progress
-> implementing Document / Page using AACid's thread as the generation thread
-> improve thumbnail generation to make it non-gui blocking
-> multiple pages per view -> multiple pages per view
-> centering pages in the view -> centering pages in the view
-> outline bottom and right edges (of pages) -> outline bottom and right edges (of pages)
Done
-> merge lots of kpdf_part and part (centralview) code (to simplify/clenup)
-> maybe: use local instead of X memory for thumbnails (..)
-> previews sorted by visible areas (prioritize items where the scrollbar is)

@ -50,18 +50,41 @@ namespace KPDF
w->setPixmap( SmallIcon("up") ); w->setPixmap( SmallIcon("up") );
setCornerWidget( w ); setCornerWidget( w );
} }
PageWidget::~PageWidget() PageWidget::~PageWidget()
{ {
delete m_outputdev; delete m_outputdev;
} }
void
PageWidget::setPDFDocument(PDFDoc* doc) void PageWidget::pageSetup( const QValueList<int> & /*pages*/ )
{ {
m_doc = doc; /*
m_outputdev -> startDoc(doc->getXRef()); m_doc = doc;
m_currentPage = 1; m_outputdev -> startDoc(doc->getXRef());
updatePixmap(); m_currentPage = 1;
} updatePixmap();
*/
}
void PageWidget::pageSetCurrent( int /*pageNumber*/, float /*position*/ )
{
/*
// any idea why this mutex is necessary?
static QMutex mutex;
m_selection = false;
Q_ASSERT(mutex.locked() == false);
mutex.lock();
if (m_doc)
{
m_currentPage = pageNumber;
} else {
m_currentPage = 0;
}
updatePixmap();
mutex.unlock();
*/
}
void void
PageWidget::setPixelsPerPoint(float ppp) PageWidget::setPixelsPerPoint(float ppp)
@ -126,7 +149,7 @@ namespace KPDF
} }
void PageWidget::drawContents ( QPainter *p, int clipx, int clipy, int clipw, int cliph ) void PageWidget::drawContents ( QPainter *p, int clipx, int clipy, int clipw, int cliph )
{ {return;
QImage im; QImage im;
QColor bc(KGlobalSettings::calculateAlternateBackgroundColor(KGlobalSettings::baseColor())); QColor bc(KGlobalSettings::calculateAlternateBackgroundColor(KGlobalSettings::baseColor()));
if (m_outputdev) if (m_outputdev)
@ -181,50 +204,12 @@ namespace KPDF
updatePixmap(); updatePixmap();
} }
void PageWidget::setPage(int page)
{
// any idea why this mutex is necessary?
static QMutex mutex;
m_selection = false;
Q_ASSERT(mutex.locked() == false);
mutex.lock();
if (m_doc)
{
m_currentPage = page;
} else {
m_currentPage = 0;
}
updatePixmap();
mutex.unlock();
}
void PageWidget::enableScrollBars( bool b ) void PageWidget::enableScrollBars( bool b )
{ {
setHScrollBarMode( b ? Auto : AlwaysOff ); setHScrollBarMode( b ? Auto : AlwaysOff );
setVScrollBarMode( b ? Auto : AlwaysOff ); setVScrollBarMode( b ? Auto : AlwaysOff );
} }
void PageWidget::scrollRight()
{
horizontalScrollBar()->addLine();
}
void PageWidget::scrollLeft()
{
horizontalScrollBar()->subtractLine();
}
void PageWidget::scrollDown()
{
verticalScrollBar()->addLine();
}
void PageWidget::scrollUp()
{
verticalScrollBar()->subtractLine();
}
void PageWidget::scrollBottom() void PageWidget::scrollBottom()
{ {
verticalScrollBar()->setValue( verticalScrollBar()->maxValue() ); verticalScrollBar()->setValue( verticalScrollBar()->maxValue() );
@ -235,39 +220,36 @@ namespace KPDF
verticalScrollBar()->setValue( verticalScrollBar()->minValue() ); verticalScrollBar()->setValue( verticalScrollBar()->minValue() );
} }
void PageWidget::keyPressEvent( QKeyEvent* e ) void PageWidget::keyPressEvent( QKeyEvent* e )
{ {
switch ( e->key() ) { switch ( e->key() ) {
case Key_Up: case Key_Up:
if ( atTop() ) if ( atTop() )
emit ReadUp(); emit ReadUp();
else else
scrollUp(); verticalScrollBar()->subtractLine();
break; break;
case Key_Down: case Key_Down:
if ( atBottom() ) if ( atBottom() )
emit ReadDown(); emit ReadDown();
else else
scrollDown(); verticalScrollBar()->addLine();
break; break;
case Key_Left: case Key_Left:
scrollLeft(); horizontalScrollBar()->subtractLine();
break; break;
case Key_Right: case Key_Right:
scrollRight(); horizontalScrollBar()->addLine();
break; break;
case Key_Space: case Key_Space:
{ if( e->state() != ShiftButton )
if( e->state() != ShiftButton ) { emit spacePressed();
emit spacePressed(); default:
} e->ignore();
} return;
default: }
e->ignore(); e->accept();
return; }
}
e->accept();
}
bool PageWidget::atTop() const bool PageWidget::atTop() const
{ {

@ -44,21 +44,15 @@ namespace KPDF
public: public:
PageWidget(QWidget *parent, KPDFDocument *document); PageWidget(QWidget *parent, KPDFDocument *document);
~PageWidget(); ~PageWidget();
void setPDFDocument(PDFDoc*);
void setPixelsPerPoint(float); void setPixelsPerPoint(float);
/* void setLinks(); */ /* void setLinks(); */
// inherited from KPDFDocumentObserver // inherited from KPDFDocumentObserver
void pageSetup( const QValueList<int> & /*pages*/ ) void pageSetup( const QValueList<int> & pages );
{/* void pageSetCurrent( int pageNumber, float position );
m_outputDev->setPDFDocument(d->pdfdoc);
*/}
void pageSetCurrent( int /*pageNumber*/, float /*position*/ )
{
//m_pageWidget->setPage(m_currentPage);
}
void setPage(int pagenum);
void enableScrollBars( bool b ); void enableScrollBars( bool b );
/** /**
* Return true if the top resp. bottom of the page is visible. * Return true if the top resp. bottom of the page is visible.
@ -74,10 +68,6 @@ namespace KPDF
void zoomOut(); void zoomOut();
void updatePixmap(); void updatePixmap();
void scrollUp();
void scrollDown();
void scrollRight();
void scrollLeft();
void scrollBottom(); void scrollBottom();
void scrollTop(); void scrollTop();
bool readUp(); bool readUp();

@ -69,7 +69,9 @@ Part::Part(QWidget *parentWidget, const char *widgetName,
// create browser extension (for printing when embedded into browser) // create browser extension (for printing when embedded into browser)
new BrowserExtension(this); new BrowserExtension(this);
// xpdf 'extern' global class (m_count is a static instance counter) TODO check for wasted creation // xpdf 'extern' global class (m_count is a static instance counter)
//if ( m_count ) TODO check if we need to insert these lines..
// delete globalParams;
globalParams = new GlobalParams(""); globalParams = new GlobalParams("");
globalParams->setupBaseFonts(NULL); globalParams->setupBaseFonts(NULL);
m_count++; m_count++;

@ -7,7 +7,8 @@
* (at your option) any later version. * * (at your option) any later version. *
***************************************************************************/ ***************************************************************************/
// qt includes // qt includes
#include <qapplication.h>
#include <qpixmap.h> #include <qpixmap.h>
#include <qstring.h> #include <qstring.h>
#include <qpainter.h> #include <qpainter.h>
@ -16,18 +17,21 @@
#include "TextOutputDev.h" #include "TextOutputDev.h"
#include "page.h" #include "page.h"
#include <qimage.h>
KPDFPage::KPDFPage( uint i, float w, float h ) KPDFPage::KPDFPage( uint page, float w, float h )
: m_number( i ), m_width( w ), m_height( h ), m_zoom( 1 ), : m_number( page ), m_width( w ), m_height( h ), m_zoom( 1 ),
m_pixmap( 0 ), m_thumbnail( 0 ), m_text( 0 ), m_overlay( 0 ) m_pixmap( 0 ), m_thumbnail( 0 ), m_text( 0 ), m_overlay( 0 )
{ {
printf( "hello %d ", i ); /* m_thumbnail = new QPixmap( "/a.png", "PNG" );
m_thumbnail = new QPixmap( "/a.png", "PNG" ); QImage im = m_thumbnail->convertToImage();
im = im.smoothScale(100,100);
im.setAlphaBuffer( false );
m_thumbnail->convertFromImage(im);
*/
} }
KPDFPage::~KPDFPage() KPDFPage::~KPDFPage()
{ {
printf( "bye[%d] ", m_number );
delete m_pixmap; delete m_pixmap;
delete m_thumbnail; delete m_thumbnail;
delete m_text; delete m_text;
@ -47,15 +51,21 @@ void KPDFPage::drawPixmap( QPainter * p, const QRect & limits ) const // MUTEXE
//threadLock.unlock(); //threadLock.unlock();
} }
void KPDFPage::drawThumbnail( QPainter * p, const QRect & limits ) const // MUTEXED void KPDFPage::drawThumbnail( QPainter * p, const QRect & limits, int width, int height ) const // OK
{ {
//threadLock.lock(); //threadLock.lock();
if ( m_thumbnail ) if ( m_thumbnail )
p->drawPixmap( limits.topLeft(), *m_thumbnail, limits ); {
if ( m_thumbnail->width() == width && m_thumbnail->height() == height )
p->drawPixmap( limits.topLeft(), *m_thumbnail, limits );
else
{
p->scale( width / (double)m_thumbnail->width(), height / (double)m_thumbnail->height() );
p->drawPixmap( 0,0, *m_thumbnail, 0,0, m_thumbnail->width(), m_thumbnail->height() );
}
}
else else
p->fillRect( limits, Qt::red ); p->fillRect( limits, QApplication::palette().active().base() );
//threadLock.unlock(); //threadLock.unlock();
} }

@ -13,7 +13,6 @@
#include <qobject.h> #include <qobject.h>
#include <qsize.h> #include <qsize.h>
#include <qmutex.h> #include <qmutex.h>
#include "document.h"
class QPixmap; class QPixmap;
class QString; class QString;
@ -34,7 +33,7 @@ class PageOverlay{ /*fake temp*/ };
* class is destroyed. * class is destroyed.
*/ */
class KPDFPage : public QObject, public KPDFDocumentObserver class KPDFPage : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -50,7 +49,7 @@ public:
// rendering // rendering
void drawPixmap( QPainter * p, const QRect & rect ) const; void drawPixmap( QPainter * p, const QRect & rect ) const;
void drawThumbnail( QPainter * p, const QRect & rect ) const; void drawThumbnail( QPainter * p, const QRect & rect, int width, int height ) const;
float currentZoom() const { return m_zoom; } float currentZoom() const { return m_zoom; }
const QSize & currentSize() const { return m_size; } const QSize & currentSize() const { return m_size; }

@ -7,50 +7,83 @@
* (at your option) any later version. * * (at your option) any later version. *
***************************************************************************/ ***************************************************************************/
#include <qapplication.h>
#include <qimage.h>
#include <qlabel.h> #include <qlabel.h>
#include <qpixmap.h> #include <qpainter.h>
#include "thumbnail.h" #include "thumbnail.h"
#include "page.h" #include "page.h"
Thumbnail::Thumbnail(QWidget *parent, const QColor &color, const KPDFPage *page) : QVBox(parent), m_page(page), m_backgroundColor(color) Thumbnail::Thumbnail( QWidget *parent, const KPDFPage *page )
: QWidget( parent ), m_page( page ), m_previewWidth( 0 ), m_previewHeight( 0 )
{ {
m_thumbnailW = new QWidget(this); m_label = new QLabel( QString::number( page->number() + 1 ), this );
m_thumbnailW->setEraseColor(Qt::gray); m_label->setAlignment( AlignCenter );
m_label = new QLabel(QString::number(page->number()+1), this); setPaletteBackgroundColor( palette().active().base() );
m_label->setAlignment(AlignCenter);
setPaletteBackgroundColor(m_backgroundColor);
} }
int Thumbnail::pageNumber() //BEGIN commands
int Thumbnail::setThumbnailWidth( int width )
{ {
return m_page->number(); // compute and update drawable area dimensions
// note: 3 pixels are left (in each dimension) for page decorations
m_previewWidth = width - 3;
//TODO albert: check page rotation for aspect ratio
m_previewHeight = (int)(m_page->ratio() * width);
// reposition label at bottom
int labelHeight = m_label->sizeHint().height();
m_label->setGeometry( 0, m_previewHeight + 3, width, labelHeight );
// resize the widget
int totalHeight = m_previewHeight + 3 + labelHeight;
resize( width, totalHeight );
// return this->height plus a little (4px) margin to the next page
return totalHeight + 4;
}
void Thumbnail::setSelected( bool selected )
{
// alternate 'base' or 'hilight' colors to represent selection
if (selected) m_label->setPaletteBackgroundColor( palette().active().highlight() );
else m_label->setPaletteBackgroundColor( palette().active().base() );
} }
//END commands
void Thumbnail::setImage(const QImage *thumbnail) //BEGIN query methods
int Thumbnail::pageNumber() const
{ {
// TODO i am almost sure this can be done inside the thumbnailgenerator thread return m_page->number();
m_original = thumbnail->smoothScale(m_thumbnailW->size());
m_thumbnailW->setPaletteBackgroundPixmap(m_original);
} }
int Thumbnail::setThumbnailWidth(int width) int Thumbnail::previewWidth() const
{ {
int height = (int)(m_page->ratio() * width); return m_previewWidth;
m_thumbnailW->setFixedHeight(height);
m_thumbnailW->setFixedWidth(width);
height += m_label->sizeHint().height();
resize( width, height );
return height;
} }
void Thumbnail::setSelected(bool selected) int Thumbnail::previewHeight() const
{ {
if (selected) setPaletteBackgroundColor(QApplication::palette().active().highlight()); return m_previewHeight;
else setPaletteBackgroundColor(m_backgroundColor);
} }
//END query methods
void Thumbnail::paintEvent( QPaintEvent * e )
{
QRect clipRect = e->rect();
QPainter p( this );
// draw page outline
p.setPen( Qt::black );
p.drawRect( 0, 0, m_previewWidth + 2, m_previewHeight + 2 );
p.setPen( Qt::gray );
p.drawLine( 4, m_previewHeight + 2, m_previewWidth + 2, m_previewHeight + 2 );
p.drawLine( m_previewWidth + 2, 4, m_previewWidth + 2, m_previewHeight + 2 );
// draw the pixmap
p.translate( 1, 1 );
clipRect.moveBy( -1, -1 );
clipRect = clipRect.intersect( QRect( 0, 0, m_previewWidth, m_previewHeight ) );
m_page->drawThumbnail( &p, clipRect, m_previewWidth, m_previewHeight );
#include "thumbnail.moc" p.end();
}

@ -10,30 +10,33 @@
#ifndef THUMBNAIL_H #ifndef THUMBNAIL_H
#define THUMBNAIL_H #define THUMBNAIL_H
#include <qcolor.h> #include <qwidget.h>
#include <qimage.h>
#include <qvbox.h>
class QLabel; class QLabel;
class KPDFPage; class KPDFPage;
class Thumbnail : public QVBox class Thumbnail : public QWidget
{ {
Q_OBJECT
public: public:
Thumbnail(QWidget *parent, const QColor &color, const KPDFPage *page); Thumbnail(QWidget *parent, const KPDFPage *page);
int pageNumber(); // resize / select commands
void setImage(const QImage *thumbnail); int setThumbnailWidth(int width);
int setThumbnailWidth( int w );
void setSelected(bool selected); void setSelected(bool selected);
// query methods
int pageNumber() const;
int previewWidth() const;
int previewHeight() const;
protected:
void paintEvent(QPaintEvent *);
private: private:
QWidget *m_thumbnailW;
QLabel *m_label; QLabel *m_label;
const KPDFPage *m_page; const KPDFPage *m_page;
QColor m_backgroundColor; uint m_previewWidth;
QImage m_original; uint m_previewHeight;
}; };
#endif #endif

@ -30,6 +30,7 @@ ThumbnailList::ThumbnailList(QWidget *parent, KPDFDocument *document)
// set contents background to the 'base' color // set contents background to the 'base' color
viewport()->setPaletteBackgroundColor( palette().active().base() ); viewport()->setPaletteBackgroundColor( palette().active().base() );
setFrameStyle( StyledPanel | Raised );
connect( this, SIGNAL(contentsMoving(int, int)), this, SLOT(slotRequestThumbnails(int, int)) ); connect( this, SIGNAL(contentsMoving(int, int)), this, SLOT(slotRequestThumbnails(int, int)) );
} }
@ -58,7 +59,7 @@ void ThumbnailList::pageSetup( const QValueList<int> & pages )
QValueList<int>::const_iterator pageEnd = pages.end(); QValueList<int>::const_iterator pageEnd = pages.end();
for (; pageIt != pageEnd ; ++pageIt) for (; pageIt != pageEnd ; ++pageIt)
{ {
t = new Thumbnail( viewport(), viewport()->paletteBackgroundColor(), m_document->page(*pageIt) ); t = new Thumbnail( viewport(), m_document->page(*pageIt) );
// add to the scrollview // add to the scrollview
addChild( t, 0, totalHeight ); addChild( t, 0, totalHeight );
// add to the internal queue // add to the internal queue
@ -117,21 +118,32 @@ void ThumbnailList::notifyThumbnailChanged( int pageNumber )
void ThumbnailList::keyPressEvent( QKeyEvent * keyEvent ) void ThumbnailList::keyPressEvent( QKeyEvent * keyEvent )
{ {
if ( thumbnails.count() < 1 ) if ( thumbnails.count() < 1 )
return; return keyEvent->ignore();
if ( keyEvent->key() == Key_Up ) if ( keyEvent->key() == Key_Up )
{ {
if ( !m_selected ) if ( !m_selected )
m_document->slotSetCurrentPage( 0 ); m_document->slotSetCurrentPage( 0 );
else if ( vectorIndex > 0 ) else if ( vectorIndex > 0 )
m_document->slotSetCurrentPage( thumbnails[ --vectorIndex ]->pageNumber() ); m_document->slotSetCurrentPage( thumbnails[ vectorIndex - 1 ]->pageNumber() );
else
return keyEvent->ignore();
} }
else if ( keyEvent->key() == Key_Down ) else if ( keyEvent->key() == Key_Down )
{ {
if ( !m_selected ) if ( !m_selected )
m_document->slotSetCurrentPage( 0 ); m_document->slotSetCurrentPage( 0 );
else if ( vectorIndex < (int)thumbnails.count() - 1 ) else if ( vectorIndex < (int)thumbnails.count() - 1 )
m_document->slotSetCurrentPage( thumbnails[ ++vectorIndex ]->pageNumber() ); m_document->slotSetCurrentPage( thumbnails[ vectorIndex + 1 ]->pageNumber() );
else
return keyEvent->ignore();
} }
else if ( keyEvent->key() == Key_Home )
m_document->slotSetCurrentPage( thumbnails[ 0 ]->pageNumber() );
else if ( keyEvent->key() == Key_End )
m_document->slotSetCurrentPage( thumbnails[ thumbnails.count() - 1 ]->pageNumber() );
else
return keyEvent->ignore();
keyEvent->accept();
} }
void ThumbnailList::contentsMousePressEvent( QMouseEvent * e ) void ThumbnailList::contentsMousePressEvent( QMouseEvent * e )
@ -159,6 +171,7 @@ void ThumbnailList::viewportResizeEvent(QResizeEvent *e)
// right place and recalculate the contents area // right place and recalculate the contents area
if ( e->size().width() != e->oldSize().width() ) if ( e->size().width() != e->oldSize().width() )
{ {
// resize and reposition items
int totalHeight = 0, int totalHeight = 0,
newWidth = e->size().width(); newWidth = e->size().width();
QValueVector<Thumbnail *>::iterator thumbIt = thumbnails.begin(); QValueVector<Thumbnail *>::iterator thumbIt = thumbnails.begin();
@ -187,6 +200,10 @@ void ThumbnailList::viewportResizeEvent(QResizeEvent *e)
//BEGIN internal SLOTS //BEGIN internal SLOTS
void ThumbnailList::slotRequestThumbnails( int /*newContentsX*/, int newContentsY ) void ThumbnailList::slotRequestThumbnails( int /*newContentsX*/, int newContentsY )
{ {
// an update is already scheduled, so don't proceed
if ( m_delayTimer && m_delayTimer->isActive() )
return;
int vHeight = visibleHeight(), int vHeight = visibleHeight(),
vOffset = newContentsY == -1 ? contentsY() : newContentsY; vOffset = newContentsY == -1 ? contentsY() : newContentsY;

Loading…
Cancel
Save