source: trunk/src/gui/widgets/qtoolbar.cpp@ 460

Last change on this file since 460 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 35.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qtoolbar.h"
43
44#ifndef QT_NO_TOOLBAR
45
46#include <qapplication.h>
47#include <qcombobox.h>
48#include <qevent.h>
49#include <qlayout.h>
50#include <qmainwindow.h>
51#include <qmenu.h>
52#include <qmenubar.h>
53#include <qrubberband.h>
54#include <qsignalmapper.h>
55#include <qstylepainter.h>
56#include <qtoolbutton.h>
57#include <qwidgetaction.h>
58#include <qtimer.h>
59#include <private/qwidgetaction_p.h>
60#ifdef Q_WS_MAC
61#include <private/qt_mac_p.h>
62#include <private/qt_cocoa_helpers_mac_p.h>
63#endif
64
65#include <private/qmainwindowlayout_p.h>
66
67#include "qtoolbar_p.h"
68#include "qtoolbarseparator_p.h"
69#include "qtoolbarlayout_p.h"
70
71#include "qdebug.h"
72
73QT_BEGIN_NAMESPACE
74
75#ifdef Q_WS_MAC
76static void qt_mac_updateToolBarButtonHint(QWidget *parentWidget)
77{
78 if (!(parentWidget->windowFlags() & Qt::CustomizeWindowHint))
79 parentWidget->setWindowFlags(parentWidget->windowFlags() | Qt::MacWindowToolBarButtonHint);
80}
81#endif
82
83/******************************************************************************
84** QToolBarPrivate
85*/
86
87void QToolBarPrivate::init()
88{
89 Q_Q(QToolBar);
90
91 waitForPopupTimer = new QTimer(q);
92 waitForPopupTimer->setSingleShot(false);
93 waitForPopupTimer->setInterval(500);
94 QObject::connect(waitForPopupTimer, SIGNAL(timeout()), q, SLOT(_q_waitForPopup()));
95
96 floatable = true;
97 movable = true;
98 q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
99 q->setBackgroundRole(QPalette::Button);
100 q->setAttribute(Qt::WA_Hover);
101 q->setAttribute(Qt::WA_X11NetWmWindowTypeToolBar);
102
103 QStyle *style = q->style();
104 int e = style->pixelMetric(QStyle::PM_ToolBarIconSize, 0, q);
105 iconSize = QSize(e, e);
106
107 layout = new QToolBarLayout(q);
108 layout->updateMarginAndSpacing();
109
110#ifdef Q_WS_MAC
111 if (q->parentWidget() && q->parentWidget()->isWindow()) {
112 // Make sure that the window has the "toolbar" button.
113 QWidget *parentWidget = q->parentWidget();
114 qt_mac_updateToolBarButtonHint(parentWidget);
115 reinterpret_cast<QToolBar *>(parentWidget)->d_func()->createWinId(); // Please let me create your winId...
116 extern OSWindowRef qt_mac_window_for(const QWidget *); // qwidget_mac.cpp
117 macWindowToolbarShow(q->parentWidget(), true);
118 }
119#endif
120
121 toggleViewAction = new QAction(q);
122 toggleViewAction->setCheckable(true);
123 q->setMovable(q->style()->styleHint(QStyle::SH_ToolBar_Movable, 0, q ));
124 QObject::connect(toggleViewAction, SIGNAL(triggered(bool)), q, SLOT(_q_toggleView(bool)));
125}
126
127void QToolBarPrivate::_q_toggleView(bool b)
128{
129 Q_Q(QToolBar);
130 if (b == q->isHidden()) {
131 if (b)
132 q->show();
133 else
134 q->close();
135 }
136}
137
138void QToolBarPrivate::_q_updateIconSize(const QSize &sz)
139{
140 Q_Q(QToolBar);
141 if (!explicitIconSize) {
142 // iconSize not explicitly set
143 q->setIconSize(sz);
144 explicitIconSize = false;
145 }
146}
147
148void QToolBarPrivate::_q_updateToolButtonStyle(Qt::ToolButtonStyle style)
149{
150 Q_Q(QToolBar);
151 if (!explicitToolButtonStyle) {
152 q->setToolButtonStyle(style);
153 explicitToolButtonStyle = false;
154 }
155}
156
157void QToolBarPrivate::updateWindowFlags(bool floating, bool unplug)
158{
159 Q_Q(QToolBar);
160 Qt::WindowFlags flags = floating ? Qt::Tool : Qt::Widget;
161
162 flags |= Qt::FramelessWindowHint;
163
164 if (unplug) {
165 flags |= Qt::X11BypassWindowManagerHint;
166#ifdef Q_WS_MAC
167 flags |= Qt::WindowStaysOnTopHint;
168#endif
169 }
170
171 q->setWindowFlags(flags);
172}
173
174void QToolBarPrivate::setWindowState(bool floating, bool unplug, const QRect &rect)
175{
176 Q_Q(QToolBar);
177 bool visible = !q->isHidden();
178 bool wasFloating = q->isFloating(); // ...is also currently using popup menus
179
180 q->hide();
181
182 updateWindowFlags(floating, unplug);
183
184 if (floating != wasFloating)
185 layout->checkUsePopupMenu();
186
187 if (!rect.isNull())
188 q->setGeometry(rect);
189
190 if (visible)
191 q->show();
192}
193
194void QToolBarPrivate::initDrag(const QPoint &pos)
195{
196 Q_Q(QToolBar);
197
198 if (state != 0)
199 return;
200
201 QMainWindow *win = qobject_cast<QMainWindow*>(q->parentWidget());
202 Q_ASSERT(win != 0);
203 QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
204 Q_ASSERT(layout != 0);
205 if (layout->pluggingWidget != 0) // the main window is animating a docking operation
206 return;
207
208 state = new DragState;
209 state->pressPos = pos;
210 state->dragging = false;
211 state->moving = false;
212 state->widgetItem = 0;
213
214 if (q->layoutDirection() == Qt::RightToLeft)
215 state->pressPos = QPoint(q->width() - state->pressPos.x(), state->pressPos.y());
216}
217
218void QToolBarPrivate::startDrag(bool moving)
219{
220 Q_Q(QToolBar);
221
222 Q_ASSERT(state != 0);
223
224 if ((moving && state->moving) || state->dragging)
225 return;
226
227 QMainWindow *win = qobject_cast<QMainWindow*>(q->parentWidget());
228 Q_ASSERT(win != 0);
229 QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
230 Q_ASSERT(layout != 0);
231
232 if (!moving) {
233 state->widgetItem = layout->unplug(q);
234#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
235 if (q->isWindow()) {
236 setWindowState(true, true); //set it to floating
237 }
238#endif
239 Q_ASSERT(state->widgetItem != 0);
240 }
241 state->dragging = !moving;
242 state->moving = moving;
243}
244
245void QToolBarPrivate::endDrag()
246{
247 Q_Q(QToolBar);
248 Q_ASSERT(state != 0);
249
250 q->releaseMouse();
251
252 if (state->dragging) {
253 QMainWindowLayout *layout =
254 qobject_cast<QMainWindowLayout *>(q->parentWidget()->layout());
255 Q_ASSERT(layout != 0);
256
257 if (!layout->plug(state->widgetItem)) {
258 if (q->isFloatable()) {
259 layout->restore();
260#if defined(Q_WS_X11) || defined(Q_WS_MAC)
261 setWindowState(true); // gets rid of the X11BypassWindowManager window flag
262 // and activates the resizer
263#endif
264 q->activateWindow();
265 } else {
266 layout->revert(state->widgetItem);
267 }
268 }
269 }
270
271 delete state;
272 state = 0;
273}
274
275bool QToolBarPrivate::mousePressEvent(QMouseEvent *event)
276{
277 if (layout->handleRect().contains(event->pos()) == false) {
278#ifdef Q_WS_MAC
279 Q_Q(QToolBar);
280 // When using the unified toolbar on Mac OS X the user can can click and
281 // drag between toolbar contents to move the window. Make this work by
282 // implementing the standard mouse-dragging code and then call
283 // window->move() in mouseMoveEvent below.
284 if (QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q->parentWidget())) {
285 if (mainWindow->toolBarArea(q) == Qt::TopToolBarArea
286 && mainWindow->unifiedTitleAndToolBarOnMac()
287 && q->childAt(event->pos()) == 0) {
288 macWindowDragging = true;
289 macWindowDragPressPosition = event->pos();
290 return true;
291 }
292 }
293#endif
294 return false;
295 }
296
297 if (event->button() != Qt::LeftButton)
298 return true;
299
300 if (!layout->movable())
301 return true;
302
303 initDrag(event->pos());
304 return true;
305}
306
307bool QToolBarPrivate::mouseReleaseEvent(QMouseEvent*)
308{
309 if (state != 0) {
310 endDrag();
311 return true;
312 } else {
313#ifdef Q_WS_MAC
314 macWindowDragging = false;
315 macWindowDragPressPosition = QPoint();
316 return true;
317#endif
318 return false;
319 }
320}
321
322bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event)
323{
324 Q_Q(QToolBar);
325
326 if (!state) {
327#ifdef Q_WS_MAC
328 if (!macWindowDragging)
329 return false;
330 QWidget *w = q->window();
331 const QPoint delta = event->pos() - macWindowDragPressPosition;
332 w->move(w->pos() + delta);
333 return true;
334#endif
335 return false;
336 }
337
338 QMainWindow *win = qobject_cast<QMainWindow*>(q->parentWidget());
339 if (win == 0)
340 return true;
341
342 QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
343 Q_ASSERT(layout != 0);
344
345 if (layout->pluggingWidget == 0
346 && (event->pos() - state->pressPos).manhattanLength() > QApplication::startDragDistance()) {
347 const bool wasDragging = state->dragging;
348 const bool moving = !q->isWindow() && (orientation == Qt::Vertical ?
349 event->x() >= 0 && event->x() < q->width() :
350 event->y() >= 0 && event->y() < q->height());
351
352 startDrag(moving);
353 if (!moving && !wasDragging) {
354#ifdef Q_OS_WIN
355 grabMouseWhileInWindow();
356#else
357 q->grabMouse();
358#endif
359 }
360 }
361
362 if (state->dragging) {
363 QPoint pos = event->globalPos();
364 // if we are right-to-left, we move so as to keep the right edge the same distance
365 // from the mouse
366 if (q->layoutDirection() == Qt::LeftToRight)
367 pos -= state->pressPos;
368 else
369 pos += QPoint(state->pressPos.x() - q->width(), -state->pressPos.y());
370
371 q->move(pos);
372 layout->hover(state->widgetItem, event->globalPos());
373 } else if (state->moving) {
374
375 const QPoint rtl(q->width() - state->pressPos.x(), state->pressPos.y()); //for RTL
376 const QPoint globalPressPos = q->mapToGlobal(q->layoutDirection() == Qt::RightToLeft ? rtl : state->pressPos);
377 int pos = 0;
378
379 QPoint delta = event->globalPos() - globalPressPos;
380 if (orientation == Qt::Vertical) {
381 pos = q->y() + delta.y();
382 } else {
383 if (q->layoutDirection() == Qt::RightToLeft) {
384 pos = win->width() - q->width() - q->x() - delta.x();
385 } else {
386 pos = q->x() + delta.x();
387 }
388 }
389
390 layout->moveToolBar(q, pos);
391 }
392 return true;
393}
394
395void QToolBarPrivate::unplug(const QRect &_r)
396{
397 Q_Q(QToolBar);
398
399 QRect r = _r;
400 r.moveTopLeft(q->mapToGlobal(QPoint(0, 0)));
401 setWindowState(true, true, r);
402}
403
404void QToolBarPrivate::plug(const QRect &r)
405{
406 setWindowState(false, false, r);
407}
408
409/******************************************************************************
410** QToolBar
411*/
412
413/*!
414 \class QToolBar
415
416 \brief The QToolBar class provides a movable panel that contains a
417 set of controls.
418
419 \ingroup application
420 \mainclass
421
422 Toolbar buttons are added by adding \e actions, using addAction()
423 or insertAction(). Groups of buttons can be separated using
424 addSeparator() or insertSeparator(). If a toolbar button is not
425 appropriate, a widget can be inserted instead using addWidget() or
426 insertWidget(); examples of suitable widgets are QSpinBox,
427 QDoubleSpinBox, and QComboBox. When a toolbar button is pressed it
428 emits the actionTriggered() signal.
429
430 A toolbar can be fixed in place in a particular area (e.g. at the
431 top of the window), or it can be movable (isMovable()) between
432 toolbar areas; see allowedAreas() and isAreaAllowed().
433
434 When a toolbar is resized in such a way that it is too small to
435 show all the items it contains, an extension button will appear as
436 the last item in the toolbar. Pressing the extension button will
437 pop up a menu containing the items that does not currently fit in
438 the toolbar.
439
440 When a QToolBar is not a child of a QMainWindow, it looses the ability
441 to populate the extension pop up with widgets added to the toolbar using
442 addWidget(). Please use widget actions created by inheriting QWidgetAction
443 and implementing QWidgetAction::createWidget() instead. This is a known
444 issue which will be fixed in a future release.
445
446 \sa QToolButton, QMenu, QAction, {Application Example}
447*/
448
449/*!
450 \fn bool QToolBar::isAreaAllowed(Qt::ToolBarArea area) const
451
452 Returns true if this toolbar is dockable in the given \a area;
453 otherwise returns false.
454*/
455
456/*!
457 \fn void QToolBar::addAction(QAction *action)
458 \overload
459
460 Appends the action \a action to the toolbar's list of actions.
461
462 \sa QMenu::addAction(), QWidget::addAction()
463*/
464
465/*!
466 \fn void QToolBar::actionTriggered(QAction *action)
467
468 This signal is emitted when an action in this toolbar is triggered.
469 This happens when the action's tool button is pressed, or when the
470 action is triggered in some other way outside the tool bar. The parameter
471 holds the triggered \a action.
472*/
473
474/*!
475 \fn void QToolBar::allowedAreasChanged(Qt::ToolBarAreas allowedAreas)
476
477 This signal is emitted when the collection of allowed areas for the
478 toolbar is changed. The new areas in which the toolbar can be positioned
479 are specified by \a allowedAreas.
480
481 \sa allowedAreas
482*/
483
484/*!
485 \fn void QToolBar::iconSizeChanged(const QSize &iconSize)
486
487 This signal is emitted when the icon size is changed. The \a
488 iconSize parameter holds the toolbar's new icon size.
489
490 \sa iconSize QMainWindow::iconSize
491*/
492
493/*!
494 \fn void QToolBar::movableChanged(bool movable)
495
496 This signal is emitted when the toolbar becomes movable or fixed.
497 If the toolbar can be moved, \a movable is true; otherwise it is
498 false.
499
500 \sa movable
501*/
502
503/*!
504 \fn void QToolBar::orientationChanged(Qt::Orientation orientation)
505
506 This signal is emitted when the orientation of the toolbar changes.
507 The new orientation is specified by the \a orientation given.
508
509 \sa orientation
510*/
511
512/*!
513 \fn void QToolBar::toolButtonStyleChanged(Qt::ToolButtonStyle toolButtonStyle)
514
515 This signal is emitted when the tool button style is changed. The
516 \a toolButtonStyle parameter holds the toolbar's new tool button
517 style.
518
519 \sa toolButtonStyle QMainWindow::toolButtonStyle
520*/
521
522/*!
523 Constructs a QToolBar with the given \a parent.
524*/
525QToolBar::QToolBar(QWidget *parent)
526 : QWidget(*new QToolBarPrivate, parent, 0)
527{
528 Q_D(QToolBar);
529 d->init();
530}
531
532/*!
533 Constructs a QToolBar with the given \a parent.
534
535 The given window \a title identifies the toolbar and is shown in
536 the context menu provided by QMainWindow.
537
538 \sa setWindowTitle()
539*/
540QToolBar::QToolBar(const QString &title, QWidget *parent)
541 : QWidget(*new QToolBarPrivate, parent, 0)
542{
543 Q_D(QToolBar);
544 d->init();
545 setWindowTitle(title);
546}
547
548#ifdef QT3_SUPPORT
549/*! \obsolete
550 Constructs a QToolBar with the given \a parent and \a name.
551*/
552QToolBar::QToolBar(QWidget *parent, const char *name)
553 : QWidget(*new QToolBarPrivate, parent, 0)
554{
555 Q_D(QToolBar);
556 d->init();
557 setObjectName(QString::fromAscii(name));
558}
559#endif
560
561/*!
562 Destroys the toolbar.
563*/
564QToolBar::~QToolBar()
565{
566 // Remove the toolbar button if there is nothing left.
567 QMainWindow *mainwindow = qobject_cast<QMainWindow *>(parentWidget());
568 if (mainwindow) {
569#ifdef Q_WS_MAC
570 QMainWindowLayout *mainwin_layout = qobject_cast<QMainWindowLayout *>(mainwindow->layout());
571 if (mainwin_layout && mainwin_layout->layoutState.toolBarAreaLayout.isEmpty()
572 && mainwindow->testAttribute(Qt::WA_WState_Created))
573 macWindowToolbarShow(mainwindow, false);
574#endif
575 }
576}
577
578/*! \property QToolBar::movable
579 \brief whether the user can move the toolbar within the toolbar area,
580 or between toolbar areas
581
582 By default, this property is true.
583
584 This property only makes sense if the toolbar is in a
585 QMainWindow.
586
587 \sa allowedAreas
588*/
589
590void QToolBar::setMovable(bool movable)
591{
592 Q_D(QToolBar);
593 if (!movable == !d->movable)
594 return;
595 d->movable = movable;
596 d->layout->invalidate();
597 emit movableChanged(d->movable);
598}
599
600bool QToolBar::isMovable() const
601{
602 Q_D(const QToolBar);
603 return d->movable;
604}
605
606/*!
607 \property QToolBar::floatable
608 \brief whether the toolbar can be dragged and dropped as an independent window.
609
610 The default is true.
611*/
612bool QToolBar::isFloatable() const
613{
614 Q_D(const QToolBar);
615 return d->floatable;
616}
617
618void QToolBar::setFloatable(bool floatable)
619{
620 Q_D(QToolBar);
621 d->floatable = floatable;
622}
623
624/*!
625 \property QToolBar::floating
626 \brief whether the toolbar is an independent window.
627
628 By default, this property is true.
629
630 \sa QWidget::isWindow()
631*/
632bool QToolBar::isFloating() const
633{
634 return isWindow();
635}
636
637/*!
638 \property QToolBar::allowedAreas
639 \brief areas where the toolbar may be placed
640
641 The default is Qt::AllToolBarAreas.
642
643 This property only makes sense if the toolbar is in a
644 QMainWindow.
645
646 \sa movable
647*/
648
649void QToolBar::setAllowedAreas(Qt::ToolBarAreas areas)
650{
651 Q_D(QToolBar);
652 areas &= Qt::ToolBarArea_Mask;
653 if (areas == d->allowedAreas)
654 return;
655 d->allowedAreas = areas;
656 emit allowedAreasChanged(d->allowedAreas);
657}
658
659Qt::ToolBarAreas QToolBar::allowedAreas() const
660{
661 Q_D(const QToolBar);
662#ifdef Q_WS_MAC
663 if (QMainWindow *window = qobject_cast<QMainWindow *>(parentWidget())) {
664 if (window->unifiedTitleAndToolBarOnMac()) // Don't allow drags to the top (for now).
665 return (d->allowedAreas & ~Qt::TopToolBarArea);
666 }
667#endif
668 return d->allowedAreas;
669}
670
671/*! \property QToolBar::orientation
672 \brief orientation of the toolbar
673
674 The default is Qt::Horizontal.
675
676 This function should not be used when the toolbar is managed
677 by QMainWindow. You can use QMainWindow::addToolBar() or
678 QMainWindow::insertToolBar() if you wish to move a toolbar (that
679 is already added to a main window) to another Qt::ToolBarArea.
680*/
681
682void QToolBar::setOrientation(Qt::Orientation orientation)
683{
684 Q_D(QToolBar);
685 if (orientation == d->orientation)
686 return;
687
688 d->orientation = orientation;
689
690 if (orientation == Qt::Vertical)
691 setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred));
692 else
693 setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
694
695 d->layout->invalidate();
696 d->layout->activate();
697
698 emit orientationChanged(d->orientation);
699}
700
701Qt::Orientation QToolBar::orientation() const
702{ Q_D(const QToolBar); return d->orientation; }
703
704/*!
705 \property QToolBar::iconSize
706 \brief size of icons in the toolbar.
707
708 The default size is determined by the application's style and is
709 derived from the QStyle::PM_ToolBarIconSize pixel metric. It is
710 the maximum size an icon can have. Icons of smaller size will not
711 be scaled up.
712*/
713
714QSize QToolBar::iconSize() const
715{ Q_D(const QToolBar); return d->iconSize; }
716
717void QToolBar::setIconSize(const QSize &iconSize)
718{
719 Q_D(QToolBar);
720 QSize sz = iconSize;
721 if (!sz.isValid()) {
722 QMainWindow *mw = qobject_cast<QMainWindow *>(parentWidget());
723 if (mw && mw->layout()) {
724 QLayout *layout = mw->layout();
725 int i = 0;
726 QLayoutItem *item = 0;
727 do {
728 item = layout->itemAt(i++);
729 if (item && (item->widget() == this))
730 sz = mw->iconSize();
731 } while (!sz.isValid() && item != 0);
732 }
733 }
734 if (!sz.isValid()) {
735 const int metric = style()->pixelMetric(QStyle::PM_ToolBarIconSize, 0, this);
736 sz = QSize(metric, metric);
737 }
738 if (d->iconSize != sz) {
739 d->iconSize = sz;
740 setMinimumSize(0, 0);
741 emit iconSizeChanged(d->iconSize);
742 }
743 d->explicitIconSize = iconSize.isValid();
744
745 d->layout->invalidate();
746}
747
748/*!
749 \property QToolBar::toolButtonStyle
750 \brief the style of toolbar buttons
751
752 This property defines the style of all tool buttons that are added
753 as \l{QAction}s. Note that if you add a QToolButton with the
754 addWidget() method, it will not get this button style.
755
756 The default is Qt::ToolButtonIconOnly.
757*/
758
759Qt::ToolButtonStyle QToolBar::toolButtonStyle() const
760{ Q_D(const QToolBar); return d->toolButtonStyle; }
761
762void QToolBar::setToolButtonStyle(Qt::ToolButtonStyle toolButtonStyle)
763{
764 Q_D(QToolBar);
765 d->explicitToolButtonStyle = true;
766 if (d->toolButtonStyle == toolButtonStyle)
767 return;
768 d->toolButtonStyle = toolButtonStyle;
769 setMinimumSize(0, 0);
770 emit toolButtonStyleChanged(d->toolButtonStyle);
771}
772
773/*!
774 Removes all actions from the toolbar.
775
776 \sa removeAction()
777*/
778void QToolBar::clear()
779{
780 QList<QAction *> actions = this->actions();
781 for(int i = 0; i < actions.size(); i++)
782 removeAction(actions.at(i));
783}
784
785/*!
786 \overload
787
788 Creates a new action with the given \a text. This action is added to
789 the end of the toolbar.
790*/
791QAction *QToolBar::addAction(const QString &text)
792{
793 QAction *action = new QAction(text, this);
794 addAction(action);
795 return action;
796}
797
798/*!
799 \overload
800
801 Creates a new action with the given \a icon and \a text. This
802 action is added to the end of the toolbar.
803*/
804QAction *QToolBar::addAction(const QIcon &icon, const QString &text)
805{
806 QAction *action = new QAction(icon, text, this);
807 addAction(action);
808 return action;
809}
810
811/*!
812 \overload
813
814 Creates a new action with the given \a text. This action is added to
815 the end of the toolbar. The action's \link QAction::triggered()
816 triggered()\endlink signal is connected to \a member in \a
817 receiver.
818*/
819QAction *QToolBar::addAction(const QString &text,
820 const QObject *receiver, const char* member)
821{
822 QAction *action = new QAction(text, this);
823 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member);
824 addAction(action);
825 return action;
826}
827
828/*!
829 \overload
830
831 Creates a new action with the icon \a icon and text \a text. This
832 action is added to the end of the toolbar. The action's \link
833 QAction::triggered() triggered()\endlink signal is connected to \a
834 member in \a receiver.
835*/
836QAction *QToolBar::addAction(const QIcon &icon, const QString &text,
837 const QObject *receiver, const char* member)
838{
839 QAction *action = new QAction(icon, text, this);
840 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member);
841 addAction(action);
842 return action;
843}
844
845/*!
846 Adds a separator to the end of the toolbar.
847
848 \sa insertSeparator()
849*/
850QAction *QToolBar::addSeparator()
851{
852 QAction *action = new QAction(this);
853 action->setSeparator(true);
854 addAction(action);
855 return action;
856}
857
858/*!
859 Inserts a separator into the toolbar in front of the toolbar
860 item associated with the \a before action.
861
862 \sa addSeparator()
863*/
864QAction *QToolBar::insertSeparator(QAction *before)
865{
866 QAction *action = new QAction(this);
867 action->setSeparator(true);
868 insertAction(before, action);
869 return action;
870}
871
872/*!
873 Adds the given \a widget to the toolbar as the toolbar's last
874 item.
875
876 The toolbar takes ownership of \a widget.
877
878 If you add a QToolButton with this method, the tools bar's
879 Qt::ToolButtonStyle will not be respected.
880
881 Note: You should use QAction::setVisible() to change the
882 visibility of the widget. Using QWidget::setVisible(),
883 QWidget::show() and QWidget::hide() does not work.
884
885 \sa insertWidget()
886*/
887QAction *QToolBar::addWidget(QWidget *widget)
888{
889 QWidgetAction *action = new QWidgetAction(this);
890 action->setDefaultWidget(widget);
891 action->d_func()->autoCreated = true;
892 addAction(action);
893 return action;
894}
895
896/*!
897 Inserts the given \a widget in front of the toolbar item
898 associated with the \a before action.
899
900 Note: You should use QAction::setVisible() to change the
901 visibility of the widget. Using QWidget::setVisible(),
902 QWidget::show() and QWidget::hide() does not work.
903
904 \sa addWidget()
905*/
906QAction *QToolBar::insertWidget(QAction *before, QWidget *widget)
907{
908 QWidgetAction *action = new QWidgetAction(this);
909 action->setDefaultWidget(widget);
910 action->d_func()->autoCreated = true;
911 insertAction(before, action);
912 return action;
913}
914
915/*!
916 \internal
917
918 Returns the geometry of the toolbar item associated with the given
919 \a action, or an invalid QRect if no matching item is found.
920*/
921QRect QToolBar::actionGeometry(QAction *action) const
922{
923 Q_D(const QToolBar);
924
925 int index = d->layout->indexOf(action);
926 if (index == -1)
927 return QRect();
928 return d->layout->itemAt(index)->widget()->geometry();
929}
930
931/*!
932 Returns the action at point \a p. This function returns zero if no
933 action was found.
934
935 \sa QWidget::childAt()
936*/
937QAction *QToolBar::actionAt(const QPoint &p) const
938{
939 Q_D(const QToolBar);
940 QWidget *widget = childAt(p);
941 int index = d->layout->indexOf(widget);
942 if (index == -1)
943 return 0;
944 QLayoutItem *item = d->layout->itemAt(index);
945 return static_cast<QToolBarItem*>(item)->action;
946}
947
948/*! \fn QAction *QToolBar::actionAt(int x, int y) const
949 \overload
950
951 Returns the action at the point \a x, \a y. This function returns
952 zero if no action was found.
953*/
954
955/*! \reimp */
956void QToolBar::actionEvent(QActionEvent *event)
957{
958 Q_D(QToolBar);
959 QAction *action = event->action();
960 QWidgetAction *widgetAction = qobject_cast<QWidgetAction *>(action);
961
962 switch (event->type()) {
963 case QEvent::ActionAdded: {
964 Q_ASSERT_X(widgetAction == 0 || d->layout->indexOf(widgetAction) == -1,
965 "QToolBar", "widgets cannot be inserted multiple times");
966
967 // reparent the action to this toolbar if it has been created
968 // using the addAction(text) etc. convenience functions, to
969 // preserve Qt 4.1.x behavior. The widget is already
970 // reparented to us due to the createWidget call inside
971 // createItem()
972 if (widgetAction != 0 && widgetAction->d_func()->autoCreated)
973 widgetAction->setParent(this);
974
975 int index = d->layout->count();
976 if (event->before()) {
977 index = d->layout->indexOf(event->before());
978 Q_ASSERT_X(index != -1, "QToolBar::insertAction", "internal error");
979 }
980 d->layout->insertAction(index, action);
981 break;
982 }
983
984 case QEvent::ActionChanged:
985 d->layout->invalidate();
986 break;
987
988 case QEvent::ActionRemoved: {
989 int index = d->layout->indexOf(action);
990 if (index != -1) {
991 delete d->layout->takeAt(index);
992 }
993 break;
994 }
995
996 default:
997 Q_ASSERT_X(false, "QToolBar::actionEvent", "internal error");
998 }
999}
1000
1001/*! \reimp */
1002void QToolBar::changeEvent(QEvent *event)
1003{
1004 Q_D(QToolBar);
1005 switch (event->type()) {
1006 case QEvent::WindowTitleChange:
1007 d->toggleViewAction->setText(windowTitle());
1008 break;
1009 case QEvent::StyleChange:
1010 d->layout->invalidate();
1011 if (!d->explicitIconSize)
1012 setIconSize(QSize());
1013 d->layout->updateMarginAndSpacing();
1014 break;
1015 case QEvent::LayoutDirectionChange:
1016 d->layout->invalidate();
1017 break;
1018 default:
1019 break;
1020 }
1021 QWidget::changeEvent(event);
1022}
1023
1024/*! \reimp */
1025void QToolBar::paintEvent(QPaintEvent *)
1026{
1027 Q_D(QToolBar);
1028
1029 QPainter p(this);
1030 QStyle *style = this->style();
1031 QStyleOptionToolBar opt;
1032 initStyleOption(&opt);
1033
1034 if (d->layout->expanded || d->layout->animating || isWindow()) {
1035 //if the toolbar is expended, we need to fill the background with the window color
1036 //because some styles may expects that.
1037 p.fillRect(opt.rect, palette().background());
1038 style->drawControl(QStyle::CE_ToolBar, &opt, &p, this);
1039 style->drawPrimitive(QStyle::PE_FrameMenu, &opt, &p, this);
1040 } else {
1041 style->drawControl(QStyle::CE_ToolBar, &opt, &p, this);
1042 }
1043
1044 opt.rect = d->layout->handleRect();
1045 if (opt.rect.isValid())
1046 style->drawPrimitive(QStyle::PE_IndicatorToolBarHandle, &opt, &p, this);
1047}
1048
1049/*
1050 Checks if an expanded toolbar has to wait for this popup to close before
1051 the toolbar collapses. This is true if
1052 1) the popup has the toolbar in its parent chain,
1053 2) the popup is a menu whose menuAction is somewhere in the toolbar.
1054*/
1055static bool waitForPopup(QToolBar *tb, QWidget *popup)
1056{
1057 if (popup == 0 || popup->isHidden())
1058 return false;
1059
1060 QWidget *w = popup;
1061 while (w != 0) {
1062 if (w == tb)
1063 return true;
1064 w = w->parentWidget();
1065 }
1066
1067 QMenu *menu = qobject_cast<QMenu*>(popup);
1068 if (menu == 0)
1069 return false;
1070
1071 QAction *action = menu->menuAction();
1072 QList<QWidget*> widgets = action->associatedWidgets();
1073 for (int i = 0; i < widgets.count(); ++i) {
1074 if (waitForPopup(tb, widgets.at(i)))
1075 return true;
1076 }
1077
1078 return false;
1079}
1080
1081/*! \reimp */
1082bool QToolBar::event(QEvent *event)
1083{
1084 Q_D(QToolBar);
1085
1086 switch (event->type()) {
1087 case QEvent::Hide:
1088 if (!isHidden())
1089 break;
1090 // fallthrough intended
1091 case QEvent::Show:
1092 d->toggleViewAction->setChecked(event->type() == QEvent::Show);
1093#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
1094 // Fall through
1095 case QEvent::LayoutRequest: {
1096 // There's currently no way to invalidate the size and let
1097 // HIToolbar know about it. This forces a re-check.
1098 int earlyResult = -1;
1099 if (QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget())) {
1100 bool needUpdate = true;
1101 if (event->type() == QEvent::LayoutRequest) {
1102 QSize oldSizeHint = sizeHint();
1103 earlyResult = QWidget::event(event) ? 1 : 0;
1104 needUpdate = oldSizeHint != sizeHint();
1105 }
1106
1107 if (needUpdate) {
1108 OSWindowRef windowRef = qt_mac_window_for(this);
1109 if (mainWindow->unifiedTitleAndToolBarOnMac()
1110 && mainWindow->toolBarArea(this) == Qt::TopToolBarArea
1111 && macWindowToolbarVisible(windowRef)) {
1112 DisableScreenUpdates();
1113 macWindowToolbarShow(this, false);
1114 macWindowToolbarShow(this, true);
1115 EnableScreenUpdates();
1116 }
1117 }
1118
1119 if (earlyResult != -1)
1120 return earlyResult;
1121 }
1122 }
1123#endif
1124 break;
1125 case QEvent::ParentChange:
1126 d->layout->checkUsePopupMenu();
1127#if defined(Q_WS_MAC)
1128 if (parentWidget() && parentWidget()->isWindow())
1129 qt_mac_updateToolBarButtonHint(parentWidget());
1130#endif
1131 break;
1132
1133 case QEvent::MouseButtonPress: {
1134 if (d->mousePressEvent(static_cast<QMouseEvent*>(event)))
1135 return true;
1136 break;
1137 }
1138 case QEvent::MouseButtonRelease:
1139 if (d->mouseReleaseEvent(static_cast<QMouseEvent*>(event)))
1140 return true;
1141 break;
1142 case QEvent::HoverMove: {
1143#ifndef QT_NO_CURSOR
1144 QHoverEvent *e = static_cast<QHoverEvent*>(event);
1145 if (d->layout->handleRect().contains(e->pos()))
1146 setCursor(Qt::SizeAllCursor);
1147 else
1148 unsetCursor();
1149#endif
1150 break;
1151 }
1152 case QEvent::MouseMove:
1153 if (d->mouseMoveEvent(static_cast<QMouseEvent*>(event)))
1154 return true;
1155 break;
1156#ifdef Q_OS_WINCE
1157 case QEvent::ContextMenu:
1158 {
1159 QContextMenuEvent* contextMenuEvent = static_cast<QContextMenuEvent*>(event);
1160 QWidget* child = childAt(contextMenuEvent->pos());
1161 QAbstractButton* button = qobject_cast<QAbstractButton*>(child);
1162 if (button)
1163 button->setDown(false);
1164 }
1165 break;
1166#endif
1167 case QEvent::Leave:
1168 if (d->state != 0 && d->state->dragging) {
1169#ifdef Q_OS_WIN
1170 // This is a workaround for loosing the mouse on Vista.
1171 QPoint pos = QCursor::pos();
1172 QMouseEvent fake(QEvent::MouseMove, mapFromGlobal(pos), pos, Qt::NoButton,
1173 QApplication::mouseButtons(), QApplication::keyboardModifiers());
1174 d->mouseMoveEvent(&fake);
1175#endif
1176 } else {
1177 if (!d->layout->expanded)
1178 break;
1179
1180 QWidget *w = qApp->activePopupWidget();
1181 if (waitForPopup(this, w)) {
1182 d->waitForPopupTimer->start();
1183 break;
1184 }
1185
1186 d->waitForPopupTimer->stop();
1187 d->layout->setExpanded(false);
1188 break;
1189 }
1190 default:
1191 break;
1192 }
1193 return QWidget::event(event);
1194}
1195
1196void QToolBarPrivate::_q_waitForPopup()
1197{
1198 Q_Q(QToolBar);
1199
1200 QWidget *w = qApp->activePopupWidget();
1201 if (!waitForPopup(q, w)) {
1202 waitForPopupTimer->stop();
1203 if (!q->underMouse())
1204 layout->setExpanded(false);
1205 }
1206}
1207
1208/*!
1209 Returns a checkable action that can be used to show or hide this
1210 toolbar.
1211
1212 The action's text is set to the toolbar's window title.
1213
1214 \sa QAction::text QWidget::windowTitle
1215*/
1216QAction *QToolBar::toggleViewAction() const
1217{ Q_D(const QToolBar); return d->toggleViewAction; }
1218
1219/*!
1220 \fn void QToolBar::setLabel(const QString &label)
1221
1222 Use setWindowTitle() instead.
1223*/
1224
1225/*!
1226 \fn QString QToolBar::label() const
1227
1228 Use windowTitle() instead.
1229*/
1230
1231/*!
1232 \since 4.2
1233
1234 Returns the widget associated with the specified \a action.
1235
1236 \sa addWidget()
1237*/
1238QWidget *QToolBar::widgetForAction(QAction *action) const
1239{
1240 Q_D(const QToolBar);
1241
1242 int index = d->layout->indexOf(action);
1243 if (index == -1)
1244 return 0;
1245
1246 return d->layout->itemAt(index)->widget();
1247}
1248
1249/*!
1250 \internal
1251*/
1252void QToolBar::initStyleOption(QStyleOptionToolBar *option) const
1253{
1254 Q_D(const QToolBar);
1255
1256 if (!option)
1257 return;
1258
1259 option->initFrom(this);
1260 if (orientation() == Qt::Horizontal)
1261 option->state |= QStyle::State_Horizontal;
1262 option->lineWidth = style()->pixelMetric(QStyle::PM_ToolBarFrameWidth, 0, this);
1263 option->features = d->layout->movable()
1264 ? QStyleOptionToolBar::Movable
1265 : QStyleOptionToolBar::None;
1266 // if the tool bar is not in a QMainWindow, this will make the painting right
1267 option->toolBarArea = Qt::NoToolBarArea;
1268
1269 // Add more styleoptions if the toolbar has been added to a mainwindow.
1270 QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
1271
1272 if (!mainWindow)
1273 return;
1274
1275 QMainWindowLayout *layout = qobject_cast<QMainWindowLayout *>(mainWindow->layout());
1276 Q_ASSERT_X(layout != 0, "QToolBar::initStyleOption()",
1277 "QMainWindow->layout() != QMainWindowLayout");
1278
1279 layout->getStyleOptionInfo(option, const_cast<QToolBar *>(this));
1280}
1281
1282/*!
1283 \reimp
1284*/
1285void QToolBar::childEvent(QChildEvent *event) // ### remove me in 5.0
1286{
1287 QWidget::childEvent(event);
1288}
1289
1290/*!
1291 \reimp
1292*/
1293void QToolBar::resizeEvent(QResizeEvent *event) // ### remove me in 5.0
1294{
1295 QWidget::resizeEvent(event);
1296}
1297
1298QT_END_NAMESPACE
1299
1300#include "moc_qtoolbar.cpp"
1301
1302#endif // QT_NO_TOOLBAR
Note: See TracBrowser for help on using the repository browser.