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
.constBegin(), tEnd
= m_thumbnails
.constEnd();
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
.constBegin(), tEnd
= m_thumbnails
.constEnd();
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();
220 prevPage
= d
->m_document
->viewport().pageNumber
;
222 // delete all the Thumbnails
223 QVector
<ThumbnailWidget
*>::const_iterator tIt
= d
->m_thumbnails
.constBegin(), tEnd
= d
->m_thumbnails
.constEnd();
224 for ( ; tIt
!= tEnd
; ++tIt
)
226 d
->m_thumbnails
.clear();
227 d
->m_visibleThumbnails
.clear();
229 d
->mouseGrabItem
= 0;
231 if ( pages
.count() < 1 )
233 widget()->resize( 0, 0 );
237 // show pages containing hilighted text or bookmarked ones
238 //RESTORE THIS int flags = Okular::Settings::filterBookmarks() ? Okular::Page::Bookmark : Okular::Page::Highlight;
240 // if no page matches filter rule, then display all pages
241 QVector
< Okular::Page
* >::const_iterator pIt
= pages
.constBegin(), pEnd
= pages
.constEnd();
242 bool skipCheck
= true;
243 for ( ; pIt
!= pEnd
; ++pIt
)
244 //if ( (*pIt)->attributes() & flags )
245 if ( (*pIt
)->hasHighlights( SW_SEARCH_ID
) )
248 // generate Thumbnails for the given set of pages
249 int width
= viewport()->width();
251 int centerHeight
= 0;
252 for ( pIt
= pages
.constBegin(); pIt
!= pEnd
; ++pIt
)
253 //if ( skipCheck || (*pIt)->attributes() & flags )
254 if ( skipCheck
|| (*pIt
)->hasHighlights( SW_SEARCH_ID
) )
256 ThumbnailWidget
* t
= new ThumbnailWidget( d
, *pIt
);
258 // add to the internal queue
259 d
->m_thumbnails
.push_back( t
);
260 // update total height (asking widget its own height)
261 t
->resizeFitWidth( width
);
262 // restoring the previous selected page, if any
263 if ( (*pIt
)->number() < prevPage
)
265 centerHeight
= height
+ t
->height() + KDialog::spacingHint()/2;
267 if ( (*pIt
)->number() == prevPage
)
270 d
->m_selected
->setSelected( true );
271 centerHeight
= height
+ t
->height() / 2;
273 height
+= t
->height() + KDialog::spacingHint();
276 // update scrollview's contents size (sets scrollbars limits)
277 height
-= KDialog::spacingHint();
278 widget()->resize( width
, height
);
280 // enable scrollbar when there's something to scroll
281 verticalScrollBar()->setEnabled( viewport()->height() < height
);
282 verticalScrollBar()->setValue(centerHeight
- viewport()->height() / 2);
284 // request for thumbnail generation
285 d
->delayedRequestVisiblePixmaps( 200 );
288 void ThumbnailList::notifyViewportChanged( bool /*smoothMove*/ )
290 // skip notifies for the current page (already selected)
291 int newPage
= d
->m_document
->viewport().pageNumber
;
292 if ( d
->m_selected
&& d
->m_selected
->pageNumber() == newPage
)
295 // deselect previous thumbnail
297 d
->m_selected
->setSelected( false );
300 // select the page with viewport and ensure it's centered in the view
301 d
->m_vectorIndex
= 0;
302 QVector
<ThumbnailWidget
*>::const_iterator tIt
= d
->m_thumbnails
.constBegin(), tEnd
= d
->m_thumbnails
.constEnd();
303 for ( ; tIt
!= tEnd
; ++tIt
)
305 if ( (*tIt
)->pageNumber() == newPage
)
307 d
->m_selected
= *tIt
;
308 d
->m_selected
->setSelected( true );
309 if ( Okular::Settings::syncThumbnailsViewport() )
311 int yOffset
= qMax( viewport()->height() / 4, d
->m_selected
->height() / 2 );
312 ensureVisible( 0, d
->m_selected
->pos().y() + d
->m_selected
->height()/2, 0, yOffset
);
320 void ThumbnailList::notifyPageChanged( int pageNumber
, int changedFlags
)
322 static int interestingFlags
= DocumentObserver::Pixmap
| DocumentObserver::Bookmark
| DocumentObserver::Highlights
| DocumentObserver::Annotations
;
323 // only handle change notifications we are interested in
324 if ( !( changedFlags
& interestingFlags
) )
327 // iterate over visible items: if page(pageNumber) is one of them, repaint it
328 QList
<ThumbnailWidget
*>::const_iterator vIt
= d
->m_visibleThumbnails
.constBegin(), vEnd
= d
->m_visibleThumbnails
.constEnd();
329 for ( ; vIt
!= vEnd
; ++vIt
)
330 if ( (*vIt
)->pageNumber() == pageNumber
)
337 void ThumbnailList::notifyContentsCleared( int changedFlags
)
339 // if pixmaps were cleared, re-ask them
340 if ( changedFlags
& DocumentObserver::Pixmap
)
341 d
->slotRequestVisiblePixmaps();
344 void ThumbnailList::notifyVisibleRectsChanged()
347 const QVector
<Okular::VisiblePageRect
*> & visibleRects
= d
->m_document
->visiblePageRects();
348 QVector
<ThumbnailWidget
*>::const_iterator tIt
= d
->m_thumbnails
.constBegin(), tEnd
= d
->m_thumbnails
.constEnd();
349 QVector
<Okular::VisiblePageRect
*>::const_iterator vEnd
= visibleRects
.end();
350 for ( ; tIt
!= tEnd
; ++tIt
)
353 QVector
<Okular::VisiblePageRect
*>::const_iterator vIt
= visibleRects
.begin();
354 for ( ; ( vIt
!= vEnd
) && !found
; ++vIt
)
356 if ( (*tIt
)->pageNumber() == (*vIt
)->pageNumber
)
358 (*tIt
)->setVisibleRect( (*vIt
)->rect
);
364 (*tIt
)->setVisibleRect( Okular::NormalizedRect() );
369 bool ThumbnailList::canUnloadPixmap( int pageNumber
) const
371 // if the thubnail 'pageNumber' is one of the visible ones, forbid unloading
372 QList
<ThumbnailWidget
*>::const_iterator vIt
= d
->m_visibleThumbnails
.constBegin(), vEnd
= d
->m_visibleThumbnails
.constEnd();
373 for ( ; vIt
!= vEnd
; ++vIt
)
374 if ( (*vIt
)->pageNumber() == pageNumber
)
376 // if hidden permit unloading
379 //END DocumentObserver inherited methods
382 void ThumbnailList::updateWidgets()
384 // find all widgets that intersects the viewport and update them
385 QRect viewportRect
= viewport()->rect().translated( viewport()->pos() );
386 QList
<ThumbnailWidget
*>::const_iterator vIt
= d
->m_visibleThumbnails
.constBegin(), vEnd
= d
->m_visibleThumbnails
.constEnd();
387 for ( ; vIt
!= vEnd
; ++vIt
)
389 ThumbnailWidget
* t
= *vIt
;
390 QRect thumbRect
= t
->rect().translated( widget()->mapToParent( t
->pos() ) );
391 // update only the exposed area of the widget (saves pixels..)
392 QRect relativeRect
= thumbRect
.intersect( viewport()->rect() );
393 if ( !relativeRect
.isValid() )
395 t
->update( relativeRect
);
399 void ThumbnailListPrivate::forwardTrack( const Okular::Page
* p
, const QPoint
&point
, const QSize
&s
)
401 Okular::DocumentViewport vp
=m_document
->viewport();
403 QVector
< Okular::VisiblePageRect
* > vVpr
= m_document
->visiblePageRects();
405 QVector
< Okular::VisiblePageRect
* >::const_iterator vIt
= vVpr
.constBegin();
406 QVector
< Okular::VisiblePageRect
* >::const_iterator vEnd
= vVpr
.constEnd();
407 for ( ; vIt
!= vEnd
; ++vIt
)
409 Okular::VisiblePageRect
*vpr
= ( *vIt
);
410 if( vpr
->pageNumber
== p
->number() )
412 double w
= vpr
->rect
.right
- vpr
->rect
.left
,
413 h
= vpr
->rect
.bottom
- vpr
->rect
.top
,
414 deltaX
= (double)point
.x() / s
.width(),
415 deltaY
= (double)point
.y() / s
.height();
417 vp
.rePos
.normalizedX
-= deltaX
;
418 vp
.rePos
.normalizedY
-= deltaY
;
420 if( !vp
.rePos
.enabled
)
422 vp
.rePos
.enabled
= true;
423 vp
.rePos
.normalizedY
+= h
/2;
425 m_document
->setViewport( vp
);
431 const QPixmap
* ThumbnailListPrivate::getBookmarkOverlay() const
433 return m_bookmarkOverlay
;
436 void ThumbnailList::slotFilterBookmarks( bool filterOn
)
439 Okular::Settings::setFilterBookmarks( filterOn
);
440 Okular::Settings::self()->writeConfig();
441 // ask for the 'notifySetup' with a little trick (on reinsertion the
442 // document sends the list again)
443 d
->m_document
->removeObserver( this );
444 d
->m_document
->addObserver( this );
448 //BEGIN widget events
449 void ThumbnailList::keyPressEvent( QKeyEvent
* keyEvent
)
451 if ( d
->m_thumbnails
.count() < 1 )
452 return keyEvent
->ignore();
455 if ( keyEvent
->key() == Qt::Key_Up
)
457 if ( !d
->m_selected
)
459 else if ( d
->m_vectorIndex
> 0 )
460 nextPage
= d
->m_thumbnails
[ d
->m_vectorIndex
- 1 ]->pageNumber();
462 else if ( keyEvent
->key() == Qt::Key_Down
)
464 if ( !d
->m_selected
)
466 else if ( d
->m_vectorIndex
< (int)d
->m_thumbnails
.count() - 1 )
467 nextPage
= d
->m_thumbnails
[ d
->m_vectorIndex
+ 1 ]->pageNumber();
469 else if ( keyEvent
->key() == Qt::Key_PageUp
)
470 verticalScrollBar()->triggerAction( QScrollBar::SliderPageStepSub
);
471 else if ( keyEvent
->key() == Qt::Key_PageDown
)
472 verticalScrollBar()->triggerAction( QScrollBar::SliderPageStepAdd
);
473 else if ( keyEvent
->key() == Qt::Key_Home
)
474 nextPage
= d
->m_thumbnails
[ 0 ]->pageNumber();
475 else if ( keyEvent
->key() == Qt::Key_End
)
476 nextPage
= d
->m_thumbnails
[ d
->m_thumbnails
.count() - 1 ]->pageNumber();
478 if ( nextPage
== -1 )
479 return keyEvent
->ignore();
483 d
->m_selected
->setSelected( false );
485 d
->m_document
->setViewportPage( nextPage
);
488 bool ThumbnailList::viewportEvent( QEvent
* e
)
494 d
->viewportResizeEvent( (QResizeEvent
*)e
);
500 return QScrollArea::viewportEvent( e
);
503 void ThumbnailListPrivate::viewportResizeEvent( QResizeEvent
* e
)
505 if ( m_thumbnails
.count() < 1 || width() < 1 )
508 // if width changed resize all the Thumbnails, reposition them to the
509 // right place and recalculate the contents area
510 if ( e
->size().width() != e
->oldSize().width() )
512 // runs the timer avoiding a thumbnail regeneration by 'contentsMoving'
513 delayedRequestVisiblePixmaps( 2000 );
515 // resize and reposition items
516 int newWidth
= q
->viewport()->width();
518 QVector
<ThumbnailWidget
*>::const_iterator tIt
= m_thumbnails
.constBegin(), tEnd
= m_thumbnails
.constEnd();
519 for ( ; tIt
!= tEnd
; ++tIt
)
521 ThumbnailWidget
*t
= *tIt
;
522 t
->move(0, newHeight
);
523 t
->resizeFitWidth( newWidth
);
524 newHeight
+= t
->height() + KDialog::spacingHint();
527 // update scrollview's contents size (sets scrollbars limits)
528 newHeight
-= KDialog::spacingHint();
529 const int oldHeight
= q
->widget()->height();
530 const int oldYCenter
= q
->verticalScrollBar()->value() + q
->viewport()->height() / 2;
531 q
->widget()->resize( newWidth
, newHeight
);
533 // enable scrollbar when there's something to scroll
534 q
->verticalScrollBar()->setEnabled( q
->viewport()->height() < newHeight
);
536 // ensure that what was visibile before remains visible now
537 q
->ensureVisible( 0, int( (qreal
)oldYCenter
* q
->widget()->height() / oldHeight
), 0, q
->viewport()->height() / 2 );
539 else if ( e
->size().height() <= e
->oldSize().height() )
542 // invalidate the bookmark overlay
543 if ( m_bookmarkOverlay
)
545 delete m_bookmarkOverlay
;
546 m_bookmarkOverlay
= 0;
549 // update Thumbnails since width has changed or height has increased
550 delayedRequestVisiblePixmaps( 500 );
553 void ThumbnailList::dragEnterEvent( QDragEnterEvent
* ev
)
558 void ThumbnailList::dropEvent( QDropEvent
* ev
)
560 if ( KUrl::List::canDecode( ev
->mimeData() ) )
561 emit
urlDropped( KUrl::List::fromMimeData( ev
->mimeData() ).first() );
565 //BEGIN internal SLOTS
566 void ThumbnailListPrivate::slotRequestVisiblePixmaps( int /*newContentsY*/ )
568 // if an update is already scheduled or the widget is hidden, don't proceed
569 if ( ( m_delayTimer
&& m_delayTimer
->isActive() ) || q
->isHidden() )
572 // scroll from the top to the last visible thumbnail
573 m_visibleThumbnails
.clear();
574 QLinkedList
< Okular::PixmapRequest
* > requestedPixmaps
;
575 QVector
<ThumbnailWidget
*>::const_iterator tIt
= m_thumbnails
.constBegin(), tEnd
= m_thumbnails
.constEnd();
576 QRect viewportRect
= q
->viewport()->rect().translated( q
->horizontalScrollBar()->value(), q
->verticalScrollBar()->value() );
577 for ( ; tIt
!= tEnd
; ++tIt
)
579 ThumbnailWidget
* t
= *tIt
;
580 QRect thumbRect
= t
->rect();
581 if ( !thumbRect
.intersects( viewportRect
) )
583 // add ThumbnailWidget to visible list
584 m_visibleThumbnails
.push_back( t
);
585 // if pixmap not present add it to requests
586 if ( !t
->page()->hasPixmap( THUMBNAILS_ID
, t
->pixmapWidth(), t
->pixmapHeight() ) )
588 Okular::PixmapRequest
* p
= new Okular::PixmapRequest(
589 THUMBNAILS_ID
, t
->pageNumber(), t
->pixmapWidth(), t
->pixmapHeight(), THUMBNAILS_PRIO
, true );
590 requestedPixmaps
.push_back( p
);
594 // actually request pixmaps
595 if ( !requestedPixmaps
.isEmpty() )
596 m_document
->requestPixmaps( requestedPixmaps
);
599 void ThumbnailListPrivate::slotDelayTimeout()
601 // resize the bookmark overlay
602 delete m_bookmarkOverlay
;
603 int expectedWidth
= q
->viewport()->width() / 4;
604 if ( expectedWidth
> 10 )
605 m_bookmarkOverlay
= new QPixmap( DesktopIcon( "bookmarks", expectedWidth
) );
607 m_bookmarkOverlay
= 0;
610 slotRequestVisiblePixmaps();
614 void ThumbnailListPrivate::delayedRequestVisiblePixmaps( int delayMs
)
618 m_delayTimer
= new QTimer( q
);
619 m_delayTimer
->setSingleShot( true );
620 connect( m_delayTimer
, SIGNAL( timeout() ), q
, SLOT( slotDelayTimeout() ) );
622 m_delayTimer
->start( delayMs
);
626 /** ThumbnailWidget implementation **/
628 ThumbnailWidget::ThumbnailWidget( ThumbnailListPrivate
* parent
, const Okular::Page
* kp
)
629 : m_parent( parent
), m_page( kp
),
630 m_selected( false ), m_pixmapWidth( 10 ), m_pixmapHeight( 10 )
632 m_labelNumber
= m_page
->number() + 1;
633 m_labelHeight
= QFontMetrics( m_parent
->font() ).height();
637 void ThumbnailWidget::resizeFitWidth( int width
)
639 m_pixmapWidth
= width
- m_margin
;
640 m_pixmapHeight
= qRound( m_page
->ratio() * (double)m_pixmapWidth
);
641 m_rect
.setSize( QSize( width
, heightHint() ) );
644 void ThumbnailWidget::setSelected( bool selected
)
646 // update selected state
647 if ( m_selected
!= selected
)
649 m_selected
= selected
;
654 void ThumbnailWidget::setVisibleRect( const Okular::NormalizedRect
& rect
)
656 if ( rect
== m_visibleRect
)
659 m_visibleRect
= rect
;
663 void ThumbnailListPrivate::mousePressEvent( QMouseEvent
* e
)
665 ThumbnailWidget
* item
= itemFor( e
->pos() );
666 if ( !item
) // mouse on the spacing between items
669 QRect r
= item
->visibleRect();
670 int margin
= ThumbnailWidget::margin();
671 QPoint p
= e
->pos() - item
->pos();
673 if ( e
->button() != Qt::RightButton
&& r
.contains( p
- QPoint( margin
/ 2, margin
/ 2 ) ) )
675 mouseGrabPos
= e
->pos();
676 mouseGrabItem
= item
;
680 mouseGrabPos
.setX( 0 );
681 mouseGrabPos
.setY( 0 );
686 void ThumbnailListPrivate::mouseReleaseEvent( QMouseEvent
* e
)
688 ThumbnailWidget
* item
= itemFor( e
->pos() );
689 mouseGrabItem
= item
;
690 if ( !item
) // mouse on the spacing between items
693 QRect r
= item
->visibleRect();
694 int margin
= ThumbnailWidget::margin();
695 QPoint p
= e
->pos() - item
->pos();
697 if ( r
.contains( p
- QPoint( margin
/ 2, margin
/ 2 ) ) )
699 setCursor( Qt::OpenHandCursor
);
703 setCursor( Qt::ArrowCursor
);
704 if ( mouseGrabPos
.isNull() )
706 if ( m_document
->viewport().pageNumber
!= item
->pageNumber() )
707 m_document
->setViewportPage( item
->pageNumber() );
710 mouseGrabPos
.setX( 0 );
711 mouseGrabPos
.setY( 0 );
714 void ThumbnailListPrivate::mouseMoveEvent( QMouseEvent
* e
)
716 ThumbnailWidget
* item
= itemFor( e
->pos() );
717 if ( e
->buttons() == Qt::NoButton
)
720 ThumbnailWidget
* theItem
= item
? item
: mouseGrabItem
;
721 // no item under the mouse or previously selected
724 QRect r
= theItem
->rect();
725 int margin
= ThumbnailWidget::margin();
726 QPoint p
= e
->pos() - theItem
->pos();
728 if ( true /*r.contains( p - QPoint( margin / 2, margin / 2 ) )*/ )
730 if ( !mouseGrabPos
.isNull() )
732 setCursor( Qt::ClosedHandCursor
);
733 QPoint mousePos
= e
->pos();
734 QPoint delta
= mouseGrabPos
- mousePos
;
735 mouseGrabPos
= e
->pos();
737 mouseGrabItem
= item
;
738 // don't handle the mouse move, forward it to the thumbnail list
739 forwardTrack( mouseGrabItem
->page(), delta
, r
.size() );
743 mouseGrabPos
= QPoint();
745 setCursor( Qt::OpenHandCursor
);
750 setCursor( Qt::ArrowCursor
);
754 void ThumbnailListPrivate::wheelEvent( QWheelEvent
* e
)
756 ThumbnailWidget
* item
= itemFor( e
->pos() );
757 if ( !item
) // wheeling on the spacing between items
760 QRect r
= item
->visibleRect();
761 int margin
= ThumbnailWidget::margin();
763 if ( r
.contains( e
->pos() - QPoint( margin
/ 2, margin
/ 2 ) ) && e
->orientation() == Qt::Vertical
&& e
->modifiers() == Qt::ControlModifier
)
765 m_document
->setZoom( e
->delta() );
773 void ThumbnailListPrivate::contextMenuEvent( QContextMenuEvent
* e
)
775 ThumbnailWidget
* item
= itemFor( e
->pos() );
778 emit q
->rightClick( item
->page(), e
->globalPos() );
782 void ThumbnailWidget::paint( QPainter
&p
, const QRect
&_clipRect
)
784 int width
= m_pixmapWidth
+ m_margin
;
785 QRect clipRect
= _clipRect
;
786 QPalette pal
= m_parent
->palette();
788 // draw the bottom label + highlight mark
789 QColor fillColor
= m_selected
? pal
.color( QPalette::Active
, QPalette::Highlight
) : pal
.color( QPalette::Active
, QPalette::Base
);
790 p
.fillRect( clipRect
, fillColor
);
791 p
.setPen( m_selected
? pal
.color( QPalette::Active
, QPalette::HighlightedText
) : pal
.color( QPalette::Active
, QPalette::Text
) );
792 p
.drawText( 0, m_pixmapHeight
+ m_margin
, width
, m_labelHeight
, Qt::AlignCenter
, QString::number( m_labelNumber
) );
794 // draw page outline and pixmap
795 if ( clipRect
.top() < m_pixmapHeight
+ m_margin
)
797 // if page is bookmarked draw a colored border
798 bool isBookmarked
= m_parent
->m_document
->bookmarkManager()->isBookmarked( pageNumber() );
799 // draw the inner rect
800 p
.setPen( isBookmarked
? QColor( 0xFF8000 ) : Qt::black
);
801 p
.drawRect( m_margin
/2 - 1, m_margin
/2 - 1, m_pixmapWidth
+ 1, m_pixmapHeight
+ 1 );
802 // draw the clear rect
803 p
.setPen( isBookmarked
? QColor( 0x804000 ) : pal
.color( QPalette::Active
, QPalette::Base
) );
804 // draw the bottom and right shadow edges
807 int left
, right
, bottom
, top
;
808 left
= m_margin
/2 + 1;
809 right
= m_margin
/2 + m_pixmapWidth
+ 1;
810 bottom
= m_pixmapHeight
+ m_margin
/2 + 1;
811 top
= m_margin
/2 + 1;
812 p
.setPen( Qt::gray
);
813 p
.drawLine( left
, bottom
, right
, bottom
);
814 p
.drawLine( right
, top
, right
, bottom
);
817 // draw the page using the shared PagePainter class
818 p
.translate( m_margin
/2, m_margin
/2 );
819 clipRect
.translate( -m_margin
/2, -m_margin
/2 );
820 clipRect
= clipRect
.intersect( QRect( 0, 0, m_pixmapWidth
, m_pixmapHeight
) );
821 if ( clipRect
.isValid() )
823 int flags
= PagePainter::Accessibility
| PagePainter::Highlights
|
824 PagePainter::Annotations
;
825 PagePainter::paintPageOnPainter( &p
, m_page
, THUMBNAILS_ID
, flags
,
826 m_pixmapWidth
, m_pixmapHeight
, clipRect
);
829 if ( !m_visibleRect
.isNull() )
832 p
.setPen( QColor( 255, 255, 0, 200 ) );
833 p
.setBrush( QColor( 0, 0, 0, 100 ) );
834 p
.drawRect( m_visibleRect
.geometry( m_pixmapWidth
, m_pixmapHeight
).adjusted( 0, 0, -1, -1 ) );
838 // draw the bookmark overlay on the top-right corner
839 const QPixmap
* bookmarkPixmap
= m_parent
->getBookmarkOverlay();
840 if ( isBookmarked
&& bookmarkPixmap
)
842 int pixW
= bookmarkPixmap
->width(),
843 pixH
= bookmarkPixmap
->height();
844 clipRect
= clipRect
.intersect( QRect( m_pixmapWidth
- pixW
, 0, pixW
, pixH
) );
845 if ( clipRect
.isValid() )
846 p
.drawPixmap( m_pixmapWidth
- pixW
, -pixH
/8, *bookmarkPixmap
);
852 /** ThumbnailsController implementation **/
856 ThumbnailController::ThumbnailController( QWidget
* parent
, ThumbnailList
* list
)
859 setObjectName( "ThumbsControlBar" );
860 // change toolbar appearance
861 setIconSize( QSize( 16, 16 ) );
863 QSizePolicy sp
= sizePolicy();
864 sp
.setVerticalPolicy( QSizePolicy::Minimum
);
867 // insert a togglebutton [show only bookmarked pages]
869 QAction
* showBoomarkOnlyAction
= addAction(
870 KIcon( "bookmarks" ), i18n( "Show bookmarked pages only" ) );
871 showBoomarkOnlyAction
->setCheckable( true );
872 connect( showBoomarkOnlyAction
, SIGNAL( toggled( bool ) ), list
, SLOT( slotFilterBookmarks( bool ) ) );
873 showBoomarkOnlyAction
->setChecked( Okular::Settings::filterBookmarks() );
874 //insertLineSeparator();
878 #include "thumbnaillist.moc"