1 /***************************************************************************
2 * Copyright (C) 2005 by Enrico Ros <eros.kde@email.it> *
3 * Copyright (C) 2006 by Albert Astals Cid <aacid@kde.org> *
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 ***************************************************************************/
14 #include <qapplication.h>
17 #include <qpushbutton.h>
20 #include <QStyleOptionButton>
21 #include <QStylePainter>
22 #include <QtGui/QToolButton>
23 #include <qvalidator.h>
26 #include <kicontheme.h>
27 #include <klineedit.h>
29 #include <kacceleratormanager.h>
32 #include "core/document.h"
34 // [private widget] lineEdit for entering/validating page numbers
35 class PagesEdit
: public KLineEdit
38 PagesEdit( MiniBar
* parent
);
39 void setPagesNumber( int pages
);
40 void setText( const QString
& );
43 void focusInEvent( QFocusEvent
* e
);
44 void focusOutEvent( QFocusEvent
* e
);
45 void mousePressEvent( QMouseEvent
* e
);
46 void wheelEvent( QWheelEvent
* e
);
52 QIntValidator
* m_validator
;
55 // [private widget] a flat qpushbutton that enlights on hover
56 class HoverButton
: public QToolButton
59 HoverButton( QWidget
* parent
);
65 MiniBar::MiniBar( QWidget
* parent
, Okular::Document
* document
)
66 : QWidget( parent
), m_document( document
),
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
);
102 // resize width of widgets
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)
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
) )
128 // if document is closed or has no pages, hide widget
129 int pages
= pageVector
.count();
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() );
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
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()
191 void MiniBar::slotEmitPrevPage()
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 );
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 )
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
;
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 )
276 void ProgressWidget::paintEvent( QPaintEvent
* e
)
280 if ( m_progressPercentage
< 0.0 )
282 p
.fillRect( rect(), palette().color( QPalette::Active
, QPalette::HighlightedText
) );
286 // find out the 'fill' and the 'clear' rectangles
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();
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 );
301 if ( fRect
.isValid() )
302 p
.fillRect( fRect
, pal
.color( QPalette::Active
, QPalette::Highlight
) );
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
);
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
);
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
339 // call default handler if hasn't focus
341 KLineEdit::setText( text
);
344 void PagesEdit::focusInEvent( QFocusEvent
* e
)
348 if ( e
->reason() == Qt::MouseFocusReason
)
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
) );
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 ) );
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
374 KLineEdit::mousePressEvent( e
);
378 void PagesEdit::wheelEvent( QWheelEvent
* e
)
380 if ( e
->delta() > 0 )
381 m_miniBar
->slotEmitNextPage();
383 m_miniBar
->slotEmitPrevPage();
389 HoverButton::HoverButton( QWidget
* parent
)
390 : QToolButton( parent
)
393 setFocusPolicy(Qt::NoFocus
);
394 setToolButtonStyle(Qt::ToolButtonIconOnly
);
395 KAcceleratorManager::setNoAccel( this );
398 #include "minibar.moc"