source: trunk/src/gui/widgets/qtoolbutton.cpp@ 642

Last change on this file since 642 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 33.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
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 [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qtoolbutton.h"
43#ifndef QT_NO_TOOLBUTTON
44
45#include <qapplication.h>
46#include <qdesktopwidget.h>
47#include <qdrawutil.h>
48#include <qevent.h>
49#include <qicon.h>
50#include <qmenu.h>
51#include <qpainter.h>
52#include <qpointer.h>
53#include <qstyle.h>
54#include <qstyleoption.h>
55#include <qtooltip.h>
56#include <qmainwindow.h>
57#include <qtoolbar.h>
58#include <qvariant.h>
59#include <qstylepainter.h>
60#include <private/qabstractbutton_p.h>
61#include <private/qaction_p.h>
62#include <private/qmenu_p.h>
63
64QT_BEGIN_NAMESPACE
65
66class QToolButtonPrivate : public QAbstractButtonPrivate
67{
68 Q_DECLARE_PUBLIC(QToolButton)
69public:
70 void init();
71#ifndef QT_NO_MENU
72 void _q_buttonPressed();
73 void popupTimerDone();
74 void _q_updateButtonDown();
75 void _q_menuTriggered(QAction *);
76#endif
77 bool updateHoverControl(const QPoint &pos);
78 void _q_actionTriggered();
79 QStyle::SubControl newHoverControl(const QPoint &pos);
80 QStyle::SubControl hoverControl;
81 QRect hoverRect;
82 QPointer<QAction> menuAction; //the menu set by the user (setMenu)
83 QBasicTimer popupTimer;
84 int delay;
85 Qt::ArrowType arrowType;
86 Qt::ToolButtonStyle toolButtonStyle;
87 QToolButton::ToolButtonPopupMode popupMode;
88 enum { NoButtonPressed=0, MenuButtonPressed=1, ToolButtonPressed=2 };
89 uint buttonPressed : 2;
90 uint menuButtonDown : 1;
91 uint autoRaise : 1;
92 uint repeat : 1;
93 QAction *defaultAction;
94#ifndef QT_NO_MENU
95 bool hasMenu() const;
96 //workaround for task 177850
97 QList<QAction *> actionsCopy;
98#endif
99#ifdef QT3_SUPPORT
100 bool userDefinedPopupDelay;
101#endif
102};
103
104#ifndef QT_NO_MENU
105bool QToolButtonPrivate::hasMenu() const
106{
107 return ((defaultAction && defaultAction->menu())
108 || (menuAction && menuAction->menu())
109 || actions.size() > (defaultAction ? 1 : 0));
110}
111#endif
112
113/*!
114 \class QToolButton
115 \brief The QToolButton class provides a quick-access button to
116 commands or options, usually used inside a QToolBar.
117
118 \ingroup basicwidgets
119
120
121 A tool button is a special button that provides quick-access to
122 specific commands or options. As opposed to a normal command
123 button, a tool button usually doesn't show a text label, but shows
124 an icon instead.
125
126 Tool buttons are normally created when new QAction instances are
127 created with QToolBar::addAction() or existing actions are added
128 to a toolbar with QToolBar::addAction(). It is also possible to
129 construct tool buttons in the same way as any other widget, and
130 arrange them alongside other widgets in layouts.
131
132 One classic use of a tool button is to select tools; for example,
133 the "pen" tool in a drawing program. This would be implemented
134 by using a QToolButton as a toggle button (see setToggleButton()).
135
136 QToolButton supports auto-raising. In auto-raise mode, the button
137 draws a 3D frame only when the mouse points at it. The feature is
138 automatically turned on when a button is used inside a QToolBar.
139 Change it with setAutoRaise().
140
141 A tool button's icon is set as QIcon. This makes it possible to
142 specify different pixmaps for the disabled and active state. The
143 disabled pixmap is used when the button's functionality is not
144 available. The active pixmap is displayed when the button is
145 auto-raised because the mouse pointer is hovering over it.
146
147 The button's look and dimension is adjustable with
148 setToolButtonStyle() and setIconSize(). When used inside a
149 QToolBar in a QMainWindow, the button automatically adjusts to
150 QMainWindow's settings (see QMainWindow::setToolButtonStyle() and
151 QMainWindow::setIconSize()). Instead of an icon, a tool button can
152 also display an arrow symbol, specified with
153 \l{QToolButton::arrowType} {arrowType}.
154
155 A tool button can offer additional choices in a popup menu. The
156 popup menu can be set using setMenu(). Use setPopupMode() to
157 configure the different modes available for tool buttons with a
158 menu set. The default mode is DelayedPopupMode which is sometimes
159 used with the "Back" button in a web browser. After pressing and
160 holding the button down for a while, a menu pops up showing a list
161 of possible pages to jump to. The default delay is 600 ms; you can
162 adjust it with setPopupDelay().
163
164 \table 100%
165 \row \o \inlineimage assistant-toolbar.png Qt Assistant's toolbar with tool buttons
166 \row \o Qt Assistant's toolbar contains tool buttons that are associated
167 with actions used in other parts of the main window.
168 \endtable
169
170 \sa QPushButton, QToolBar, QMainWindow, QAction,
171 {fowler}{GUI Design Handbook: Push Button}
172*/
173
174/*!
175 \fn void QToolButton::triggered(QAction *action)
176
177 This signal is emitted when the given \a action is triggered.
178
179 The action may also be associated with other parts of the user interface,
180 such as menu items and keyboard shortcuts. Sharing actions in this
181 way helps make the user interface more consistent and is often less work
182 to implement.
183*/
184
185/*!
186 Constructs an empty tool button with parent \a
187 parent.
188*/
189QToolButton::QToolButton(QWidget * parent)
190 : QAbstractButton(*new QToolButtonPrivate, parent)
191{
192 Q_D(QToolButton);
193 d->init();
194}
195
196#ifdef QT3_SUPPORT
197/*!
198 Constructs an empty tool button called \a name, with parent \a
199 parent.
200*/
201
202QToolButton::QToolButton(QWidget * parent, const char *name)
203 : QAbstractButton(*new QToolButtonPrivate, parent)
204{
205 Q_D(QToolButton);
206 setObjectName(QString::fromAscii(name));
207 d->init();
208}
209
210/*!
211 Constructs a tool button called \a name, that is a child of \a
212 parent.
213
214 The tool button will display the given \a icon, with its text
215 label and tool tip set to \a textLabel and its status bar message
216 set to \a statusTip. It will be connected to the \a slot in
217 object \a receiver.
218*/
219
220QToolButton::QToolButton(const QIcon& icon, const QString &textLabel,
221 const QString& statusTip,
222 QObject * receiver, const char *slot,
223 QWidget * parent, const char *name)
224 : QAbstractButton(*new QToolButtonPrivate, parent)
225{
226 Q_D(QToolButton);
227 setObjectName(QString::fromAscii(name));
228 d->init();
229 setIcon(icon);
230 setText(textLabel);
231 if (receiver && slot)
232 connect(this, SIGNAL(clicked()), receiver, slot);
233#ifndef QT_NO_TOOLTIP
234 if (!textLabel.isEmpty())
235 setToolTip(textLabel);
236#endif
237#ifndef QT_NO_STATUSTIP
238 if (!statusTip.isEmpty())
239 setStatusTip(statusTip);
240#else
241 Q_UNUSED(statusTip);
242#endif
243}
244
245
246/*!
247 Constructs a tool button as an arrow button. The Qt::ArrowType \a
248 type defines the arrow direction. Possible values are
249 Qt::LeftArrow, Qt::RightArrow, Qt::UpArrow, and Qt::DownArrow.
250
251 An arrow button has auto-repeat turned on by default.
252
253 The \a parent and \a name arguments are sent to the QWidget
254 constructor.
255*/
256QToolButton::QToolButton(Qt::ArrowType type, QWidget *parent, const char *name)
257 : QAbstractButton(*new QToolButtonPrivate, parent)
258{
259 Q_D(QToolButton);
260 setObjectName(QString::fromAscii(name));
261 d->init();
262 setAutoRepeat(true);
263 d->arrowType = type;
264}
265
266#endif
267
268
269/* Set-up code common to all the constructors */
270
271void QToolButtonPrivate::init()
272{
273 Q_Q(QToolButton);
274 delay = q->style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, q);
275#ifdef QT3_SUPPORT
276 userDefinedPopupDelay = false;
277#endif
278 defaultAction = 0;
279#ifndef QT_NO_TOOLBAR
280 if (qobject_cast<QToolBar*>(parent))
281 autoRaise = true;
282 else
283#endif
284 autoRaise = false;
285 arrowType = Qt::NoArrow;
286 menuButtonDown = false;
287 popupMode = QToolButton::DelayedPopup;
288 buttonPressed = QToolButtonPrivate::NoButtonPressed;
289
290 toolButtonStyle = Qt::ToolButtonIconOnly;
291 hoverControl = QStyle::SC_None;
292
293 q->setFocusPolicy(Qt::TabFocus);
294 q->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed,
295 QSizePolicy::ToolButton));
296
297#ifndef QT_NO_MENU
298 QObject::connect(q, SIGNAL(pressed()), q, SLOT(_q_buttonPressed()));
299#endif
300
301 setLayoutItemMargins(QStyle::SE_ToolButtonLayoutItem);
302
303}
304
305/*!
306 Initialize \a option with the values from this QToolButton. This method
307 is useful for subclasses when they need a QStyleOptionToolButton, but don't want
308 to fill in all the information themselves.
309
310 \sa QStyleOption::initFrom()
311*/
312void QToolButton::initStyleOption(QStyleOptionToolButton *option) const
313{
314 if (!option)
315 return;
316
317 Q_D(const QToolButton);
318 option->initFrom(this);
319 bool forceNoText = false;
320 option->iconSize = iconSize(); //default value
321
322#ifndef QT_NO_TOOLBAR
323 if (parentWidget()) {
324 if (QToolBar *toolBar = qobject_cast<QToolBar *>(parentWidget())) {
325 option->iconSize = toolBar->iconSize();
326 }
327#ifdef QT3_SUPPORT
328 else if (parentWidget()->inherits("Q3ToolBar")) {
329 if (!option->iconSize.isValid()) {
330 int iconSize = style()->pixelMetric(QStyle::PM_ToolBarIconSize, option, this);
331 option->iconSize = d->icon.actualSize(QSize(iconSize, iconSize));
332 }
333 forceNoText = d->toolButtonStyle == Qt::ToolButtonIconOnly;
334 }
335#endif
336 }
337#endif // QT_NO_TOOLBAR
338
339 if (!forceNoText)
340 option->text = d->text;
341 option->icon = d->icon;
342 option->arrowType = d->arrowType;
343 if (d->down)
344 option->state |= QStyle::State_Sunken;
345 if (d->checked)
346 option->state |= QStyle::State_On;
347 if (d->autoRaise)
348 option->state |= QStyle::State_AutoRaise;
349 if (!d->checked && !d->down)
350 option->state |= QStyle::State_Raised;
351
352 option->subControls = QStyle::SC_ToolButton;
353 option->activeSubControls = QStyle::SC_None;
354
355 option->features = QStyleOptionToolButton::None;
356 if (d->popupMode == QToolButton::MenuButtonPopup) {
357 option->subControls |= QStyle::SC_ToolButtonMenu;
358 option->features |= QStyleOptionToolButton::MenuButtonPopup;
359 }
360 if (option->state & QStyle::State_MouseOver) {
361 option->activeSubControls = d->hoverControl;
362 }
363 if (d->menuButtonDown) {
364 option->state |= QStyle::State_Sunken;
365 option->activeSubControls |= QStyle::SC_ToolButtonMenu;
366 }
367 if (d->down) {
368 option->state |= QStyle::State_Sunken;
369 option->activeSubControls |= QStyle::SC_ToolButton;
370 }
371
372
373 if (d->arrowType != Qt::NoArrow)
374 option->features |= QStyleOptionToolButton::Arrow;
375 if (d->popupMode == QToolButton::DelayedPopup)
376 option->features |= QStyleOptionToolButton::PopupDelay;
377#ifndef QT_NO_MENU
378 if (d->hasMenu())
379 option->features |= QStyleOptionToolButton::HasMenu;
380#endif
381 if (d->toolButtonStyle == Qt::ToolButtonFollowStyle) {
382 option->toolButtonStyle = Qt::ToolButtonStyle(style()->styleHint(QStyle::SH_ToolButtonStyle, option, this));
383 } else
384 option->toolButtonStyle = d->toolButtonStyle;
385
386 if (option->toolButtonStyle == Qt::ToolButtonTextBesideIcon) {
387 // If the action is not prioritized, remove the text label to save space
388 if (d->defaultAction && d->defaultAction->priority() < QAction::NormalPriority)
389 option->toolButtonStyle = Qt::ToolButtonIconOnly;
390 }
391
392 if (d->icon.isNull() && d->arrowType == Qt::NoArrow && !forceNoText) {
393 if (!d->text.isEmpty())
394 option->toolButtonStyle = Qt::ToolButtonTextOnly;
395 else if (option->toolButtonStyle != Qt::ToolButtonTextOnly)
396 option->toolButtonStyle = Qt::ToolButtonIconOnly;
397 } else {
398 if (d->text.isEmpty() && option->toolButtonStyle != Qt::ToolButtonIconOnly)
399 option->toolButtonStyle = Qt::ToolButtonIconOnly;
400 }
401
402 option->pos = pos();
403 option->font = font();
404}
405
406/*!
407 Destroys the object and frees any allocated resources.
408*/
409
410QToolButton::~QToolButton()
411{
412}
413
414/*!
415 \reimp
416*/
417QSize QToolButton::sizeHint() const
418{
419 Q_D(const QToolButton);
420 if (d->sizeHint.isValid())
421 return d->sizeHint;
422 ensurePolished();
423
424 int w = 0, h = 0;
425 QStyleOptionToolButton opt;
426 initStyleOption(&opt);
427
428 QFontMetrics fm = fontMetrics();
429 if (opt.toolButtonStyle != Qt::ToolButtonTextOnly) {
430 QSize icon = opt.iconSize;
431 w = icon.width();
432 h = icon.height();
433 }
434
435 if (opt.toolButtonStyle != Qt::ToolButtonIconOnly) {
436 QSize textSize = fm.size(Qt::TextShowMnemonic, text());
437 textSize.setWidth(textSize.width() + fm.width(QLatin1Char(' '))*2);
438 if (opt.toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
439 h += 4 + textSize.height();
440 if (textSize.width() > w)
441 w = textSize.width();
442 } else if (opt.toolButtonStyle == Qt::ToolButtonTextBesideIcon) {
443 w += 4 + textSize.width();
444 if (textSize.height() > h)
445 h = textSize.height();
446 } else { // TextOnly
447 w = textSize.width();
448 h = textSize.height();
449 }
450 }
451
452 opt.rect.setSize(QSize(w, h)); // PM_MenuButtonIndicator depends on the height
453 if (d->popupMode == MenuButtonPopup)
454 w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this);
455
456 d->sizeHint = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(w, h), this).
457 expandedTo(QApplication::globalStrut());
458 return d->sizeHint;
459}
460
461/*!
462 \reimp
463 */
464QSize QToolButton::minimumSizeHint() const
465{
466 return sizeHint();
467}
468
469/*!
470 \enum QToolButton::TextPosition
471 \compat
472
473 This enum describes the position of the tool button's text label in
474 relation to the tool button's icon.
475
476 \value BesideIcon The text appears beside the icon.
477 \value BelowIcon The text appears below the icon.
478 \omitvalue Right
479 \omitvalue Under
480*/
481
482/*!
483 \property QToolButton::toolButtonStyle
484 \brief whether the tool button displays an icon only, text only,
485 or text beside/below the icon.
486
487 The default is Qt::ToolButtonIconOnly.
488
489 To have the style of toolbuttons follow the system settings (as available
490 in GNOME and KDE desktop environments), set this property to Qt::ToolButtonFollowStyle.
491
492 QToolButton automatically connects this slot to the relevant
493 signal in the QMainWindow in which is resides.
494*/
495
496/*!
497 \property QToolButton::arrowType
498 \brief whether the button displays an arrow instead of a normal icon
499
500 This displays an arrow as the icon for the QToolButton.
501
502 By default, this property is set to Qt::NoArrow.
503*/
504
505Qt::ToolButtonStyle QToolButton::toolButtonStyle() const
506{
507 Q_D(const QToolButton);
508 return d->toolButtonStyle;
509}
510
511Qt::ArrowType QToolButton::arrowType() const
512{
513 Q_D(const QToolButton);
514 return d->arrowType;
515}
516
517
518void QToolButton::setToolButtonStyle(Qt::ToolButtonStyle style)
519{
520 Q_D(QToolButton);
521 if (d->toolButtonStyle == style)
522 return;
523
524 d->toolButtonStyle = style;
525 d->sizeHint = QSize();
526 updateGeometry();
527 if (isVisible()) {
528 update();
529 }
530}
531
532void QToolButton::setArrowType(Qt::ArrowType type)
533{
534 Q_D(QToolButton);
535 if (d->arrowType == type)
536 return;
537
538 d->arrowType = type;
539 d->sizeHint = QSize();
540 updateGeometry();
541 if (isVisible()) {
542 update();
543 }
544}
545
546/*!
547 \fn void QToolButton::paintEvent(QPaintEvent *event)
548
549 Paints the button in response to the paint \a event.
550*/
551void QToolButton::paintEvent(QPaintEvent *)
552{
553 QStylePainter p(this);
554 QStyleOptionToolButton opt;
555 initStyleOption(&opt);
556 p.drawComplexControl(QStyle::CC_ToolButton, opt);
557}
558
559/*!
560 \reimp
561 */
562void QToolButton::actionEvent(QActionEvent *event)
563{
564 Q_D(QToolButton);
565 QAction *action = event->action();
566 switch (event->type()) {
567 case QEvent::ActionChanged:
568 if (action == d->defaultAction)
569 setDefaultAction(action); // update button state
570 break;
571 case QEvent::ActionAdded:
572 connect(action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
573 break;
574 case QEvent::ActionRemoved:
575 if (d->defaultAction == action)
576 d->defaultAction = 0;
577#ifndef QT_NO_MENU
578 if (action == d->menuAction)
579 d->menuAction = 0;
580#endif
581 action->disconnect(this);
582 break;
583 default:
584 ;
585 }
586 QAbstractButton::actionEvent(event);
587}
588
589QStyle::SubControl QToolButtonPrivate::newHoverControl(const QPoint &pos)
590{
591 Q_Q(QToolButton);
592 QStyleOptionToolButton opt;
593 q->initStyleOption(&opt);
594 opt.subControls = QStyle::SC_All;
595 hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ToolButton, &opt, pos, q);
596 if (hoverControl == QStyle::SC_None)
597 hoverRect = QRect();
598 else
599 hoverRect = q->style()->subControlRect(QStyle::CC_ToolButton, &opt, hoverControl, q);
600 return hoverControl;
601}
602
603bool QToolButtonPrivate::updateHoverControl(const QPoint &pos)
604{
605 Q_Q(QToolButton);
606 QRect lastHoverRect = hoverRect;
607 QStyle::SubControl lastHoverControl = hoverControl;
608 bool doesHover = q->testAttribute(Qt::WA_Hover);
609 if (lastHoverControl != newHoverControl(pos) && doesHover) {
610 q->update(lastHoverRect);
611 q->update(hoverRect);
612 return true;
613 }
614 return !doesHover;
615}
616
617void QToolButtonPrivate::_q_actionTriggered()
618{
619 Q_Q(QToolButton);
620 if (QAction *action = qobject_cast<QAction *>(q->sender()))
621 emit q->triggered(action);
622}
623
624/*!
625 \reimp
626 */
627void QToolButton::enterEvent(QEvent * e)
628{
629 Q_D(QToolButton);
630 if (d->autoRaise)
631 update();
632 if (d->defaultAction)
633 d->defaultAction->hover();
634 QAbstractButton::enterEvent(e);
635}
636
637
638/*!
639 \reimp
640 */
641void QToolButton::leaveEvent(QEvent * e)
642{
643 Q_D(QToolButton);
644 if (d->autoRaise)
645 update();
646
647 QAbstractButton::leaveEvent(e);
648}
649
650
651/*!
652 \reimp
653 */
654void QToolButton::timerEvent(QTimerEvent *e)
655{
656#ifndef QT_NO_MENU
657 Q_D(QToolButton);
658 if (e->timerId() == d->popupTimer.timerId()) {
659 d->popupTimerDone();
660 return;
661 }
662#endif
663 QAbstractButton::timerEvent(e);
664}
665
666
667/*!
668 \reimp
669*/
670void QToolButton::changeEvent(QEvent *e)
671{
672#ifndef QT_NO_TOOLBAR
673 Q_D(QToolButton);
674 if (e->type() == QEvent::ParentChange) {
675 if (qobject_cast<QToolBar*>(parentWidget()))
676 d->autoRaise = true;
677 } else if (e->type() == QEvent::StyleChange
678#ifdef Q_WS_MAC
679 || e->type() == QEvent::MacSizeChange
680#endif
681 ) {
682#ifdef QT3_SUPPORT
683 if (!d->userDefinedPopupDelay)
684#endif
685 d->delay = style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, this);
686 d->setLayoutItemMargins(QStyle::SE_ToolButtonLayoutItem);
687 }
688#endif
689 QAbstractButton::changeEvent(e);
690}
691
692/*!
693 \reimp
694*/
695void QToolButton::mousePressEvent(QMouseEvent *e)
696{
697 Q_D(QToolButton);
698#ifndef QT_NO_MENU
699 QStyleOptionToolButton opt;
700 initStyleOption(&opt);
701 if (e->button() == Qt::LeftButton && (d->popupMode == MenuButtonPopup)) {
702 QRect popupr = style()->subControlRect(QStyle::CC_ToolButton, &opt,
703 QStyle::SC_ToolButtonMenu, this);
704 if (popupr.isValid() && popupr.contains(e->pos())) {
705 d->buttonPressed = QToolButtonPrivate::MenuButtonPressed;
706 showMenu();
707 return;
708 }
709 }
710#endif
711 d->buttonPressed = QToolButtonPrivate::ToolButtonPressed;
712 QAbstractButton::mousePressEvent(e);
713}
714
715/*!
716 \reimp
717*/
718void QToolButton::mouseReleaseEvent(QMouseEvent *e)
719{
720 Q_D(QToolButton);
721 QAbstractButton::mouseReleaseEvent(e);
722 d->buttonPressed = QToolButtonPrivate::NoButtonPressed;
723}
724
725/*!
726 \reimp
727*/
728bool QToolButton::hitButton(const QPoint &pos) const
729{
730 Q_D(const QToolButton);
731 if(QAbstractButton::hitButton(pos))
732 return (d->buttonPressed != QToolButtonPrivate::MenuButtonPressed);
733 return false;
734}
735
736#ifdef QT3_SUPPORT
737
738/*!
739 Use icon() instead.
740*/
741QIcon QToolButton::onIconSet() const
742{
743 return icon();
744}
745
746/*!
747 Use icon() instead.
748*/
749QIcon QToolButton::offIconSet() const
750{
751 return icon();
752}
753
754
755/*!
756 \obsolete
757
758 Use setIcon() instead.
759*/
760void QToolButton::setOnIconSet(const QIcon& set)
761{
762 setIcon(set);
763}
764
765/*!
766 \obsolete
767
768 Use setIcon() instead.
769*/
770void QToolButton::setOffIconSet(const QIcon& set)
771{
772 setIcon(set);
773}
774
775
776/*! \overload
777 \obsolete
778
779 Since Qt 3.0, QIcon contains both the On and Off icons.
780
781 For ease of porting, this function ignores the \a on parameter and
782 sets the \l{QAbstractButton::icon} {icon} property. If you relied on
783 the \a on parameter, you probably want to update your code to use
784 the QIcon On/Off mechanism.
785
786 \sa icon QIcon::State
787*/
788
789void QToolButton::setIconSet(const QIcon & set, bool /* on */)
790{
791 QAbstractButton::setIcon(set);
792}
793
794/*! \overload
795 \obsolete
796
797 Since Qt 3.0, QIcon contains both the On and Off icons.
798
799 For ease of porting, this function ignores the \a on parameter and
800 returns the \l{QAbstractButton::icon} {icon} property. If you relied
801 on the \a on parameter, you probably want to update your code to use
802 the QIcon On/Off mechanism.
803*/
804QIcon QToolButton::iconSet(bool /* on */) const
805{
806 return QAbstractButton::icon();
807}
808
809#endif
810
811#ifndef QT_NO_MENU
812/*!
813 Associates the given \a menu with this tool button.
814
815 The menu will be shown according to the button's \l popupMode.
816
817 Ownership of the menu is not transferred to the tool button.
818
819 \sa menu()
820*/
821void QToolButton::setMenu(QMenu* menu)
822{
823 Q_D(QToolButton);
824
825 if (d->menuAction)
826 removeAction(d->menuAction);
827
828 if (menu) {
829 d->menuAction = menu->menuAction();
830 addAction(d->menuAction);
831 } else {
832 d->menuAction = 0;
833 }
834 update();
835}
836
837/*!
838 Returns the associated menu, or 0 if no menu has been defined.
839
840 \sa setMenu()
841*/
842QMenu* QToolButton::menu() const
843{
844 Q_D(const QToolButton);
845 if (d->menuAction)
846 return d->menuAction->menu();
847 return 0;
848}
849
850/*!
851 Shows (pops up) the associated popup menu. If there is no such
852 menu, this function does nothing. This function does not return
853 until the popup menu has been closed by the user.
854*/
855void QToolButton::showMenu()
856{
857 Q_D(QToolButton);
858 if (!d->hasMenu()) {
859 d->menuButtonDown = false;
860 return; // no menu to show
861 }
862
863 d->menuButtonDown = true;
864 repaint();
865 d->popupTimer.stop();
866 d->popupTimerDone();
867}
868
869void QToolButtonPrivate::_q_buttonPressed()
870{
871 Q_Q(QToolButton);
872 if (!hasMenu())
873 return; // no menu to show
874 if (popupMode == QToolButton::MenuButtonPopup)
875 return;
876 else if (delay > 0 && !popupTimer.isActive() && popupMode == QToolButton::DelayedPopup)
877 popupTimer.start(delay, q);
878 else if (delay == 0 || popupMode == QToolButton::InstantPopup)
879 q->showMenu();
880}
881
882void QToolButtonPrivate::popupTimerDone()
883{
884 Q_Q(QToolButton);
885 popupTimer.stop();
886 if (!menuButtonDown && !down)
887 return;
888
889 menuButtonDown = true;
890 QPointer<QMenu> actualMenu;
891 bool mustDeleteActualMenu = false;
892 if(menuAction) {
893 actualMenu = menuAction->menu();
894 } else if (defaultAction && defaultAction->menu()) {
895 actualMenu = defaultAction->menu();
896 } else {
897 actualMenu = new QMenu(q);
898 mustDeleteActualMenu = true;
899 for(int i = 0; i < actions.size(); i++)
900 actualMenu->addAction(actions.at(i));
901 }
902 repeat = q->autoRepeat();
903 q->setAutoRepeat(false);
904 bool horizontal = true;
905#if !defined(QT_NO_TOOLBAR)
906 QToolBar *tb = qobject_cast<QToolBar*>(parent);
907 if (tb && tb->orientation() == Qt::Vertical)
908 horizontal = false;
909#endif
910 QPoint p;
911 QRect screen = QApplication::desktop()->availableGeometry(q);
912 QSize sh = ((QToolButton*)(QMenu*)actualMenu)->receivers(SIGNAL(aboutToShow()))? QSize() : actualMenu->sizeHint();
913 QRect rect = q->rect();
914 if (horizontal) {