| 1 | /**************************************************************************** | 
|---|
| 2 | ** | 
|---|
| 3 | ** Copyright (C) 2011 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 | ** Commercial Usage | 
|---|
| 11 | ** Licensees holding valid Qt Commercial licenses may use this file in | 
|---|
| 12 | ** accordance with the Qt Commercial License Agreement provided with the | 
|---|
| 13 | ** Software or, alternatively, in accordance with the terms contained in | 
|---|
| 14 | ** a written agreement between you and Nokia. | 
|---|
| 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 | ** GNU General Public License Usage | 
|---|
| 29 | ** Alternatively, this file may be used under the terms of the GNU | 
|---|
| 30 | ** General Public License version 3.0 as published by the Free Software | 
|---|
| 31 | ** Foundation and appearing in the file LICENSE.GPL included in the | 
|---|
| 32 | ** packaging of this file.  Please review the following information to | 
|---|
| 33 | ** ensure the GNU General Public License version 3.0 requirements will be | 
|---|
| 34 | ** met: http://www.gnu.org/copyleft/gpl.html. | 
|---|
| 35 | ** | 
|---|
| 36 | ** If you have questions regarding the use of this file, please contact | 
|---|
| 37 | ** Nokia at qt-info@nokia.com. | 
|---|
| 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 | update(); | 
|---|
| 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 | 
|---|