|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtGui module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qstatusbar.h" |
|
43 #ifndef QT_NO_STATUSBAR |
|
44 |
|
45 #include "qlist.h" |
|
46 #include "qdebug.h" |
|
47 #include "qevent.h" |
|
48 #include "qlayout.h" |
|
49 #include "qpainter.h" |
|
50 #include "qtimer.h" |
|
51 #include "qstyle.h" |
|
52 #include "qstyleoption.h" |
|
53 #include "qsizegrip.h" |
|
54 #include "qmainwindow.h" |
|
55 |
|
56 #include <private/qlayoutengine_p.h> |
|
57 #include <private/qwidget_p.h> |
|
58 |
|
59 QT_BEGIN_NAMESPACE |
|
60 |
|
61 class QStatusBarPrivate : public QWidgetPrivate |
|
62 { |
|
63 Q_DECLARE_PUBLIC(QStatusBar) |
|
64 public: |
|
65 QStatusBarPrivate() {} |
|
66 |
|
67 struct SBItem { |
|
68 SBItem(QWidget* widget, int stretch, bool permanent) |
|
69 : s(stretch), w(widget), p(permanent) {} |
|
70 int s; |
|
71 QWidget * w; |
|
72 bool p; |
|
73 }; |
|
74 |
|
75 QList<SBItem *> items; |
|
76 QString tempItem; |
|
77 |
|
78 QBoxLayout * box; |
|
79 QTimer * timer; |
|
80 |
|
81 #ifndef QT_NO_SIZEGRIP |
|
82 QSizeGrip * resizer; |
|
83 bool showSizeGrip; |
|
84 #endif |
|
85 |
|
86 int savedStrut; |
|
87 |
|
88 #ifdef Q_WS_MAC |
|
89 QPoint dragStart; |
|
90 #endif |
|
91 |
|
92 int indexToLastNonPermanentWidget() const |
|
93 { |
|
94 int i = items.size() - 1; |
|
95 for (; i >= 0; --i) { |
|
96 SBItem *item = items.at(i); |
|
97 if (!(item && item->p)) |
|
98 break; |
|
99 } |
|
100 return i; |
|
101 } |
|
102 |
|
103 #ifndef QT_NO_SIZEGRIP |
|
104 void tryToShowSizeGrip() |
|
105 { |
|
106 if (!showSizeGrip) |
|
107 return; |
|
108 showSizeGrip = false; |
|
109 if (!resizer || resizer->isVisible()) |
|
110 return; |
|
111 resizer->setAttribute(Qt::WA_WState_ExplicitShowHide, false); |
|
112 QMetaObject::invokeMethod(resizer, "_q_showIfNotHidden", Qt::DirectConnection); |
|
113 resizer->setAttribute(Qt::WA_WState_ExplicitShowHide, false); |
|
114 } |
|
115 #endif |
|
116 |
|
117 QRect messageRect() const; |
|
118 }; |
|
119 |
|
120 |
|
121 QRect QStatusBarPrivate::messageRect() const |
|
122 { |
|
123 Q_Q(const QStatusBar); |
|
124 bool rtl = q->layoutDirection() == Qt::RightToLeft; |
|
125 |
|
126 int left = 6; |
|
127 int right = q->width() - 12; |
|
128 |
|
129 #ifndef QT_NO_SIZEGRIP |
|
130 if (resizer && resizer->isVisible()) { |
|
131 if (rtl) |
|
132 left = resizer->x() + resizer->width(); |
|
133 else |
|
134 right = resizer->x(); |
|
135 } |
|
136 #endif |
|
137 |
|
138 for (int i=0; i<items.size(); ++i) { |
|
139 QStatusBarPrivate::SBItem* item = items.at(i); |
|
140 if (!item) |
|
141 break; |
|
142 if (item->p && item->w->isVisible()) { |
|
143 if (item->p) { |
|
144 if (rtl) |
|
145 left = qMax(left, item->w->x() + item->w->width() + 2); |
|
146 else |
|
147 right = qMin(right, item->w->x() - 2); |
|
148 } |
|
149 break; |
|
150 } |
|
151 } |
|
152 return QRect(left, 0, right-left, q->height()); |
|
153 } |
|
154 |
|
155 |
|
156 /*! |
|
157 \class QStatusBar |
|
158 \brief The QStatusBar class provides a horizontal bar suitable for |
|
159 presenting status information. |
|
160 |
|
161 \ingroup mainwindow-classes |
|
162 \ingroup helpsystem |
|
163 |
|
164 |
|
165 Each status indicator falls into one of three categories: |
|
166 |
|
167 \list |
|
168 \o \e Temporary - briefly occupies most of the status bar. Used |
|
169 to explain tool tip texts or menu entries, for example. |
|
170 \o \e Normal - occupies part of the status bar and may be hidden |
|
171 by temporary messages. Used to display the page and line |
|
172 number in a word processor, for example. |
|
173 \o \e Permanent - is never hidden. Used for important mode |
|
174 indications, for example, some applications put a Caps Lock |
|
175 indicator in the status bar. |
|
176 \endlist |
|
177 |
|
178 QStatusBar lets you display all three types of indicators. |
|
179 |
|
180 Typically, a request for the status bar functionality occurs in |
|
181 relation to a QMainWindow object. QMainWindow provides a main |
|
182 application window, with a menu bar, tool bars, dock widgets \e |
|
183 and a status bar around a large central widget. The status bar can |
|
184 be retrieved using the QMainWindow::statusBar() function, and |
|
185 replaced using the QMainWindow::setStatusBar() function. |
|
186 |
|
187 Use the showMessage() slot to display a \e temporary message: |
|
188 |
|
189 \snippet examples/mainwindows/dockwidgets/mainwindow.cpp 8 |
|
190 |
|
191 To remove a temporary message, use the clearMessage() slot, or set |
|
192 a time limit when calling showMessage(). For example: |
|
193 |
|
194 \snippet examples/mainwindows/dockwidgets/mainwindow.cpp 3 |
|
195 |
|
196 Use the currentMessage() function to retrieve the temporary |
|
197 message currently shown. The QStatusBar class also provide the |
|
198 messageChanged() signal which is emitted whenever the temporary |
|
199 status message changes. |
|
200 |
|
201 \target permanent message |
|
202 \e Normal and \e Permanent messages are displayed by creating a |
|
203 small widget (QLabel, QProgressBar or even QToolButton) and then |
|
204 adding it to the status bar using the addWidget() or the |
|
205 addPermanentWidget() function. Use the removeWidget() function to |
|
206 remove such messages from the status bar. |
|
207 |
|
208 \snippet doc/src/snippets/code/src_gui_widgets_qstatusbar.cpp 0 |
|
209 |
|
210 By default QStatusBar provides a QSizeGrip in the lower-right |
|
211 corner. You can disable it using the setSizeGripEnabled() |
|
212 function. Use the isSizeGripEnabled() function to determine the |
|
213 current status of the size grip. |
|
214 |
|
215 \image plastique-statusbar.png A status bar shown in the Plastique widget style |
|
216 |
|
217 \sa QMainWindow, QStatusTipEvent, {fowler}{GUI Design Handbook: |
|
218 Status Bar}, {Application Example} |
|
219 */ |
|
220 |
|
221 #ifdef QT3_SUPPORT |
|
222 /*! |
|
223 Constructs a status bar with a size grip and the given \a parent |
|
224 and object \a name. |
|
225 |
|
226 Use the QStatusBar() constructor and the QObject::setObjectName() |
|
227 function instead. |
|
228 |
|
229 \oldcode |
|
230 QStatusBar *myStatusBar = new QStatusBar(parent, name); |
|
231 \newcode |
|
232 QStatusBar *myStatusBar = new QStatusBar(parent); |
|
233 myStatusBar->setObjectName(name); |
|
234 \endcode |
|
235 */ |
|
236 QStatusBar::QStatusBar(QWidget * parent, const char *name) |
|
237 : QWidget(*new QStatusBarPrivate, parent, 0) |
|
238 { |
|
239 Q_D(QStatusBar); |
|
240 setObjectName(QString::fromAscii(name)); |
|
241 d->box = 0; |
|
242 d->timer = 0; |
|
243 |
|
244 #ifndef QT_NO_SIZEGRIP |
|
245 d->resizer = 0; |
|
246 d->showSizeGrip = false; |
|
247 setSizeGripEnabled(true); // causes reformat() |
|
248 #else |
|
249 reformat(); |
|
250 #endif |
|
251 } |
|
252 |
|
253 |
|
254 /*! |
|
255 \fn void QStatusBar::addWidget(QWidget * widget, int stretch, bool permanent) |
|
256 |
|
257 Use addWidget() or addPermanentWidget() instead, depending on the |
|
258 value of the \a permanent parameter. |
|
259 |
|
260 \oldcode |
|
261 QStatusBar *myStatusBar; |
|
262 myStatusBar->addWidget(widget, stretch, permanent); // permanent == true |
|
263 \newcode |
|
264 QStatusBar *myStatusBar; |
|
265 myStatusBar->addPermanentWidget(widget, stretch); |
|
266 \endcode |
|
267 */ |
|
268 |
|
269 #endif |
|
270 |
|
271 /*! |
|
272 Constructs a status bar with a size grip and the given \a parent. |
|
273 |
|
274 \sa setSizeGripEnabled() |
|
275 */ |
|
276 QStatusBar::QStatusBar(QWidget * parent) |
|
277 : QWidget(*new QStatusBarPrivate, parent, 0) |
|
278 { |
|
279 Q_D(QStatusBar); |
|
280 d->box = 0; |
|
281 d->timer = 0; |
|
282 |
|
283 #ifndef QT_NO_SIZEGRIP |
|
284 d->resizer = 0; |
|
285 setSizeGripEnabled(true); // causes reformat() |
|
286 #else |
|
287 reformat(); |
|
288 #endif |
|
289 } |
|
290 |
|
291 /*! |
|
292 Destroys this status bar and frees any allocated resources and |
|
293 child widgets. |
|
294 */ |
|
295 QStatusBar::~QStatusBar() |
|
296 { |
|
297 Q_D(QStatusBar); |
|
298 while (!d->items.isEmpty()) |
|
299 delete d->items.takeFirst(); |
|
300 } |
|
301 |
|
302 |
|
303 /*! |
|
304 Adds the given \a widget to this status bar, reparenting the |
|
305 widget if it isn't already a child of this QStatusBar object. The |
|
306 \a stretch parameter is used to compute a suitable size for the |
|
307 given \a widget as the status bar grows and shrinks. The default |
|
308 stretch factor is 0, i.e giving the widget a minimum of space. |
|
309 |
|
310 The widget is located to the far left of the first permanent |
|
311 widget (see addPermanentWidget()) and may be obscured by temporary |
|
312 messages. |
|
313 |
|
314 \sa insertWidget(), removeWidget(), addPermanentWidget() |
|
315 */ |
|
316 |
|
317 void QStatusBar::addWidget(QWidget * widget, int stretch) |
|
318 { |
|
319 if (!widget) |
|
320 return; |
|
321 insertWidget(d_func()->indexToLastNonPermanentWidget() + 1, widget, stretch); |
|
322 } |
|
323 |
|
324 /*! |
|
325 \since 4.2 |
|
326 |
|
327 Inserts the given \a widget at the given \a index to this status bar, |
|
328 reparenting the widget if it isn't already a child of this |
|
329 QStatusBar object. If \a index is out of range, the widget is appended |
|
330 (in which case it is the actual index of the widget that is returned). |
|
331 |
|
332 The \a stretch parameter is used to compute a suitable size for |
|
333 the given \a widget as the status bar grows and shrinks. The |
|
334 default stretch factor is 0, i.e giving the widget a minimum of |
|
335 space. |
|
336 |
|
337 The widget is located to the far left of the first permanent |
|
338 widget (see addPermanentWidget()) and may be obscured by temporary |
|
339 messages. |
|
340 |
|
341 \sa addWidget(), removeWidget(), addPermanentWidget() |
|
342 */ |
|
343 int QStatusBar::insertWidget(int index, QWidget *widget, int stretch) |
|
344 { |
|
345 if (!widget) |
|
346 return -1; |
|
347 |
|
348 Q_D(QStatusBar); |
|
349 QStatusBarPrivate::SBItem* item = new QStatusBarPrivate::SBItem(widget, stretch, false); |
|
350 |
|
351 int idx = d->indexToLastNonPermanentWidget(); |
|
352 if (index < 0 || index > d->items.size() || (idx >= 0 && index > idx + 1)) { |
|
353 qWarning("QStatusBar::insertWidget: Index out of range (%d), appending widget", index); |
|
354 index = idx + 1; |
|
355 } |
|
356 d->items.insert(index, item); |
|
357 |
|
358 if (!d->tempItem.isEmpty()) |
|
359 widget->hide(); |
|
360 |
|
361 reformat(); |
|
362 if (!widget->isHidden() || !widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) |
|
363 widget->show(); |
|
364 |
|
365 return index; |
|
366 } |
|
367 |
|
368 /*! |
|
369 Adds the given \a widget permanently to this status bar, |
|
370 reparenting the widget if it isn't already a child of this |
|
371 QStatusBar object. The \a stretch parameter is used to compute a |
|
372 suitable size for the given \a widget as the status bar grows and |
|
373 shrinks. The default stretch factor is 0, i.e giving the widget a |
|
374 minimum of space. |
|
375 |
|
376 Permanently means that the widget may not be obscured by temporary |
|
377 messages. It is is located at the far right of the status bar. |
|
378 |
|
379 \sa insertPermanentWidget(), removeWidget(), addWidget() |
|
380 */ |
|
381 |
|
382 void QStatusBar::addPermanentWidget(QWidget * widget, int stretch) |
|
383 { |
|
384 if (!widget) |
|
385 return; |
|
386 insertPermanentWidget(d_func()->items.size(), widget, stretch); |
|
387 } |
|
388 |
|
389 |
|
390 /*! |
|
391 \since 4.2 |
|
392 |
|
393 Inserts the given \a widget at the given \a index permanently to this status bar, |
|
394 reparenting the widget if it isn't already a child of this |
|
395 QStatusBar object. If \a index is out of range, the widget is appended |
|
396 (in which case it is the actual index of the widget that is returned). |
|
397 |
|
398 The \a stretch parameter is used to compute a |
|
399 suitable size for the given \a widget as the status bar grows and |
|
400 shrinks. The default stretch factor is 0, i.e giving the widget a |
|
401 minimum of space. |
|
402 |
|
403 Permanently means that the widget may not be obscured by temporary |
|
404 messages. It is is located at the far right of the status bar. |
|
405 |
|
406 \sa addPermanentWidget(), removeWidget(), addWidget() |
|
407 */ |
|
408 int QStatusBar::insertPermanentWidget(int index, QWidget *widget, int stretch) |
|
409 { |
|
410 if (!widget) |
|
411 return -1; |
|
412 |
|
413 Q_D(QStatusBar); |
|
414 QStatusBarPrivate::SBItem* item = new QStatusBarPrivate::SBItem(widget, stretch, true); |
|
415 |
|
416 int idx = d->indexToLastNonPermanentWidget(); |
|
417 if (index < 0 || index > d->items.size() || (idx >= 0 && index <= idx)) { |
|
418 qWarning("QStatusBar::insertPermanentWidget: Index out of range (%d), appending widget", index); |
|
419 index = d->items.size(); |
|
420 } |
|
421 d->items.insert(index, item); |
|
422 |
|
423 reformat(); |
|
424 if (!widget->isHidden() || !widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) |
|
425 widget->show(); |
|
426 |
|
427 return index; |
|
428 } |
|
429 |
|
430 /*! |
|
431 Removes the specified \a widget from the status bar. |
|
432 |
|
433 \note This function does not delete the widget but \e hides it. |
|
434 To add the widget again, you must call both the addWidget() and |
|
435 show() functions. |
|
436 |
|
437 \sa addWidget(), addPermanentWidget(), clearMessage() |
|
438 */ |
|
439 |
|
440 void QStatusBar::removeWidget(QWidget *widget) |
|
441 { |
|
442 if (!widget) |
|
443 return; |
|
444 |
|
445 Q_D(QStatusBar); |
|
446 bool found = false; |
|
447 QStatusBarPrivate::SBItem* item; |
|
448 for (int i=0; i<d->items.size(); ++i) { |
|
449 item = d->items.at(i); |
|
450 if (!item) |
|
451 break; |
|
452 if (item->w == widget) { |
|
453 d->items.removeAt(i); |
|
454 item->w->hide(); |
|
455 delete item; |
|
456 found = true; |
|
457 break; |
|
458 } |
|
459 } |
|
460 |
|
461 if (found) |
|
462 reformat(); |
|
463 #if defined(QT_DEBUG) |
|
464 else |
|
465 qDebug("QStatusBar::removeWidget(): Widget not found."); |
|
466 #endif |
|
467 } |
|
468 |
|
469 /*! |
|
470 \property QStatusBar::sizeGripEnabled |
|
471 |
|
472 \brief whether the QSizeGrip in the bottom-right corner of the |
|
473 status bar is enabled |
|
474 |
|
475 The size grip is enabled by default. |
|
476 */ |
|
477 |
|
478 bool QStatusBar::isSizeGripEnabled() const |
|
479 { |
|
480 #ifdef QT_NO_SIZEGRIP |
|
481 return false; |
|
482 #else |
|
483 Q_D(const QStatusBar); |
|
484 return !!d->resizer; |
|
485 #endif |
|
486 } |
|
487 |
|
488 void QStatusBar::setSizeGripEnabled(bool enabled) |
|
489 { |
|
490 #ifdef QT_NO_SIZEGRIP |
|
491 Q_UNUSED(enabled); |
|
492 #else |
|
493 Q_D(QStatusBar); |
|
494 if (!enabled != !d->resizer) { |
|
495 if (enabled) { |
|
496 d->resizer = new QSizeGrip(this); |
|
497 d->resizer->hide(); |
|
498 d->resizer->installEventFilter(this); |
|
499 d->showSizeGrip = true; |
|
500 } else { |
|
501 delete d->resizer; |
|
502 d->resizer = 0; |
|
503 d->showSizeGrip = false; |
|
504 } |
|
505 reformat(); |
|
506 if (d->resizer && isVisible()) |
|
507 d->tryToShowSizeGrip(); |
|
508 } |
|
509 #endif |
|
510 } |
|
511 |
|
512 |
|
513 /*! |
|
514 Changes the status bar's appearance to account for item changes. |
|
515 |
|
516 Special subclasses may need this function, but geometry management |
|
517 will usually take care of any necessary rearrangements. |
|
518 */ |
|
519 void QStatusBar::reformat() |
|
520 { |
|
521 Q_D(QStatusBar); |
|
522 if (d->box) |
|
523 delete d->box; |
|
524 |
|
525 QBoxLayout *vbox; |
|
526 #ifndef QT_NO_SIZEGRIP |
|
527 if (d->resizer) { |
|
528 d->box = new QHBoxLayout(this); |
|
529 d->box->setMargin(0); |
|
530 vbox = new QVBoxLayout; |
|
531 d->box->addLayout(vbox); |
|
532 } else |
|
533 #endif |
|
534 { |
|
535 vbox = d->box = new QVBoxLayout(this); |
|
536 d->box->setMargin(0); |
|
537 } |
|
538 vbox->addSpacing(3); |
|
539 QBoxLayout* l = new QHBoxLayout; |
|
540 vbox->addLayout(l); |
|
541 l->addSpacing(2); |
|
542 l->setSpacing(6); |
|
543 |
|
544 int maxH = fontMetrics().height(); |
|
545 |
|
546 int i; |
|
547 QStatusBarPrivate::SBItem* item; |
|
548 for (i=0,item=0; i<d->items.size(); ++i) { |
|
549 item = d->items.at(i); |
|
550 if (!item || item->p) |
|
551 break; |
|
552 l->addWidget(item->w, item->s); |
|
553 int itemH = qMin(qSmartMinSize(item->w).height(), item->w->maximumHeight()); |
|
554 maxH = qMax(maxH, itemH); |
|
555 } |
|
556 |
|
557 l->addStretch(0); |
|
558 |
|
559 for (item=0; i<d->items.size(); ++i) { |
|
560 item = d->items.at(i); |
|
561 if (!item) |
|
562 break; |
|
563 l->addWidget(item->w, item->s); |
|
564 int itemH = qMin(qSmartMinSize(item->w).height(), item->w->maximumHeight()); |
|
565 maxH = qMax(maxH, itemH); |
|
566 } |
|
567 #ifndef QT_NO_SIZEGRIP |
|
568 if (d->resizer) { |
|
569 maxH = qMax(maxH, d->resizer->sizeHint().height()); |
|
570 d->box->addSpacing(1); |
|
571 d->box->addWidget(d->resizer, 0, Qt::AlignBottom); |
|
572 } |
|
573 #endif |
|
574 l->addStrut(maxH); |
|
575 d->savedStrut = maxH; |
|
576 vbox->addSpacing(2); |
|
577 d->box->activate(); |
|
578 repaint(); |
|
579 } |
|
580 |
|
581 /*! |
|
582 |
|
583 Hides the normal status indications and displays the given \a |
|
584 message for the specified number of milli-seconds (\a{timeout}). If |
|
585 \a{timeout} is 0 (default), the \a {message} remains displayed until |
|
586 the clearMessage() slot is called or until the showMessage() slot is |
|
587 called again to change the message. |
|
588 |
|
589 Note that showMessage() is called to show temporary explanations of |
|
590 tool tip texts, so passing a \a{timeout} of 0 is not sufficient to |
|
591 display a \l{permanent message}{permanent message}. |
|
592 |
|
593 \sa messageChanged(), currentMessage(), clearMessage() |
|
594 */ |
|
595 void QStatusBar::showMessage(const QString &message, int timeout) |
|
596 { |
|
597 Q_D(QStatusBar); |
|
598 if (d->tempItem == message) |
|
599 return; |
|
600 |
|
601 d->tempItem = message; |
|
602 |
|
603 if (timeout > 0) { |
|
604 if (!d->timer) { |
|
605 d->timer = new QTimer(this); |
|
606 connect(d->timer, SIGNAL(timeout()), this, SLOT(clearMessage())); |
|
607 } |
|
608 d->timer->start(timeout); |
|
609 } else if (d->timer) { |
|
610 delete d->timer; |
|
611 d->timer = 0; |
|
612 } |
|
613 |
|
614 hideOrShow(); |
|
615 } |
|
616 |
|
617 /*! |
|
618 Removes any temporary message being shown. |
|
619 |
|
620 \sa currentMessage(), showMessage(), removeWidget() |
|
621 */ |
|
622 |
|
623 void QStatusBar::clearMessage() |
|
624 { |
|
625 Q_D(QStatusBar); |
|
626 if (d->tempItem.isEmpty()) |
|
627 return; |
|
628 if (d->timer) { |
|
629 qDeleteInEventHandler(d->timer); |
|
630 d->timer = 0; |
|
631 } |
|
632 d->tempItem.clear(); |
|
633 hideOrShow(); |
|
634 } |
|
635 |
|
636 /*! |
|
637 Returns the temporary message currently shown, |
|
638 or an empty string if there is no such message. |
|
639 |
|
640 \sa showMessage() |
|
641 */ |
|
642 QString QStatusBar::currentMessage() const |
|
643 { |
|
644 Q_D(const QStatusBar); |
|
645 return d->tempItem; |
|
646 } |
|
647 |
|
648 /*! |
|
649 \fn void QStatusBar::message(const QString &message, int timeout) |
|
650 |
|
651 Use the showMessage() function instead. |
|
652 */ |
|
653 |
|
654 /*! |
|
655 \fn void QStatusBar::clear() |
|
656 |
|
657 Use the clearMessage() function instead. |
|
658 */ |
|
659 |
|
660 /*! |
|
661 \fn QStatusBar::messageChanged(const QString &message) |
|
662 |
|
663 This signal is emitted whenever the temporary status message |
|
664 changes. The new temporary message is passed in the \a message |
|
665 parameter which is a null-string when the message has been |
|
666 removed. |
|
667 |
|
668 \sa showMessage(), clearMessage() |
|
669 */ |
|
670 |
|
671 /*! |
|
672 Ensures that the right widgets are visible. |
|
673 |
|
674 Used by the showMessage() and clearMessage() functions. |
|
675 */ |
|
676 void QStatusBar::hideOrShow() |
|
677 { |
|
678 Q_D(QStatusBar); |
|
679 bool haveMessage = !d->tempItem.isEmpty(); |
|
680 |
|
681 QStatusBarPrivate::SBItem* item = 0; |
|
682 for (int i=0; i<d->items.size(); ++i) { |
|
683 item = d->items.at(i); |
|
684 if (!item || item->p) |
|
685 break; |
|
686 if (haveMessage && item->w->isVisible()) { |
|
687 item->w->hide(); |
|
688 item->w->setAttribute(Qt::WA_WState_ExplicitShowHide, false); |
|
689 } else if (!haveMessage && !item->w->testAttribute(Qt::WA_WState_ExplicitShowHide)) { |
|
690 item->w->show(); |
|
691 } |
|
692 } |
|
693 |
|
694 emit messageChanged(d->tempItem); |
|
695 repaint(d->messageRect()); |
|
696 } |
|
697 |
|
698 /*! |
|
699 \reimp |
|
700 */ |
|
701 void QStatusBar::showEvent(QShowEvent *) |
|
702 { |
|
703 #ifndef QT_NO_SIZEGRIP |
|
704 Q_D(QStatusBar); |
|
705 if (d->resizer && d->showSizeGrip) |
|
706 d->tryToShowSizeGrip(); |
|
707 #endif |
|
708 } |
|
709 |
|
710 /*! |
|
711 \reimp |
|
712 \fn void QStatusBar::paintEvent(QPaintEvent *event) |
|
713 |
|
714 Shows the temporary message, if appropriate, in response to the |
|
715 paint \a event. |
|
716 */ |
|
717 void QStatusBar::paintEvent(QPaintEvent *event) |
|
718 { |
|
719 Q_D(QStatusBar); |
|
720 bool haveMessage = !d->tempItem.isEmpty(); |
|
721 |
|
722 QPainter p(this); |
|
723 QStyleOption opt; |
|
724 opt.initFrom(this); |
|
725 style()->drawPrimitive(QStyle::PE_PanelStatusBar, &opt, &p, this); |
|
726 |
|
727 for (int i=0; i<d->items.size(); ++i) { |
|
728 QStatusBarPrivate::SBItem* item = d->items.at(i); |
|
729 if (item && item->w->isVisible() && (!haveMessage || item->p)) { |
|
730 QRect ir = item->w->geometry().adjusted(-2, -1, 2, 1); |
|
731 if (event->rect().intersects(ir)) { |
|
732 QStyleOption opt(0); |
|
733 opt.rect = ir; |
|
734 opt.palette = palette(); |
|
735 opt.state = QStyle::State_None; |
|
736 style()->drawPrimitive(QStyle::PE_FrameStatusBarItem, &opt, &p, item->w); |
|
737 } |
|
738 } |
|
739 } |
|
740 if (haveMessage) { |
|
741 p.setPen(palette().foreground().color()); |
|
742 p.drawText(d->messageRect(), Qt::AlignLeading | Qt::AlignVCenter | Qt::TextSingleLine, d->tempItem); |
|
743 } |
|
744 } |
|
745 |
|
746 /*! |
|
747 \reimp |
|
748 */ |
|
749 void QStatusBar::resizeEvent(QResizeEvent * e) |
|
750 { |
|
751 QWidget::resizeEvent(e); |
|
752 } |
|
753 |
|
754 /*! |
|
755 \reimp |
|
756 */ |
|
757 |
|
758 bool QStatusBar::event(QEvent *e) |
|
759 { |
|
760 Q_D(QStatusBar); |
|
761 |
|
762 if (e->type() == QEvent::LayoutRequest |
|
763 #ifdef QT3_SUPPORT |
|
764 || e->type() == QEvent::LayoutHint |
|
765 #endif |
|
766 ) { |
|
767 // Calculate new strut height and call reformat() if it has changed |
|
768 int maxH = fontMetrics().height(); |
|
769 |
|
770 QStatusBarPrivate::SBItem* item = 0; |
|
771 for (int i=0; i<d->items.size(); ++i) { |
|
772 item = d->items.at(i); |
|
773 if (!item) |
|
774 break; |
|
775 int itemH = qMin(qSmartMinSize(item->w).height(), item->w->maximumHeight()); |
|
776 maxH = qMax(maxH, itemH); |
|
777 } |
|
778 |
|
779 #ifndef QT_NO_SIZEGRIP |
|
780 if (d->resizer) |
|
781 maxH = qMax(maxH, d->resizer->sizeHint().height()); |
|
782 #endif |
|
783 |
|
784 if (maxH != d->savedStrut) |
|
785 reformat(); |
|
786 else |
|
787 update(); |
|
788 } |
|
789 if (e->type() == QEvent::ChildRemoved) { |
|
790 QStatusBarPrivate::SBItem* item = 0; |
|
791 for (int i=0; i<d->items.size(); ++i) { |
|
792 item = d->items.at(i); |
|
793 if (!item) |
|
794 break; |
|
795 if (item->w == ((QChildEvent*)e)->child()) { |
|
796 d->items.removeAt(i); |
|
797 delete item; |
|
798 } |
|
799 } |
|
800 } |
|
801 |
|
802 // On Mac OS X Leopard it is possible to drag the window by clicking |
|
803 // on the tool bar on most applications. |
|
804 #ifndef Q_WS_MAC |
|
805 return QWidget::event(e); |
|
806 #else |
|
807 if (QSysInfo::MacintoshVersion <= QSysInfo::MV_10_4) |
|
808 return QWidget::event(e); |
|
809 |
|
810 // Enable drag-click only if the status bar is the status bar for a |
|
811 // QMainWindow with a unifed toolbar. |
|
812 if (parent() == 0 || qobject_cast<QMainWindow *>(parent()) == 0 || |
|
813 qobject_cast<QMainWindow *>(parent())->unifiedTitleAndToolBarOnMac() == false ) |
|
814 return QWidget::event(e); |
|
815 |
|
816 // Check for mouse events. |
|
817 QMouseEvent *mouseEvent; |
|
818 if (e->type() == QEvent::MouseButtonPress || |
|
819 e->type() == QEvent::MouseMove || |
|
820 e->type() == QEvent::MouseButtonRelease) { |
|
821 mouseEvent = static_cast <QMouseEvent*>(e); |
|
822 } else { |
|
823 return QWidget::event(e); |
|
824 } |
|
825 |
|
826 // The following is a standard mouse drag handler. |
|
827 if (e->type() == QEvent::MouseButtonPress && (mouseEvent->button() == Qt::LeftButton)) { |
|
828 d->dragStart = mouseEvent->pos(); |
|
829 } else if (e->type() == QEvent::MouseMove){ |
|
830 if (d->dragStart == QPoint()) |
|
831 return QWidget::event(e); |
|
832 QPoint pos = mouseEvent->pos(); |
|
833 QPoint delta = (pos - d->dragStart); |
|
834 window()->move(window()->pos() + delta); |
|
835 } else if (e->type() == QEvent::MouseButtonRelease && (mouseEvent->button() == Qt::LeftButton)){ |
|
836 d->dragStart = QPoint(); |
|
837 } else { |
|
838 return QWidget::event(e); |
|
839 } |
|
840 |
|
841 return true; |
|
842 #endif |
|
843 } |
|
844 |
|
845 QT_END_NAMESPACE |
|
846 |
|
847 #endif |