1 /***************************************************************************
2 * Copyright (C) 2004-2006 by Albert Astals Cid <tsdgeos@terra.es> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 ***************************************************************************/
10 #include "thumbnaillist.h"
16 #include <qscrollbar.h>
17 #include <qsizepolicy.h>
22 #include <kiconloader.h>
23 #include <kactioncollection.h>
27 #include "pagepainter.h"
28 #include "core/area.h"
29 #include "core/bookmarkmanager.h"
30 #include "core/document.h"
31 #include "core/generator.h"
32 #include "core/page.h"
35 class ThumbnailWidget
;
37 class ThumbnailListPrivate
: public QWidget
40 ThumbnailListPrivate( ThumbnailList
*qq
, Okular::Document
*document
);
41 ~ThumbnailListPrivate();
44 Okular::Document
*m_document
;
45 ThumbnailWidget
*m_selected
;
47 QPixmap
*m_bookmarkOverlay
;
48 QVector
<ThumbnailWidget
*> m_thumbnails
;
49 QList
<ThumbnailWidget
*> m_visibleThumbnails
;
52 // this is a (temporary) HACK to prevent jumping of the selected area
53 // when dragging the mouse between pages
54 ThumbnailWidget
*mouseGrabItem
;
56 // resize thumbnails to fit the width
57 void viewportResizeEvent( QResizeEvent
* );
58 // called by ThumbnailWidgets to get the overlay bookmark pixmap
59 const QPixmap
* getBookmarkOverlay() const;
60 // called by ThumbnailWidgets to send (forward) the mouse move signals
61 void forwardTrack( const Okular::Page
*, const QPoint
&, const QSize
& );
63 ThumbnailWidget
* itemFor( const QPoint
& p
) const;
64 void delayedRequestVisiblePixmaps( int delayMs
= 0 );
67 // make requests for generating pixmaps for visible thumbnails
68 void slotRequestVisiblePixmaps( int newContentsY
= -1 );
69 // delay timeout: resize overlays and requests pixmaps
70 void slotDelayTimeout();
73 void mousePressEvent( QMouseEvent
* e
);
74 void mouseReleaseEvent( QMouseEvent
* e
);
75 void mouseMoveEvent( QMouseEvent
* e
);
76 void wheelEvent( QWheelEvent
* e
);
77 void contextMenuEvent( QContextMenuEvent
* e
);
78 void paintEvent( QPaintEvent
* e
);
82 // ThumbnailWidget represents a single thumbnail in the ThumbnailList
86 ThumbnailWidget( ThumbnailListPrivate
* parent
, const Okular::Page
* page
);
88 // set internal parameters to fit the page in the given width
89 void resizeFitWidth( int width
);
90 // set thumbnail's selected state
91 void setSelected( bool selected
);
92 // set the visible rect of the current page
93 void setVisibleRect( const Okular::NormalizedRect
& rect
);
96 int heightHint() const { return m_pixmapHeight
+ m_labelHeight
+ m_margin
; }
97 int pixmapWidth() const { return m_pixmapWidth
; }
98 int pixmapHeight() const { return m_pixmapHeight
; }
99 int pageNumber() const { return m_page
->number(); }
100 const Okular::Page
* page() const { return m_page
; }
101 QRect
visibleRect() const { return m_visibleRect
.geometry( m_pixmapWidth
, m_pixmapHeight
); }
103 void paint( QPainter
&p
, const QRect
&clipRect
);
105 static int margin() { return m_margin
; }
107 // simulating QWidget
108 QRect
rect() const { return m_rect
; }
109 int height() const { return m_rect
.height(); }
110 int width() const { return m_rect
.width(); }
111 QPoint
pos() const { return m_rect
.topLeft(); }
112 void move( int x
, int y
) { m_rect
.setTopLeft( QPoint( x
, y
) ); }
113 void update() { m_parent
->update( m_rect
); }
114 void update( const QRect
& rect
) { m_parent
->update( rect
.translated( m_rect
.topLeft() ) ); }
117 // the margin around the widget
118 static int const m_margin
= 16;
120 ThumbnailListPrivate
* m_parent
;
121 const Okular::Page
* m_page
;
123 int m_pixmapWidth
, m_pixmapHeight
;
124 int m_labelHeight
, m_labelNumber
;
125 Okular::NormalizedRect m_visibleRect
;
130 ThumbnailListPrivate::ThumbnailListPrivate( ThumbnailList
*qq
, Okular::Document
*document
)
131 : QWidget(), q( qq
), m_document( document
), m_selected( 0 ),
132 m_delayTimer( 0 ), m_bookmarkOverlay( 0 )
134 setMouseTracking( true );
138 ThumbnailListPrivate::~ThumbnailListPrivate()
142 ThumbnailWidget
* ThumbnailListPrivate::itemFor( const QPoint
& p
) const
144 QVector
< ThumbnailWidget
* >::const_iterator tIt
= m_thumbnails
.begin(), tEnd
= m_thumbnails
.end();
145 for ( ; tIt
!= tEnd
; ++tIt
)
147 if ( (*tIt
)->rect().contains( p
) )
153 void ThumbnailListPrivate::paintEvent( QPaintEvent
* e
)
155 QPainter
painter( this );
156 QVector
<ThumbnailWidget
*>::const_iterator tIt
= m_thumbnails
.begin(), tEnd
= m_thumbnails
.end();
157 for ( ; tIt
!= tEnd
; ++tIt
)
159 QRect rect
= e
->rect().intersected( (*tIt
)->rect() );
160 if ( !rect
.isNull() )
162 rect
.translate( -(*tIt
)->pos() );
164 painter
.translate( (*tIt
)->pos() );
165 (*tIt
)->paint( painter
, rect
);
172 /** ThumbnailList implementation **/
174 ThumbnailList::ThumbnailList( QWidget
*parent
, Okular::Document
*document
)
175 : QScrollArea( parent
), d( new ThumbnailListPrivate( this, document
) )
177 setObjectName( "okular::Thumbnails" );
179 setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff
);
180 setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn
);
181 verticalScrollBar()->setEnabled( false );
183 setAttribute( Qt::WA_StaticContents
);
185 setAcceptDrops( true );
187 QPalette pal
= palette();
188 // set contents background to the 'base' color
189 QPalette viewportPal
= viewport()->palette();
190 viewportPal
.setColor( viewport()->backgroundRole(), pal
.color( QPalette::Base
) );
191 viewport()->setPalette( viewportPal
);
194 // widget setup: can be focused by tab and mouse click (not wheel)
195 widget()->setFocusPolicy( Qt::StrongFocus
);
197 QPalette widgetPal
= widget()->palette();
198 widgetPal
.setColor( widget()->backgroundRole(), pal
.color( QPalette::Base
) );
199 widget()->setPalette( widgetPal
);
201 connect( verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(slotRequestVisiblePixmaps(int)) );
204 ThumbnailList::~ThumbnailList()
206 d
->m_document
->removeObserver( this );
207 delete d
->m_bookmarkOverlay
;
210 //BEGIN DocumentObserver inherited methods
211 void ThumbnailList::notifySetup( const QVector
< Okular::Page
* > & pages
, int setupFlags
)
213 // if there was a widget selected, save its pagenumber to restore
214 // its selection (if available in the new set of pages)
216 if ( !( setupFlags
& Okular::DocumentObserver::DocumentChanged
) && d
->m_selected
)
218 prevPage
= d
->m_selected
->page()->number();
221 // delete all the Thumbnails
222 QVector
<ThumbnailWidget
*>::const_iterator tIt
= d
->m_thumbnails
.begin(), tEnd
= d
->m_thumbnails
.end();
223 for ( ; tIt
!= tEnd
; ++tIt
)
225 d
->m_thumbnails
.clear();
226 d
->m_visibleThumbnails
.clear();
228 d
->mouseGrabItem
= 0;
230 if ( pages
.count() < 1 )
232 widget()->resize( 0, 0 );
236 // show pages containing hilighted text or bookmarked ones
237 //RESTORE THIS int flags = Okular::Settings::filterBookmarks() ? Okular::Page::Bookmark : Okular::Page::Highlight;
239 // if no page matches filter rule, then display all pages
240 QVector
< Okular::Page
* >::const_iterator pIt
= pages
.begin(), pEnd
= pages
.end();
241 bool skipCheck
= true;
242 for ( ; pIt
!= pEnd
; ++pIt
)
243 //if ( (*pIt)->attributes() & flags )
244 if ( (*pIt
)->hasHighlights( SW_SEARCH_ID
) )
247 // generate Thumbnails for the given set of pages
248 int width
= viewport()->width();
250 for ( pIt
= pages
.begin(); pIt
!= pEnd
; ++pIt
)
251 //if ( skipCheck || (*pIt)->attributes() & flags )
252 if ( skipCheck
|| (*pIt
)->hasHighlights( SW_SEARCH_ID
) )
254 ThumbnailWidget
* t
= new ThumbnailWidget( d
, *pIt
);
256 // add to the internal queue
257 d
->m_thumbnails
.push_back( t
);
258 // update total height (asking widget its own height)
259 t
->resizeFitWidth( width
);
260 // restoring the previous selected page, if any
261 if ( (*pIt
)->number() == prevPage
)
264 d
->m_selected
->setSelected( true );
266 height
+= t
->height() + KDialog::spacingHint();
269 // update scrollview's contents size (sets scrollbars limits)
270 height
-= KDialog::spacingHint();
271 widget()->resize( width
, height
);
273 // enable scrollbar when there's something to scroll
274 verticalScrollBar()->setEnabled( viewport()->height() < height
);
276 // request for thumbnail generation
277 d
->delayedRequestVisiblePixmaps( 200 );
280 void ThumbnailList::notifyViewportChanged( bool /*smoothMove*/ )
282 // skip notifies for the current page (already selected)
283 int newPage
= d
->m_document
->viewport().pageNumber
;
284 if ( d
->m_selected
&& d
->m_selected
->pageNumber() == newPage
)
287 // deselect previous thumbnail
289 d
->m_selected
->setSelected( false );
292 // select the page with viewport and ensure it's centered in the view
293 d
->m_vectorIndex
= 0;
294 QVector
<ThumbnailWidget
*>::const_iterator tIt
= d
->m_thumbnails
.begin(), tEnd
= d
->m_thumbnails
.end();
295 for ( ; tIt
!= tEnd
; ++tIt
)
297 if ( (*tIt
)->pageNumber() == newPage
)
299 d
->m_selected
= *tIt
;
300 d
->m_selected
->setSelected( true );
301 if ( Okular::Settings::syncThumbnailsViewport() )
303 int yOffset
= qMax( viewport()->height() / 4, d
->m_selected
->height() / 2 );
304 ensureVisible( 0, d
->m_selected
->pos().y() + d
->m_selected
->height()/2, 0, yOffset
);
312 void ThumbnailList::notifyPageChanged( int pageNumber
, int changedFlags
)
314 static int interestingFlags
= DocumentObserver::Pixmap
| DocumentObserver::Bookmark
| DocumentObserver::Highlights
| DocumentObserver::Annotations
;
315 // only handle change notifications we are interested in
316 if ( !( changedFlags
& interestingFlags
) )
319 // iterate over visible items: if page(pageNumber) is one of them, repaint it
320 QList
<ThumbnailWidget
*>::const_iterator vIt
= d
->m_visibleThumbnails
.begin(), vEnd
= d
->m_visibleThumbnails
.end();
321 for ( ; vIt
!= vEnd
; ++vIt
)
322 if ( (*vIt
)->pageNumber() == pageNumber
)
329 void ThumbnailList::notifyContentsCleared( int changedFlags
)
331 // if pixmaps were cleared, re-ask them
332 if ( changedFlags
& DocumentObserver::Pixmap
)
333 d
->slotRequestVisiblePixmaps();
336 void ThumbnailList::notifyVisibleRectsChanged()
339 const QVector
<Okular::VisiblePageRect
*> & visibleRects
= d
->m_document
->visiblePageRects();
340 QVector
<ThumbnailWidget
*>::const_iterator tIt
= d
->m_thumbnails
.constBegin(), tEnd
= d
->m_thumbnails
.constEnd();
341 QVector
<Okular::VisiblePageRect
*>::const_iterator vEnd
= visibleRects
.end();
342 for ( ; tIt
!= tEnd
; ++tIt
)
345 QVector
<Okular::VisiblePageRect
*>::const_iterator vIt
= visibleRects
.begin();
346 for ( ; ( vIt
!= vEnd
) && !found
; ++vIt
)
348 if ( (*tIt
)->pageNumber() == (*vIt
)->pageNumber
)
350 (*tIt
)->setVisibleRect( (*vIt
)->rect
);
356 (*tIt
)->setVisibleRect( Okular::NormalizedRect() );
361 bool ThumbnailList::canUnloadPixmap( int pageNumber
) const
363 // if the thubnail 'pageNumber' is one of the visible ones, forbid unloading
364 QList
<ThumbnailWidget
*>::const_iterator vIt
= d
->m_visibleThumbnails
.begin(), vEnd
= d
->m_visibleThumbnails
.end();
365 for ( ; vIt
!= vEnd
; ++vIt
)
366 if ( (*vIt
)->pageNumber() == pageNumber
)
368 // if hidden permit unloading
371 //END DocumentObserver inherited methods
374 void ThumbnailList::updateWidgets()
376 // find all widgets that intersects the viewport and update them
377 QRect viewportRect
= viewport()->rect().translated( viewport()->pos() );
378 QList
<ThumbnailWidget
*>::const_iterator vIt
= d
->m_visibleThumbnails
.begin(), vEnd
= d
->m_visibleThumbnails
.end();
379 for ( ; vIt
!= vEnd
; ++vIt
)
381 ThumbnailWidget
* t
= *vIt
;
382 QRect thumbRect
= t
->rect().translated( widget()->mapToParent( t
->pos() ) );
383 // update only the exposed area of the widget (saves pixels..)
384 QRect relativeRect
= thumbRect
.intersect( viewport()->rect() );
385 if ( !relativeRect
.isValid() )
387 t
->update( relativeRect
);
391 void ThumbnailListPrivate::forwardTrack( const Okular::Page
* p
, const QPoint
&point
, const QSize
&s
)
393 Okular::DocumentViewport vp
=m_document
->viewport();
395 QVector
< Okular::VisiblePageRect
* > vVpr
= m_document
->visiblePageRects();
397 QVector
< Okular::VisiblePageRect
* >::const_iterator vIt
= vVpr
.begin();
398 QVector
< Okular::VisiblePageRect
* >::const_iterator vEnd
= vVpr
.end();
399 for ( ; vIt
!= vEnd
; ++vIt
)
401 Okular::VisiblePageRect
*vpr
= ( *vIt
);
402 if( vpr
->pageNumber
== p
->number() )
404 double w
= vpr
->rect
.right
- vpr
->rect
.left
,
405 h
= vpr
->rect
.bottom
- vpr
->rect
.top
,
406 deltaX
= (double)point
.x() / s
.width(),
407 deltaY
= (double)point
.y() / s
.height();
409 vp
.rePos
.normalizedX
-= deltaX
;
410 vp
.rePos
.normalizedY
-= deltaY
;
412 if( !vp
.rePos
.enabled
)
414 vp
.rePos
.enabled
= true;
415 vp
.rePos
.normalizedY
+= h
/2;
417 m_document
->setViewport( vp
);
423 const QPixmap
* ThumbnailListPrivate::getBookmarkOverlay() const
425 return m_bookmarkOverlay
;
428 void ThumbnailList::slotFilterBookmarks( bool filterOn
)
431 Okular::Settings::setFilterBookmarks( filterOn
);
432 Okular::Settings::self()->writeConfig();
433 // ask for the 'notifySetup' with a little trick (on reinsertion the
434 // document sends the list again)
435 d
->m_document
->removeObserver( this );
436 d
->m_document
->addObserver( this );
440 //BEGIN widget events
441 void ThumbnailList::keyPressEvent( QKeyEvent
* keyEvent
)
443 if ( d
->m_thumbnails
.count() < 1 )
444 return keyEvent
->ignore();
447 if ( keyEvent
->key() == Qt::Key_Up
)
449 if ( !d
->m_selected
)
451 else if ( d
->m_vectorIndex
> 0 )
452 nextPage
= d
->m_thumbnails
[ d
->m_vectorIndex
- 1 ]->pageNumber();
454 else if ( keyEvent
->key() == Qt::Key_Down
)
456 if ( !d
->m_selected
)
458 else if ( d
->m_vectorIndex
< (int)d
->m_thumbnails
.count() - 1 )
459 nextPage
= d
->m_thumbnails
[ d
->m_vectorIndex
+ 1 ]->pageNumber();
461 else if ( keyEvent
->key() == Qt::Key_PageUp
)
462 verticalScrollBar()->triggerAction( QScrollBar::SliderPageStepSub
);
463 else if ( keyEvent
->key() == Qt::Key_PageDown
)
464 verticalScrollBar()->triggerAction( QScrollBar::SliderPageStepAdd
);
465 else if ( keyEvent
->key() == Qt::Key_Home
)
466 nextPage
= d
->m_thumbnails
[ 0 ]->pageNumber();
467 else if ( keyEvent
->key() == Qt::Key_End
)
468 nextPage
= d
->m_thumbnails
[ d
->m_thumbnails
.count() - 1 ]->pageNumber();
470 if ( nextPage
== -1 )
471 return keyEvent
->ignore();
475 d
->m_selected
->setSelected( false );
477 d
->m_document
->setViewportPage( nextPage
);
480 bool ThumbnailList::viewportEvent( QEvent
* e
)
486 d
->viewportResizeEvent( (QResizeEvent
*)e
);
492 return QScrollArea::viewportEvent( e
);
495 void ThumbnailListPrivate::viewportResizeEvent( QResizeEvent
* e
)
497 if ( m_thumbnails
.count() < 1 || width() < 1 )
500 // if width changed resize all the Thumbnails, reposition them to the
501 // right place and recalculate the contents area
502 if ( e
->size().width() != e
->oldSize().width() )
504 // runs the timer avoiding a thumbnail regeneration by 'contentsMoving'
505 delayedRequestVisiblePixmaps( 2000 );
507 // resize and reposition items
508 int newWidth
= q
->viewport()->width();
510 QVector
<ThumbnailWidget
*>::const_iterator tIt
= m_thumbnails
.begin(), tEnd
= m_thumbnails
.end();
511 for ( ; tIt
!= tEnd
; ++tIt
)
513 ThumbnailWidget
*t
= *tIt
;
514 t
->move(0, newHeight
);
515 t
->resizeFitWidth( newWidth
);
516 newHeight
+= t
->height() + KDialog::spacingHint();
519 // update scrollview's contents size (sets scrollbars limits)
520 newHeight
-= KDialog::spacingHint();
521 q
->widget()->resize( newWidth
, newHeight
);
523 // enable scrollbar when there's something to scroll
524 q
->verticalScrollBar()->setEnabled( q
->viewport()->height() < newHeight
);
526 // ensure selected item remains visible
528 q
->ensureVisible( 0, m_selected
->pos().y() + m_selected
->height() / 2, 0, q
->viewport()->height() / 2 );
530 else if ( e
->size().height() <= e
->oldSize().height() )
533 // invalidate the bookmark overlay
534 if ( m_bookmarkOverlay
)
536 delete m_bookmarkOverlay
;
537 m_bookmarkOverlay
= 0;
540 // update Thumbnails since width has changed or height has increased
541 delayedRequestVisiblePixmaps( 500 );
544 void ThumbnailList::dragEnterEvent( QDragEnterEvent
* ev
)
549 void ThumbnailList::dropEvent( QDropEvent
* ev
)
551 if ( KUrl::List::canDecode( ev
->mimeData() ) )
552 emit
urlDropped( KUrl::List::fromMimeData( ev
->mimeData() ).first() );
556 //BEGIN internal SLOTS
557 void ThumbnailListPrivate::slotRequestVisiblePixmaps( int /*newContentsY*/ )
559 // if an update is already scheduled or the widget is hidden, don't proceed
560 if ( ( m_delayTimer
&& m_delayTimer
->isActive() ) || q
->isHidden() )
563 // scroll from the top to the last visible thumbnail
564 m_visibleThumbnails
.clear();
565 QLinkedList
< Okular::PixmapRequest
* > requestedPixmaps
;
566 QVector
<ThumbnailWidget
*>::const_iterator tIt
= m_thumbnails
.begin(), tEnd
= m_thumbnails
.end();
567 QRect viewportRect
= q
->viewport()->rect().translated( q
->horizontalScrollBar()->value(), q
->verticalScrollBar()->value() );
568 for ( ; tIt
!= tEnd
; ++tIt
)
570 ThumbnailWidget
* t
= *tIt
;
571 QRect thumbRect
= t
->rect();
572 if ( !thumbRect
.intersects( viewportRect
) )
574 // add ThumbnailWidget to visible list
575 m_visibleThumbnails
.push_back( t
);
576 // if pixmap not present add it to requests
577 if ( !t
->page()->hasPixmap( THUMBNAILS_ID
, t
->pixmapWidth(), t
->pixmapHeight() ) )
579 Okular::PixmapRequest
* p
= new Okular::PixmapRequest(
580 THUMBNAILS_ID
, t
->pageNumber(), t
->pixmapWidth(), t
->pixmapHeight(), THUMBNAILS_PRIO
, true );
581 requestedPixmaps
.push_back( p
);
585 // actually request pixmaps
586 if ( !requestedPixmaps
.isEmpty() )
587 m_document
->requestPixmaps( requestedPixmaps
);
590 void ThumbnailListPrivate::slotDelayTimeout()
592 // resize the bookmark overlay
593 delete m_bookmarkOverlay
;
594 int expectedWidth
= q
->viewport()->width() / 4;
595 if ( expectedWidth
> 10 )
596 m_bookmarkOverlay
= new QPixmap( DesktopIcon( "bookmarks", expectedWidth
) );
598 m_bookmarkOverlay
= 0;
601 slotRequestVisiblePixmaps();
605 void ThumbnailListPrivate::delayedRequestVisiblePixmaps( int delayMs
)
609 m_delayTimer
= new QTimer( q
);
610 m_delayTimer
->setSingleShot( true );
611 connect( m_delayTimer
, SIGNAL( timeout() ), q
, SLOT( slotDelayTimeout() ) );
613 m_delayTimer
->start( delayMs
);
617 /** ThumbnailWidget implementation **/
619 ThumbnailWidget::ThumbnailWidget( ThumbnailListPrivate
* parent
, const Okular::Page
* kp
)
620 : m_parent( parent
), m_page( kp
),
621 m_selected( false ), m_pixmapWidth( 10 ), m_pixmapHeight( 10 )
623 m_labelNumber
= m_page
->number() + 1;
624 m_labelHeight
= QFontMetrics( m_parent
->font() ).height();
628 void ThumbnailWidget::resizeFitWidth( int width
)
630 m_pixmapWidth
= width
- m_margin
;
631 m_pixmapHeight
= qRound( m_page
->ratio() * (double)m_pixmapWidth
);
632 m_rect
.setSize( QSize( width
, heightHint() ) );
635 void ThumbnailWidget::setSelected( bool selected
)
637 // update selected state
638 if ( m_selected
!= selected
)
640 m_selected
= selected
;
645 void ThumbnailWidget::setVisibleRect( const Okular::NormalizedRect
& rect
)
647 if ( rect
== m_visibleRect
)
650 m_visibleRect
= rect
;
654 void ThumbnailListPrivate::mousePressEvent( QMouseEvent
* e
)
656 ThumbnailWidget
* item
= itemFor( e
->pos() );
657 if ( !item
) // mouse on the spacing between items
660 QRect r
= item
->visibleRect();
661 int margin
= ThumbnailWidget::margin();
662 QPoint p
= e
->pos() - item
->pos();
664 if ( e
->button() != Qt::RightButton
&& r
.contains( p
- QPoint( margin
/ 2, margin
/ 2 ) ) )
666 mouseGrabPos
= e
->pos();
667 mouseGrabItem
= item
;
671 mouseGrabPos
.setX( 0 );
672 mouseGrabPos
.setY( 0 );
677 void ThumbnailListPrivate::mouseReleaseEvent( QMouseEvent
* e
)
679 ThumbnailWidget
* item
= itemFor( e
->pos() );
680 mouseGrabItem
= item
;
681 if ( !item
) // mouse on the spacing between items
684 QRect r
= item
->visibleRect();
685 int margin
= ThumbnailWidget::margin();
686 QPoint p
= e
->pos() - item
->pos();
688 if ( r
.contains( p
- QPoint( margin
/ 2, margin
/ 2 ) ) )
690 setCursor( Qt::OpenHandCursor
);
694 setCursor( Qt::ArrowCursor
);
695 if ( mouseGrabPos
.isNull() )
697 if ( m_document
->viewport().pageNumber
!= item
->pageNumber() )
698 m_document
->setViewportPage( item
->pageNumber() );
701 mouseGrabPos
.setX( 0 );
702 mouseGrabPos
.setY( 0 );
705 void ThumbnailListPrivate::mouseMoveEvent( QMouseEvent
* e
)
707 ThumbnailWidget
* item
= itemFor( e
->pos() );
708 if ( e
->buttons() == Qt::NoButton
)
711 ThumbnailWidget
* theItem
= item
? item
: mouseGrabItem
;
712 // no item under the mouse or previously selected
715 QRect r
= theItem
->rect();
716 int margin
= ThumbnailWidget::margin();
717 QPoint p
= e
->pos() - theItem
->pos();
719 if ( true /*r.contains( p - QPoint( margin / 2, margin / 2 ) )*/ )
721 if ( !mouseGrabPos
.isNull() )
723 setCursor( Qt::ClosedHandCursor
);
724 QPoint mousePos
= e
->pos();
725 QPoint delta
= mouseGrabPos
- mousePos
;
726 mouseGrabPos
= e
->pos();
728 mouseGrabItem
= item
;
729 // don't handle the mouse move, forward it to the thumbnail list
730 forwardTrack( mouseGrabItem
->page(), delta
, r
.size() );
734 mouseGrabPos
= QPoint();
736 setCursor( Qt::OpenHandCursor
);
741 setCursor( Qt::ArrowCursor
);
745 void ThumbnailListPrivate::wheelEvent( QWheelEvent
* e
)
747 ThumbnailWidget
* item
= itemFor( e
->pos() );
748 if ( !item
) // wheeling on the spacing between items
751 QRect r
= item
->visibleRect();
752 int margin
= ThumbnailWidget::margin();
754 if ( r
.contains( e
->pos() - QPoint( margin
/ 2, margin
/ 2 ) ) && e
->orientation() == Qt::Vertical
&& e
->modifiers() == Qt::ControlModifier
)
756 m_document
->setZoom( e
->delta() );
764 void ThumbnailListPrivate::contextMenuEvent( QContextMenuEvent
* e
)
766 ThumbnailWidget
* item
= itemFor( e
->pos() );
769 emit q
->rightClick( item
->page(), e
->globalPos() );
773 void ThumbnailWidget::paint( QPainter
&p
, const QRect
&_clipRect
)
775 int width
= m_pixmapWidth
+ m_margin
;
776 QRect clipRect
= _clipRect
;
777 QPalette pal
= m_parent
->palette();
779 // draw the bottom label + highlight mark
780 QColor fillColor
= m_selected
? pal
.color( QPalette::Active
, QPalette::Highlight
) : pal
.color( QPalette::Active
, QPalette::Base
);
781 p
.fillRect( clipRect
, fillColor
);
782 p
.setPen( m_selected
? pal
.color( QPalette::Active
, QPalette::HighlightedText
) : pal
.color( QPalette::Active
, QPalette::Text
) );
783 p
.drawText( 0, m_pixmapHeight
+ m_margin
, width
, m_labelHeight
, Qt::AlignCenter
, QString::number( m_labelNumber
) );
785 // draw page outline and pixmap
786 if ( clipRect
.top() < m_pixmapHeight
+ m_margin
)
788 // if page is bookmarked draw a colored border
789 bool isBookmarked
= m_parent
->m_document
->bookmarkManager()->isBookmarked( pageNumber() );
790 // draw the inner rect
791 p
.setPen( isBookmarked
? QColor( 0xFF8000 ) : Qt::black
);
792 p
.drawRect( m_margin
/2 - 1, m_margin
/2 - 1, m_pixmapWidth
+ 1, m_pixmapHeight
+ 1 );
793 // draw the clear rect
794 p
.setPen( isBookmarked
? QColor( 0x804000 ) : pal
.color( QPalette::Active
, QPalette::Base
) );
795 // draw the bottom and right shadow edges
798 int left
, right
, bottom
, top
;
799 left
= m_margin
/2 + 1;
800 right
= m_margin
/2 + m_pixmapWidth
+ 1;
801 bottom
= m_pixmapHeight
+ m_margin
/2 + 1;
802 top
= m_margin
/2 + 1;
803 p
.setPen( Qt::gray
);
804 p
.drawLine( left
, bottom
, right
, bottom
);
805 p
.drawLine( right
, top
, right
, bottom
);
808 // draw the page using the shared PagePainter class
809 p
.translate( m_margin
/2, m_margin
/2 );
810 clipRect
.translate( -m_margin
/2, -m_margin
/2 );
811 clipRect
= clipRect
.intersect( QRect( 0, 0, m_pixmapWidth
, m_pixmapHeight
) );
812 if ( clipRect
.isValid() )
814 int flags
= PagePainter::Accessibility
| PagePainter::Highlights
|
815 PagePainter::Annotations
;
816 PagePainter::paintPageOnPainter( &p
, m_page
, THUMBNAILS_ID
, flags
,
817 m_pixmapWidth
, m_pixmapHeight
, clipRect
);
820 if ( !m_visibleRect
.isNull() )
823 p
.setPen( QColor( 255, 255, 0, 200 ) );
824 p
.setBrush( QColor( 0, 0, 0, 100 ) );
825 p
.drawRect( m_visibleRect
.geometry( m_pixmapWidth
, m_pixmapHeight
).adjusted( 0, 0, -1, -1 ) );
829 // draw the bookmark overlay on the top-right corner
830 const QPixmap
* bookmarkPixmap
= m_parent
->getBookmarkOverlay();
831 if ( isBookmarked
&& bookmarkPixmap
)
833 int pixW
= bookmarkPixmap
->width(),
834 pixH
= bookmarkPixmap
->height();
835 clipRect
= clipRect
.intersect( QRect( m_pixmapWidth
- pixW
, 0, pixW
, pixH
) );
836 if ( clipRect
.isValid() )
837 p
.drawPixmap( m_pixmapWidth
- pixW
, -pixH
/8, *bookmarkPixmap
);
843 /** ThumbnailsController implementation **/
847 ThumbnailController::ThumbnailController( QWidget
* parent
, ThumbnailList
* list
)
850 setObjectName( "ThumbsControlBar" );
851 // change toolbar appearance
852 setIconSize( QSize( 16, 16 ) );
854 QSizePolicy sp
= sizePolicy();
855 sp
.setVerticalPolicy( QSizePolicy::Minimum
);
858 // insert a togglebutton [show only bookmarked pages]
860 QAction
* showBoomarkOnlyAction
= addAction(
861 KIcon( "bookmarks" ), i18n( "Show bookmarked pages only" ) );
862 showBoomarkOnlyAction
->setCheckable( true );
863 connect( showBoomarkOnlyAction
, SIGNAL( toggled( bool ) ), list
, SLOT( slotFilterBookmarks( bool ) ) );
864 showBoomarkOnlyAction
->setChecked( Okular::Settings::filterBookmarks() );
865 //insertLineSeparator();
869 #include "thumbnaillist.moc"