add a small widget for showing an animation from the "animations" category of the...
[kdegraphics.git] / okular / ui / minibar.cpp
blob2445e5f7b6ebf194a1f24ec3637d1c39fd576182
1 /***************************************************************************
2 * Copyright (C) 2005 by Enrico Ros <eros.kde@email.it> *
3 * Copyright (C) 2006 by Albert Astals Cid <aacid@kde.org> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 ***************************************************************************/
11 #include "minibar.h"
13 // qt / kde includes
14 #include <qapplication.h>
15 #include <qevent.h>
16 #include <qframe.h>
17 #include <qpushbutton.h>
18 #include <qlabel.h>
19 #include <qlayout.h>
20 #include <QStyleOptionButton>
21 #include <QStylePainter>
22 #include <QtGui/QToolButton>
23 #include <qvalidator.h>
24 #include <qpainter.h>
25 #include <kicon.h>
26 #include <kicontheme.h>
27 #include <klineedit.h>
28 #include <klocale.h>
29 #include <kacceleratormanager.h>
31 // local includes
32 #include "core/document.h"
34 // [private widget] lineEdit for entering/validating page numbers
35 class PagesEdit : public KLineEdit
37 public:
38 PagesEdit( MiniBar * parent );
39 void setPagesNumber( int pages );
40 void setText( const QString & );
42 protected:
43 void focusInEvent( QFocusEvent * e );
44 void focusOutEvent( QFocusEvent * e );
45 void mousePressEvent( QMouseEvent * e );
46 void wheelEvent( QWheelEvent * e );
48 private:
49 MiniBar * m_miniBar;
50 bool m_eatClick;
51 QString backString;
52 QIntValidator * m_validator;
55 // [private widget] a flat qpushbutton that enlights on hover
56 class HoverButton : public QToolButton
58 public:
59 HoverButton( QWidget * parent );
63 /** MiniBar **/
65 MiniBar::MiniBar( QWidget * parent, Okular::Document * document )
66 : QWidget( parent ), m_document( document ),
67 m_currentPage( -1 )
69 setObjectName( "miniBar" );
71 QHBoxLayout * horLayout = new QHBoxLayout( this );
73 horLayout->setMargin( 0 );
74 horLayout->setSpacing( 3 );
76 QSize buttonSize( KIconLoader::SizeSmallMedium, KIconLoader::SizeSmallMedium );
77 // bottom: left prev_page button
78 m_prevButton = new HoverButton( this );
79 m_prevButton->setIcon( KIcon( layoutDirection() == Qt::RightToLeft ? "arrow-right" : "arrow-left" ) );
80 m_prevButton->setIconSize( buttonSize );
81 horLayout->addWidget( m_prevButton );
82 // bottom: left lineEdit (current page box)
83 m_pagesEdit = new PagesEdit( this );
84 horLayout->addWidget( m_pagesEdit );
85 // bottom: central 'of' label
86 horLayout->addSpacing(5);
87 horLayout->addWidget( new QLabel( i18nc( "Layouted like: '5 [pages] of 10'", "of" ), this ) );
88 // bottom: right button
89 m_pagesButton = new HoverButton( this );
90 horLayout->addWidget( m_pagesButton );
91 // bottom: right next_page button
92 m_nextButton = new HoverButton( this );
93 m_nextButton->setIcon( KIcon( layoutDirection() == Qt::RightToLeft ? "arrow-left" : "arrow-right" ) );
94 m_nextButton->setIconSize( buttonSize );
95 horLayout->addWidget( m_nextButton );
97 QSizePolicy sp = sizePolicy();
98 sp.setHorizontalPolicy( QSizePolicy::Fixed );
99 sp.setVerticalPolicy( QSizePolicy::Fixed );
100 setSizePolicy( sp );
102 // resize width of widgets
103 resizeForPage( 0 );
105 // connect signals from child widgets to internal handlers / signals bouncers
106 connect( m_pagesEdit, SIGNAL( returnPressed() ), this, SLOT( slotChangePage() ) );
107 connect( m_pagesButton, SIGNAL( clicked() ), this, SIGNAL( gotoPage() ) );
108 connect( m_prevButton, SIGNAL( clicked() ), this, SIGNAL( prevPage() ) );
109 connect( m_nextButton, SIGNAL( clicked() ), this, SIGNAL( nextPage() ) );
111 resize( minimumSizeHint() );
113 // widget starts disabled (will be enabled after opening a document)
114 setEnabled( false );
117 MiniBar::~MiniBar()
119 m_document->removeObserver( this );
122 void MiniBar::notifySetup( const QVector< Okular::Page * > & pageVector, int setupFlags )
124 // only process data when document changes
125 if ( !( setupFlags & Okular::DocumentObserver::DocumentChanged ) )
126 return;
128 // if document is closed or has no pages, hide widget
129 int pages = pageVector.count();
130 if ( pages < 1 )
132 m_currentPage = -1;
133 setEnabled( false );
134 return;
137 // resize width of widgets
138 resizeForPage( pages );
140 // update child widgets
141 m_pagesEdit->setPagesNumber( pages );
142 m_pagesButton->setText( QString::number( pages ) );
143 m_prevButton->setEnabled( false );
144 m_nextButton->setEnabled( false );
146 resize( minimumSizeHint() );
148 setEnabled( true );
151 void MiniBar::notifyViewportChanged( bool /*smoothMove*/ )
153 // get current page number
154 int page = m_document->viewport().pageNumber;
155 int pages = m_document->pages();
157 // if the document is opened and page is changed
158 if ( page != m_currentPage && pages > 0 )
160 m_currentPage = page;
161 // update prev/next button state
162 m_prevButton->setEnabled( page > 0 );
163 m_nextButton->setEnabled( page < ( pages - 1 ) );
164 // update text on widgets
165 m_pagesEdit->setText( QString::number( page + 1 ) );
169 void MiniBar::slotChangePage()
171 // get text from the lineEdit
172 QString pageNumber = m_pagesEdit->text();
174 // convert it to page number and go to that page
175 bool ok;
176 int number = pageNumber.toInt( &ok ) - 1;
177 if ( ok && number >= 0 && number < (int)m_document->pages() &&
178 number != m_currentPage )
180 m_document->setViewportPage( number );
181 m_pagesEdit->clearFocus();
185 void MiniBar::slotEmitNextPage()
187 // emit signal
188 nextPage();
191 void MiniBar::slotEmitPrevPage()
193 // emit signal
194 prevPage();
197 void MiniBar::resizeForPage( int pages )
199 int numberWidth = 10 + fontMetrics().width( QString::number( pages ) );
200 m_pagesEdit->setMinimumWidth( numberWidth );
201 m_pagesEdit->setMaximumWidth( 2 * numberWidth );
202 m_pagesButton->setMinimumWidth( numberWidth );
203 m_pagesButton->setMaximumWidth( 2 * numberWidth );
208 /** ProgressWidget **/
210 ProgressWidget::ProgressWidget( QWidget * parent, Okular::Document * document )
211 : QWidget( parent ), m_document( document ),
212 m_currentPage( -1 ), m_progressPercentage( -1 )
214 setObjectName( "progress" );
215 setAttribute( Qt::WA_OpaquePaintEvent, true );
216 setFixedHeight( 4 );
217 setMouseTracking( true );
220 ProgressWidget::~ProgressWidget()
222 m_document->removeObserver( this );
225 void ProgressWidget::notifyViewportChanged( bool /*smoothMove*/ )
227 // get current page number
228 int page = m_document->viewport().pageNumber;
229 int pages = m_document->pages();
231 // if the document is opened and page is changed
232 if ( page != m_currentPage && pages > 0 )
234 // update percentage
235 m_currentPage = page;
236 float percentage = pages < 2 ? 1.0 : (float)page / (float)(pages - 1);
237 setProgress( percentage );
241 void ProgressWidget::setProgress( float percentage )
243 m_progressPercentage = percentage;
244 update();
247 void ProgressWidget::slotGotoNormalizedPage( float index )
249 // figure out page number and go to that page
250 int number = (int)( index * (float)m_document->pages() );
251 if ( number >= 0 && number < (int)m_document->pages() &&
252 number != m_currentPage )
253 m_document->setViewportPage( number );
256 void ProgressWidget::mouseMoveEvent( QMouseEvent * e )
258 if ( ( QApplication::mouseButtons() & Qt::LeftButton ) && width() > 0 )
259 slotGotoNormalizedPage( (float)( QApplication::isRightToLeft() ? width() - e->x() : e->x() ) / (float)width() );
262 void ProgressWidget::mousePressEvent( QMouseEvent * e )
264 if ( e->button() == Qt::LeftButton && width() > 0 )
265 slotGotoNormalizedPage( (float)( QApplication::isRightToLeft() ? width() - e->x() : e->x() ) / (float)width() );
268 void ProgressWidget::wheelEvent( QWheelEvent * e )
270 if ( e->delta() > 0 )
271 emit nextPage();
272 else
273 emit prevPage();
276 void ProgressWidget::paintEvent( QPaintEvent * e )
278 QPainter p( this );
280 if ( m_progressPercentage < 0.0 )
282 p.fillRect( rect(), palette().color( QPalette::Active, QPalette::HighlightedText ) );
283 return;
286 // find out the 'fill' and the 'clear' rectangles
287 int w = width(),
288 h = height(),
289 l = (int)( (float)w * m_progressPercentage );
290 QRect cRect = ( QApplication::isRightToLeft() ? QRect( 0, 0, w - l, h ) : QRect( l, 0, w - l, h ) ).intersect( e->rect() );
291 QRect fRect = ( QApplication::isRightToLeft() ? QRect( w - l, 0, l, h ) : QRect( 0, 0, l, h ) ).intersect( e->rect() );
293 QPalette pal = palette();
294 // paint clear rect
295 if ( cRect.isValid() )
296 p.fillRect( cRect, pal.color( QPalette::Active, QPalette::HighlightedText ) );
297 // draw a frame-like outline
298 //p.setPen( palette().active().mid() );
299 //p.drawRect( 0,0, w, h );
300 // paint fill rect
301 if ( fRect.isValid() )
302 p.fillRect( fRect, pal.color( QPalette::Active, QPalette::Highlight ) );
303 if ( l && l != w )
305 p.setPen( pal.color( QPalette::Active, QPalette::Highlight ).dark( 120 ) );
306 int delta = QApplication::isRightToLeft() ? w - l : l;
307 p.drawLine( delta, 0, delta, h );
312 /** PagesEdit **/
314 PagesEdit::PagesEdit( MiniBar * parent )
315 : KLineEdit( parent ), m_miniBar( parent ), m_eatClick( false )
317 // use an integer validator
318 m_validator = new QIntValidator( 1, 1, this );
319 setValidator( m_validator );
321 // customize text properties
322 setAlignment( Qt::AlignCenter );
323 setMaxLength( 4 );
325 // send a focus out event
326 QFocusEvent fe( QEvent::FocusOut );
327 QApplication::sendEvent( this, &fe );
330 void PagesEdit::setPagesNumber( int pages )
332 m_validator->setTop( pages );
335 void PagesEdit::setText( const QString & text )
337 // store a copy of the string
338 backString = text;
339 // call default handler if hasn't focus
340 if ( !hasFocus() )
341 KLineEdit::setText( text );
344 void PagesEdit::focusInEvent( QFocusEvent * e )
346 // select all text
347 selectAll();
348 if ( e->reason() == Qt::MouseFocusReason )
349 m_eatClick = true;
350 // change background color to the default 'edit' color
351 QPalette pal = palette();
352 pal.setColor( QPalette::Active, QPalette::Base, QApplication::palette().color( QPalette::Active, QPalette::Base ) );
353 setPalette( pal );
354 // call default handler
355 KLineEdit::focusInEvent( e );
358 void PagesEdit::focusOutEvent( QFocusEvent * e )
360 // change background color to a dark tone
361 QPalette pal = palette();
362 pal.setColor( QPalette::Base, QApplication::palette().color( QPalette::Base ).dark( 102 ) );
363 setPalette( pal );
364 // restore text
365 KLineEdit::setText( backString );
366 // call default handler
367 KLineEdit::focusOutEvent( e );
370 void PagesEdit::mousePressEvent( QMouseEvent * e )
372 // if this click got the focus in, don't process the event
373 if ( !m_eatClick )
374 KLineEdit::mousePressEvent( e );
375 m_eatClick = false;
378 void PagesEdit::wheelEvent( QWheelEvent * e )
380 if ( e->delta() > 0 )
381 m_miniBar->slotEmitNextPage();
382 else
383 m_miniBar->slotEmitPrevPage();
387 /** HoverButton **/
389 HoverButton::HoverButton( QWidget * parent )
390 : QToolButton( parent )
392 setAutoRaise(true);
393 setFocusPolicy(Qt::NoFocus);
394 setToolButtonStyle(Qt::ToolButtonIconOnly);
395 KAcceleratorManager::setNoAccel( this );
398 #include "minibar.moc"