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

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

trunk: Merged in qt 4.6.2 sources.

File size: 33.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 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) {
915 if (q->isRightToLeft()) {
916 if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) {
917 p = q->mapToGlobal(rect.bottomRight());
918 } else {
919 p = q->mapToGlobal(rect.topRight() - QPoint(0, sh.height()));
920 }
921 p.rx() -= sh.width();
922 } else {
923 if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) {
924 p = q->mapToGlobal(rect.bottomLeft());
925 } else {
926 p = q->mapToGlobal(rect.topLeft() - QPoint(0, sh.height()));
927 }
928 }
929 } else {
930 if (q->isRightToLeft()) {
931 if (q->mapToGlobal(QPoint(rect.left(), 0)).x() - sh.width() <= screen.x()) {
932 p = q->mapToGlobal(rect.topRight());
933 } else {
934 p = q->mapToGlobal(rect.topLeft());
935 p.rx() -= sh.width();
936 }
937 } else {
938 if (q->mapToGlobal(QPoint(rect.right(), 0)).x() + sh.width() <= screen.right()) {
939 p = q->mapToGlobal(rect.topRight());
940 } else {
941 p = q->mapToGlobal(rect.topLeft() - QPoint(sh.width(), 0));
942 }
943 }
944 }
945 p.rx() = qMax(screen.left(), qMin(p.x(), screen.right() - sh.width()));
946 p.ry() += 1;
947 QPointer<QToolButton> that = q;
948 actualMenu->setNoReplayFor(q);
949 if (!mustDeleteActualMenu) //only if action are not in this widget
950 QObject::connect(actualMenu, SIGNAL(triggered(QAction*)), q, SLOT(_q_menuTriggered(QAction*)));
951 QObject::connect(actualMenu, SIGNAL(aboutToHide()), q, SLOT(_q_updateButtonDown()));
952 actualMenu->d_func()->causedPopup.widget = q;
953 actualMenu->d_func()->causedPopup.action = defaultAction;
954 actionsCopy = q->actions(); //(the list of action may be modified in slots)
955 actualMenu->exec(p);
956 QObject::disconnect(actualMenu, SIGNAL(aboutToHide()), q, SLOT(_q_updateButtonDown()));
957 if (mustDeleteActualMenu)
958 delete actualMenu;
959 else
960 QObject::disconnect(actualMenu, SIGNAL(triggered(QAction*)), q, SLOT(_q_menuTriggered(QAction*)));
961
962 if (!that)
963 return;
964
965 actionsCopy.clear();
966
967 if (repeat)
968 q->setAutoRepeat(true);
969}
970
971void QToolButtonPrivate::_q_updateButtonDown()
972{
973 Q_Q(QToolButton);
974 menuButtonDown = false;
975 if (q->isDown())
976 q->setDown(false);
977 else
978 q->repaint();
979}
980
981void QToolButtonPrivate::_q_menuTriggered(QAction *action)
982{
983 Q_Q(QToolButton);
984 if (action && !actionsCopy.contains(action))
985 emit q->triggered(action);
986}
987#endif // QT_NO_MENU
988
989#ifdef QT3_SUPPORT
990/*!
991 \fn void QToolButton::setPopupDelay(int delay)
992
993 Use the style hint QStyle::SH_ToolButton_PopupDelay instead.
994*/
995void QToolButton::setPopupDelay(int delay)
996{
997 Q_D(QToolButton);
998 d->userDefinedPopupDelay = true;
999 d->delay = delay;
1000
1001 update();
1002}
1003
1004/*!
1005 Use the style hint QStyle::SH_ToolButton_PopupDelay instead.
1006*/
1007int QToolButton::popupDelay() const
1008{
1009 Q_D(const QToolButton);
1010 return d->delay;
1011}
1012#endif
1013
1014#ifndef QT_NO_MENU
1015/*! \enum QToolButton::ToolButtonPopupMode
1016
1017 Describes how a menu should be popped up for tool buttons that has
1018 a menu set or contains a list of actions.
1019
1020 \value DelayedPopup After pressing and holding the tool button
1021 down for a certain amount of time (the timeout is style dependant,
1022 see QStyle::SH_ToolButton_PopupDelay), the menu is displayed. A
1023 typical application example is the "back" button in some web
1024 browsers's tool bars. If the user clicks it, the browser simply
1025 browses back to the previous page. If the user presses and holds
1026 the button down for a while, the tool button shows a menu
1027 containing the current history list
1028
1029 \value MenuButtonPopup In this mode the tool button displays a
1030 special arrow to indicate that a menu is present. The menu is
1031 displayed when the arrow part of the button is pressed.
1032
1033 \value InstantPopup The menu is displayed, without delay, when
1034 the tool button is pressed. In this mode, the button's own action
1035 is not triggered.
1036*/
1037
1038/*!
1039 \property QToolButton::popupMode
1040 \brief describes the way that popup menus are used with tool buttons
1041
1042 By default, this property is set to \l DelayedPopup.
1043*/
1044
1045void QToolButton::setPopupMode(ToolButtonPopupMode mode)
1046{
1047 Q_D(QToolButton);
1048 d->popupMode = mode;
1049}
1050
1051QToolButton::ToolButtonPopupMode QToolButton::popupMode() const
1052{
1053 Q_D(const QToolButton);
1054 return d->popupMode;
1055}
1056#endif
1057
1058/*!
1059 \property QToolButton::autoRaise
1060 \brief whether auto-raising is enabled or not.
1061
1062 The default is disabled (i.e. false).
1063
1064 This property is currently ignored on Mac OS X when using QMacStyle.
1065*/
1066void QToolButton::setAutoRaise(bool enable)
1067{
1068 Q_D(QToolButton);
1069 d->autoRaise = enable;
1070
1071 update();
1072}
1073
1074bool QToolButton::autoRaise() const
1075{
1076 Q_D(const QToolButton);
1077 return d->autoRaise;
1078}
1079
1080/*!
1081 Sets the default action to \a action.
1082
1083 If a tool button has a default action, the action defines the
1084 button's properties like text, icon, tool tip, etc.
1085 */
1086void QToolButton::setDefaultAction(QAction *action)
1087{
1088 Q_D(QToolButton);
1089#ifndef QT_NO_MENU
1090 bool hadMenu = false;
1091 hadMenu = d->hasMenu();
1092#endif
1093 d->defaultAction = action;
1094 if (!action)
1095 return;
1096 if (!actions().contains(action))
1097 addAction(action);
1098 setText(action->iconText());
1099 setIcon(action->icon());
1100#ifndef QT_NO_TOOLTIP
1101 setToolTip(action->toolTip());
1102#endif
1103#ifndef QT_NO_STATUSTIP
1104 setStatusTip(action->statusTip());
1105#endif
1106#ifndef QT_NO_WHATSTHIS
1107 setWhatsThis(action->whatsThis());
1108#endif
1109#ifndef QT_NO_MENU
1110 if (action->menu() && !hadMenu) {
1111 // new 'default' popup mode defined introduced by tool bar. We
1112 // should have changed QToolButton's default instead. Do that
1113 // in 4.2.
1114 setPopupMode(QToolButton::MenuButtonPopup);
1115 }
1116#endif
1117 setCheckable(action->isCheckable());
1118 setChecked(action->isChecked());
1119 setEnabled(action->isEnabled());
1120 if (action->d_func()->fontSet)
1121 setFont(action->font());
1122}
1123
1124
1125/*!
1126 Returns the default action.
1127
1128 \sa setDefaultAction()
1129 */
1130QAction *QToolButton::defaultAction() const
1131{
1132 Q_D(const QToolButton);
1133 return d->defaultAction;
1134}
1135
1136
1137
1138/*!
1139 \reimp
1140 */
1141void QToolButton::nextCheckState()
1142{
1143 Q_D(QToolButton);
1144 if (!d->defaultAction)
1145 QAbstractButton::nextCheckState();
1146 else
1147 d->defaultAction->trigger();
1148}
1149
1150/*! \reimp */
1151bool QToolButton::event(QEvent *event)
1152{
1153 switch(event->type()) {
1154 case QEvent::HoverEnter:
1155 case QEvent::HoverLeave:
1156 case QEvent::HoverMove:
1157 if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
1158 d_func()->updateHoverControl(he->pos());
1159 break;
1160 default:
1161 break;
1162 }
1163 return QAbstractButton::event(event);
1164}
1165
1166/*! \internal
1167 */
1168QToolButton::QToolButton(QToolButtonPrivate &dd, QWidget *parent)
1169 :QAbstractButton(dd, parent)
1170{
1171 Q_D(QToolButton);
1172 d->init();
1173}
1174
1175/*!
1176 \fn void QToolButton::setPixmap(const QPixmap &pixmap)
1177
1178 Use setIcon(QIcon(pixmap)) instead.
1179*/
1180
1181/*!
1182 \fn void QToolButton::setIconSet(const QIcon &icon)
1183
1184 Use setIcon() instead.
1185*/
1186
1187/*!
1188 \fn void QToolButton::setTextLabel(const QString &text, bool tooltip)
1189
1190 Use setText() and setToolTip() instead.
1191*/
1192
1193/*!
1194 \fn QString QToolButton::textLabel() const
1195
1196 Use text() instead.
1197*/
1198
1199/*!
1200 \fn QIcon QToolButton::iconSet() const
1201
1202 Use icon() instead.
1203*/
1204
1205/*!
1206 \fn void QToolButton::openPopup()
1207
1208 Use showMenu() instead.
1209*/
1210
1211/*!
1212 \fn void QToolButton::setPopup(QMenu* popup)
1213
1214 Use setMenu() instead.
1215*/
1216
1217/*!
1218 \fn QMenu* QToolButton::popup() const
1219
1220 Use menu() instead.
1221*/
1222
1223/*!
1224 \fn TextPosition QToolButton::textPosition() const
1225
1226 Use toolButtonStyle() instead.
1227*/
1228
1229/*!
1230 \fn void QToolButton::setTextPosition(QToolButton::TextPosition pos)
1231
1232 Use setToolButtonStyle() instead.
1233*/
1234
1235/*!
1236 \fn bool QToolButton::usesBigPixmap() const
1237
1238 Use iconSize() instead.
1239*/
1240
1241/*!
1242 \fn void QToolButton::setUsesBigPixmap(bool enable)
1243
1244 Use setIconSize() instead.
1245*/
1246
1247/*!
1248 \fn bool QToolButton::usesTextLabel() const
1249
1250 Use toolButtonStyle() instead.
1251*/
1252
1253/*!
1254 \fn void QToolButton::setUsesTextLabel(bool enable)
1255
1256 Use setToolButtonStyle() instead.
1257*/
1258
1259QT_END_NAMESPACE
1260
1261#include "moc_qtoolbutton.cpp"
1262
1263#endif
Note: See TracBrowser for help on using the repository browser.