source: vendor/trolltech/current/src/widgets/qstatusbar.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 13.0 KB
Line 
1/****************************************************************************
2** $Id: qstatusbar.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QStatusBar class
5**
6** Created : 980119
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the widgets module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qstatusbar.h"
39#ifndef QT_NO_STATUSBAR
40
41#include "qptrlist.h"
42#include "qlayout.h"
43#include "qpainter.h"
44#include "qtimer.h"
45#include "qdrawutil.h"
46#include "qstyle.h"
47#include "qsizegrip.h"
48
49/*!
50 \class QStatusBar qstatusbar.h
51 \brief The QStatusBar class provides a horizontal bar suitable for
52 presenting status information.
53
54 \ingroup application
55 \ingroup helpsystem
56 \mainclass
57
58 Each status indicator falls into one of three categories:
59
60 \list
61 \i \e Temporary - briefly occupies most of the status bar. Used
62 to explain tool tip texts or menu entries, for example.
63 \i \e Normal - occupies part of the status bar and may be hidden
64 by temporary messages. Used to display the page and line
65 number in a word processor, for example.
66 \i \e Permanent - is never hidden. Used for important mode
67 indications, for example, some applications put a Caps Lock
68 indicator in the status bar.
69 \endlist
70
71 QStatusBar lets you display all three types of indicators.
72
73 To display a \e temporary message, call message() (perhaps by
74 connecting a suitable signal to it). To remove a temporary
75 message, call clear(). There are two variants of message(): one
76 that displays the message until the next clear() or message() and
77 one that has a time limit:
78
79 \code
80 connect( loader, SIGNAL(progressMessage(const QString&)),
81 statusBar(), SLOT(message(const QString&)) );
82
83 statusBar()->message("Loading..."); // Initial message
84 loader.loadStuff(); // Emits progress messages
85 statusBar()->message("Done.", 2000); // Final message for 2 seconds
86 \endcode
87
88 \e Normal and \e Permanent messages are displayed by creating a
89 small widget and then adding it to the status bar with
90 addWidget(). Widgets like QLabel, QProgressBar or even QToolButton
91 are useful for adding to status bars. removeWidget() is used to
92 remove widgets.
93
94 \code
95 statusBar()->addWidget(new MyReadWriteIndication(statusBar()));
96 \endcode
97
98 By default QStatusBar provides a QSizeGrip in the lower-right
99 corner. You can disable it with setSizeGripEnabled(FALSE);
100
101 <img src=qstatusbar-m.png> <img src=qstatusbar-w.png>
102
103 \sa QToolBar QMainWindow QLabel
104 \link guibooks.html#fowler GUI Design Handbook: Status Bar.\endlink
105*/
106
107
108class QStatusBarPrivate
109{
110public:
111 QStatusBarPrivate() {}
112
113 struct SBItem {
114 SBItem( QWidget* widget, int stretch, bool permanent )
115 : s( stretch ), w( widget ), p( permanent ) {}
116 int s;
117 QWidget * w;
118 bool p;
119 };
120
121 QPtrList<SBItem> items;
122 QString tempItem;
123
124 QBoxLayout * box;
125 QTimer * timer;
126
127#ifndef QT_NO_SIZEGRIP
128 QSizeGrip * resizer;
129#endif
130
131 int savedStrut;
132};
133
134
135/*!
136 Constructs a status bar called \a name with parent \a parent and
137 with a size grip.
138
139 \sa setSizeGripEnabled()
140*/
141QStatusBar::QStatusBar( QWidget * parent, const char *name )
142 : QWidget( parent, name )
143{
144 d = new QStatusBarPrivate;
145 d->items.setAutoDelete( TRUE );
146 d->box = 0;
147 d->timer = 0;
148
149#ifndef QT_NO_SIZEGRIP
150 d->resizer = 0;
151 setSizeGripEnabled(TRUE); // causes reformat()
152#else
153 reformat();
154#endif
155}
156
157
158/*!
159 Destroys the status bar and frees any allocated resources and
160 child widgets.
161*/
162QStatusBar::~QStatusBar()
163{
164 delete d;
165 d = 0;
166}
167
168
169/*!
170 Adds \a widget to this status bar. \a widget is reparented if it
171 isn't already a child of the QStatusBar.
172
173 \a widget is permanently visible if \a permanent is TRUE and may
174 be obscured by temporary messages if \a permanent is FALSE. The
175 default is FALSE.
176
177 If \a permanent is TRUE, \a widget is located at the far right of
178 the status bar. If \a permanent is FALSE (the default), \a widget
179 is located just to the left of the first permanent widget.
180
181 \a stretch is used to compute a suitable size for \a widget as the
182 status bar grows and shrinks. The default of 0 uses a minimum of
183 space.
184
185 This function may cause some flicker.
186
187 \sa removeWidget()
188*/
189
190void QStatusBar::addWidget( QWidget * widget, int stretch, bool permanent )
191{
192 if ( !widget ) {
193#if defined(QT_CHECK_NULL)
194 qWarning( "QStatusBar::addWidget(): Cannot add null widget" );
195#endif
196 return;
197 }
198
199 if ( widget->parentWidget() != this )
200 widget->reparent( this, QPoint(0, 0), TRUE );
201
202 QStatusBarPrivate::SBItem* item
203 = new QStatusBarPrivate::SBItem( widget, stretch, permanent );
204
205 d->items.last();
206 while( !permanent && d->items.current() && d->items.current()->p )
207 d->items.prev();
208
209 d->items.insert( d->items.at() >= 0 ? d->items.at()+1 : 0, item );
210
211 if ( !d->tempItem.isEmpty() && !permanent )
212 widget->hide();
213
214 reformat();
215}
216
217
218/*!
219 Removes \a widget from the status bar.
220
221 This function may cause some flicker.
222
223 Note that \a widget is not deleted.
224
225 \sa addWidget()
226*/
227
228void QStatusBar::removeWidget( QWidget* widget )
229{
230 if ( !widget )
231 return;
232 bool found = FALSE;
233 QStatusBarPrivate::SBItem* item = d->items.first();
234 while ( item && !found ) {
235 if ( item->w == widget ) {
236 d->items.remove();
237 found = TRUE;
238 }
239 item = d->items.next();
240 }
241
242 if ( found )
243 reformat();
244#if defined(QT_DEBUG)
245 else
246 qDebug( "QStatusBar::removeWidget(): Widget not found." );
247#endif
248}
249
250/*!
251 \property QStatusBar::sizeGripEnabled
252 \brief whether the QSizeGrip in the bottom right of the status bar is enabled
253
254 Enables or disables the QSizeGrip in the bottom right of the
255 status bar. By default, the size grip is enabled.
256*/
257
258bool QStatusBar::isSizeGripEnabled() const
259{
260#ifdef QT_NO_SIZEGRIP
261 return FALSE;
262#else
263 return !!d->resizer;
264#endif
265}
266
267void QStatusBar::setSizeGripEnabled(bool enabled)
268{
269#ifndef QT_NO_SIZEGRIP
270 if ( !enabled != !d->resizer ) {
271 if ( enabled ) {
272 d->resizer = new QSizeGrip( this, "QStatusBar::resizer" );
273 } else {
274 delete d->resizer;
275 d->resizer = 0;
276 }
277 reformat();
278 if ( d->resizer && isVisible() )
279 d->resizer->show();
280 }
281#endif
282}
283
284
285/*!
286 Changes the status bar's appearance to account for item changes.
287 Special subclasses may need this, but geometry management will
288 usually take care of any necessary rearrangements.
289*/
290void QStatusBar::reformat()
291{
292 if ( d->box )
293 delete d->box;
294
295 QBoxLayout *vbox;
296 if ( isSizeGripEnabled() ) {
297 d->box = new QHBoxLayout( this );
298 vbox = new QVBoxLayout( d->box );
299 } else {
300 vbox = d->box = new QVBoxLayout( this );
301 }
302 vbox->addSpacing( 3 );
303 QBoxLayout* l = new QHBoxLayout( vbox );
304 l->addSpacing( 3 );
305 l->setSpacing( 4 );
306
307 int maxH = fontMetrics().height();
308
309 QStatusBarPrivate::SBItem* item = d->items.first();
310 while ( item && !item->p ) {
311 l->addWidget( item->w, item->s );
312 int itemH = QMIN(item->w->sizeHint().height(),
313 item->w->maximumHeight());
314 maxH = QMAX( maxH, itemH );
315 item = d->items.next();
316 }
317
318 l->addStretch( 0 );
319
320 while ( item ) {
321 l->addWidget( item->w, item->s );
322 int itemH = QMIN(item->w->sizeHint().height(),
323 item->w->maximumHeight());
324 maxH = QMAX( maxH, itemH );
325 item = d->items.next();
326 }
327 l->addSpacing( 4 );
328#ifndef QT_NO_SIZEGRIP
329 if ( d->resizer ) {
330 maxH = QMAX( maxH, d->resizer->sizeHint().height() );
331 d->box->addSpacing( 1 );
332 d->box->addWidget( d->resizer, 0, AlignBottom );
333 }
334#endif
335 l->addStrut( maxH );
336 d->savedStrut = maxH;
337 vbox->addSpacing( 2 );
338 d->box->activate();
339 repaint();
340}
341
342
343
344
345/*!
346 Hides the normal status indicators and displays \a message until
347 clear() or another message() is called.
348
349 \sa clear()
350*/
351void QStatusBar::message( const QString &message )
352{
353 if ( d->tempItem == message )
354 return;
355 d->tempItem = message;
356 if ( d->timer ) {
357 delete d->timer;
358 d->timer = 0;
359 }
360 hideOrShow();
361}
362
363
364/*!
365 \overload
366
367 Hides the normal status indications and displays \a message for \a
368 ms milli-seconds or until clear() or another message() is called,
369 whichever occurs first.
370*/
371void QStatusBar::message( const QString &message, int ms )
372{
373 d->tempItem = message;
374
375 if ( !d->timer ) {
376 d->timer = new QTimer( this );
377 connect( d->timer, SIGNAL(timeout()), this, SLOT(clear()) );
378 }
379 if ( ms > 0 ) {
380 d->timer->start( ms );
381 } else if ( d->timer ) {
382 delete d->timer;
383 d->timer = 0;
384 }
385
386 hideOrShow();
387}
388
389
390/*!
391 Removes any temporary message being shown.
392
393 \sa message()
394*/
395
396void QStatusBar::clear()
397{
398 if ( d->tempItem.isEmpty() )
399 return;
400 if ( d->timer ) {
401 delete d->timer;
402 d->timer = 0;
403 }
404 d->tempItem = QString::null;
405 hideOrShow();
406}
407
408/*!
409 \fn QStatusBar::messageChanged( const QString &message )
410
411 This signal is emitted when the temporary status messages
412 changes. \a message is the new temporary message, and is a
413 null-string when the message has been removed.
414
415 \sa message(), clear()
416*/
417
418/*!
419 Ensures that the right widgets are visible. Used by message() and
420 clear().
421*/
422void QStatusBar::hideOrShow()
423{
424 bool haveMessage = !d->tempItem.isEmpty();
425
426 QStatusBarPrivate::SBItem* item = d->items.first();
427
428 while( item && !item->p ) {
429 if ( haveMessage )
430 item->w->hide();
431 else
432 item->w->show();
433 item = d->items.next();
434 }
435
436 emit messageChanged( d->tempItem );
437 repaint();
438}
439
440
441/*!
442 Shows the temporary message, if appropriate.
443*/
444void QStatusBar::paintEvent( QPaintEvent * )
445{
446 bool haveMessage = !d->tempItem.isEmpty();
447
448 QPainter p( this );
449 QStatusBarPrivate::SBItem* item = d->items.first();
450
451#ifndef QT_NO_SIZEGRIP
452 int psx = ( d->resizer && d->resizer->isVisible() ) ? d->resizer->x() : width()-12;
453#else
454 int psx = width() - 12;
455#endif
456
457 while ( item ) {
458 if ( !haveMessage || item->p )
459 if ( item->w->isVisible() ) {
460 if ( item->p && item->w->x()-1 < psx )
461 psx = item->w->x()-1;
462 style().drawPrimitive( QStyle::PE_StatusBarSection, &p,
463 QRect(item->w->x() - 1, item->w->y() - 1,
464 item->w->width()+2, item->w->height()+2),
465 colorGroup(), QStyle::Style_Default,
466 QStyleOption(item->w) );
467 }
468 item = d->items.next();
469 }
470 if ( haveMessage ) {
471 p.setPen( colorGroup().foreground() );
472 p.drawText( 6, 0, psx, height(), AlignVCenter | SingleLine, d->tempItem );
473 }
474}
475
476/*!
477 \reimp
478*/
479void QStatusBar::resizeEvent( QResizeEvent * e )
480{
481 QWidget::resizeEvent( e );
482}
483
484/*!
485 \reimp
486*/
487
488bool QStatusBar::event( QEvent *e )
489{
490 if ( e->type() == QEvent::LayoutHint ) {
491 // Calculate new strut height and call reformat() if it has changed
492 int maxH = fontMetrics().height();
493
494 QStatusBarPrivate::SBItem* item = d->items.first();
495 while ( item ) {
496 int itemH = QMIN(item->w->sizeHint().height(),
497 item->w->maximumHeight());
498 maxH = QMAX( maxH, itemH );
499 item = d->items.next();
500 }
501
502#ifndef QT_NO_SIZEGRIP
503 if ( d->resizer )
504 maxH = QMAX( maxH, d->resizer->sizeHint().height() );
505#endif
506
507 if ( maxH != d->savedStrut )
508 reformat();
509 else
510 update();
511 }
512 if ( e->type() == QEvent::ChildRemoved ) {
513 QStatusBarPrivate::SBItem* item = d->items.first();
514 while ( item ) {
515 if ( item->w == ( (QChildEvent*)e )->child() )
516 d->items.removeRef( item );
517 item = d->items.next();
518 }
519 }
520 return QWidget::event( e );
521}
522
523#endif
Note: See TracBrowser for help on using the repository browser.