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

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

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

File size: 32.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 "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 Q_Q(const QToolButton);
108 return ((defaultAction && defaultAction->menu())
109 || (menuAction && menuAction->menu())
110 || q->actions().size() > (defaultAction ? 1 : 0));
111}
112#endif
113
114/*!
115 \class QToolButton
116 \brief The QToolButton class provides a quick-access button to
117 commands or options, usually used inside a QToolBar.
118
119 \ingroup basicwidgets
120 \mainclass
121
122 A tool button is a special button that provides quick-access to
123 specific commands or options. As opposed to a normal command
124 button, a tool button usually doesn't show a text label, but shows
125 an icon instead.
126
127 Tool buttons are normally created when new QAction instances are
128 created with QToolBar::addAction() or existing actions are added
129 to a toolbar with QToolBar::addAction(). It is also possible to
130 construct tool buttons in the same way as any other widget, and
131 arrange them alongside other widgets in layouts.
132
133 One classic use of a tool button is to select tools; for example,
134 the "pen" tool in a drawing program. This would be implemented
135 by using a QToolButton as a toggle button (see setToggleButton()).
136
137 QToolButton supports auto-raising. In auto-raise mode, the button
138 draws a 3D frame only when the mouse points at it. The feature is
139 automatically turned on when a button is used inside a QToolBar.
140 Change it with setAutoRaise().
141
142 A tool button's icon is set as QIcon. This makes it possible to
143 specify different pixmaps for the disabled and active state. The
144 disabled pixmap is used when the button's functionality is not
145 available. The active pixmap is displayed when the button is
146 auto-raised because the mouse pointer is hovering over it.
147
148 The button's look and dimension is adjustable with
149 setToolButtonStyle() and setIconSize(). When used inside a
150 QToolBar in a QMainWindow, the button automatically adjusts to
151 QMainWindow's settings (see QMainWindow::setToolButtonStyle() and
152 QMainWindow::setIconSize()). Instead of an icon, a tool button can
153 also display an arrow symbol, specified with
154 \l{QToolButton::arrowType} {arrowType}.
155
156 A tool button can offer additional choices in a popup menu. The
157 popup menu can be set using setMenu(). Use setPopupMode() to
158 configure the different modes available for tool buttons with a
159 menu set. The default mode is DelayedPopupMode which is sometimes
160 used with the "Back" button in a web browser. After pressing and
161 holding the button down for a while, a menu pops up showing a list
162 of possible pages to jump to. The default delay is 600 ms; you can
163 adjust it with setPopupDelay().
164
165 \table 100%
166 \row \o \inlineimage assistant-toolbar.png Qt Assistant's toolbar with tool buttons
167 \row \o Qt Assistant's toolbar contains tool buttons that are associated
168 with actions used in other parts of the main window.
169 \endtable
170
171 \sa QPushButton, QToolBar, QMainWindow, QAction,
172 {fowler}{GUI Design Handbook: Push Button}
173*/
174
175/*!
176 \fn void QToolButton::triggered(QAction *action)
177
178 This signal is emitted when the given \a action is triggered.
179
180 The action may also be associated with other parts of the user interface,
181 such as menu items and keyboard shortcuts. Sharing actions in this
182 way helps make the user interface more consistent and is often less work
183 to implement.
184*/
185
186/*!
187 Constructs an empty tool button with parent \a
188 parent.
189*/
190QToolButton::QToolButton(QWidget * parent)
191 : QAbstractButton(*new QToolButtonPrivate, parent)
192{
193 Q_D(QToolButton);
194 d->init();
195}
196
197#ifdef QT3_SUPPORT
198/*!
199 Constructs an empty tool button called \a name, with parent \a
200 parent.
201*/
202
203QToolButton::QToolButton(QWidget * parent, const char *name)
204 : QAbstractButton(*new QToolButtonPrivate, parent)
205{
206 Q_D(QToolButton);
207 setObjectName(QString::fromAscii(name));
208 d->init();
209}
210
211/*!
212 Constructs a tool button called \a name, that is a child of \a
213 parent.
214
215 The tool button will display the given \a icon, with its text
216 label and tool tip set to \a textLabel and its status bar message
217 set to \a statusTip. It will be connected to the \a slot in
218 object \a receiver.
219*/
220
221QToolButton::QToolButton(const QIcon& icon, const QString &textLabel,
222 const QString& statusTip,
223 QObject * receiver, const char *slot,
224 QWidget * parent, const char *name)
225 : QAbstractButton(*new QToolButtonPrivate, parent)
226{
227 Q_D(QToolButton);
228 setObjectName(QString::fromAscii(name));
229 d->init();
230 setIcon(icon);
231 setText(textLabel);
232 if (receiver && slot)
233 connect(this, SIGNAL(clicked()), receiver, slot);
234#ifndef QT_NO_TOOLTIP
235 if (!textLabel.isEmpty())
236 setToolTip(textLabel);
237#endif
238#ifndef QT_NO_STATUSTIP
239 if (!statusTip.isEmpty())
240 setStatusTip(statusTip);
241#else
242 Q_UNUSED(statusTip);
243#endif
244}
245
246
247/*!
248 Constructs a tool button as an arrow button. The Qt::ArrowType \a
249 type defines the arrow direction. Possible values are
250 Qt::LeftArrow, Qt::RightArrow, Qt::UpArrow, and Qt::DownArrow.
251
252 An arrow button has auto-repeat turned on by default.
253
254 The \a parent and \a name arguments are sent to the QWidget
255 constructor.
256*/
257QToolButton::QToolButton(Qt::ArrowType type, QWidget *parent, const char *name)
258 : QAbstractButton(*new QToolButtonPrivate, parent)
259{
260 Q_D(QToolButton);
261 setObjectName(QString::fromAscii(name));
262 d->init();
263 setAutoRepeat(true);
264 d->arrowType = type;
265}
266
267#endif
268
269
270/* Set-up code common to all the constructors */
271
272void QToolButtonPrivate::init()
273{
274 Q_Q(QToolButton);
275 delay = q->style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, q);
276#ifdef QT3_SUPPORT
277 userDefinedPopupDelay = false;
278#endif
279 defaultAction = 0;
280#ifndef QT_NO_TOOLBAR
281 if (qobject_cast<QToolBar*>(q->parentWidget()))
282 autoRaise = true;
283 else
284#endif
285 autoRaise = false;
286 arrowType = Qt::NoArrow;
287 menuButtonDown = false;
288 popupMode = QToolButton::DelayedPopup;
289 buttonPressed = QToolButtonPrivate::NoButtonPressed;
290
291 toolButtonStyle = Qt::ToolButtonIconOnly;
292 hoverControl = QStyle::SC_None;
293
294 q->setFocusPolicy(Qt::TabFocus);
295 q->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed,
296 QSizePolicy::ToolButton));
297
298#ifndef QT_NO_MENU
299 QObject::connect(q, SIGNAL(pressed()), q, SLOT(_q_buttonPressed()));
300#endif
301
302 setLayoutItemMargins(QStyle::SE_ToolButtonLayoutItem);
303
304}
305
306/*!
307 Initialize \a option with the values from this QToolButton. This method
308 is useful for subclasses when they need a QStyleOptionToolButton, but don't want
309 to fill in all the information themselves.
310
311 \sa QStyleOption::initFrom()
312*/
313void QToolButton::initStyleOption(QStyleOptionToolButton *option) const
314{
315 if (!option)
316 return;
317
318 Q_D(const QToolButton);
319 option->initFrom(this);
320 bool forceNoText = false;
321 option->iconSize = iconSize(); //default value
322
323#ifndef QT_NO_TOOLBAR
324 if (parentWidget()) {
325 if (QToolBar *toolBar = qobject_cast<QToolBar *>(parentWidget())) {
326 option->iconSize = toolBar->iconSize();
327 }
328#ifdef QT3_SUPPORT
329 else if (parentWidget()->inherits("Q3ToolBar")) {
330 if (!option->iconSize.isValid()) {
331 int iconSize = style()->pixelMetric(QStyle::PM_ToolBarIconSize, option, this);
332 option->iconSize = d->icon.actualSize(QSize(iconSize, iconSize));
333 }
334 forceNoText = d->toolButtonStyle == Qt::ToolButtonIconOnly;
335 }
336#endif
337 }
338#endif // QT_NO_TOOLBAR
339
340 if (!forceNoText)
341 option->text = d->text;
342 option->icon = d->icon;
343 option->arrowType = d->arrowType;
344 if (d->down)
345 option->state |= QStyle::State_Sunken;
346 if (d->checked)
347 option->state |= QStyle::State_On;
348 if (d->autoRaise)
349 option->state |= QStyle::State_AutoRaise;
350 if (!d->checked && !d->down)
351 option->state |= QStyle::State_Raised;
352
353 option->subControls = QStyle::SC_ToolButton;
354 option->activeSubControls = QStyle::SC_None;
355
356 option->features = QStyleOptionToolButton::None;
357 if (d->popupMode == QToolButton::MenuButtonPopup) {
358 option->subControls |= QStyle::SC_ToolButtonMenu;
359 option->features |= QStyleOptionToolButton::MenuButtonPopup;
360 }
361 if (option->state & QStyle::State_MouseOver) {
362 option->activeSubControls = d->hoverControl;
363 }
364 if (d->menuButtonDown) {
365 option->state |= QStyle::State_Sunken;
366 option->activeSubControls |= QStyle::SC_ToolButtonMenu;
367 }
368 if (d->down) {
369 option->state |= QStyle::State_Sunken;
370 option->activeSubControls |= QStyle::SC_ToolButton;
371 }
372
373
374 if (d->arrowType != Qt::NoArrow)
375 option->features |= QStyleOptionToolButton::Arrow;
376 if (d->popupMode == QToolButton::DelayedPopup)
377 option->features |= QStyleOptionToolButton::PopupDelay;
378#ifndef QT_NO_MENU
379 if (d->hasMenu())
380 option->features |= QStyleOptionToolButton::HasMenu;
381#endif
382 option->toolButtonStyle = d->toolButtonStyle;
383 if (d->icon.isNull() && d->arrowType == Qt::NoArrow && !forceNoText) {
384 if (!d->text.isEmpty())
385 option->toolButtonStyle = Qt::ToolButtonTextOnly;
386 else if (option->toolButtonStyle != Qt::ToolButtonTextOnly)
387 option->toolButtonStyle = Qt::ToolButtonIconOnly;
388 } else {
389 if (d->text.isEmpty() && option->toolButtonStyle != Qt::ToolButtonIconOnly)
390 option->toolButtonStyle = Qt::ToolButtonIconOnly;
391 }
392
393 option->pos = pos();
394 option->font = font();
395}
396
397/*!
398 Destroys the object and frees any allocated resources.
399*/
400
401QToolButton::~QToolButton()
402{
403}
404
405/*!
406 \reimp
407*/
408QSize QToolButton::sizeHint() const
409{
410 Q_D(const QToolButton);
411 if (d->sizeHint.isValid())
412 return d->sizeHint;
413 ensurePolished();
414
415 int w = 0, h = 0;
416 QStyleOptionToolButton opt;
417 initStyleOption(&opt);
418
419 QFontMetrics fm = fontMetrics();
420 if (opt.toolButtonStyle != Qt::ToolButtonTextOnly) {
421 QSize icon = opt.iconSize;
422 w = icon.width();
423 h = icon.height();
424 }
425
426 if (opt.toolButtonStyle != Qt::ToolButtonIconOnly) {
427 QSize textSize = fm.size(Qt::TextShowMnemonic, text());
428 textSize.setWidth(textSize.width() + fm.width(QLatin1Char(' '))*2);
429 if (opt.toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
430 h += 4 + textSize.height();
431 if (textSize.width() > w)
432 w = textSize.width();
433 } else if (opt.toolButtonStyle == Qt::ToolButtonTextBesideIcon) {
434 w += 4 + textSize.width();
435 if (textSize.height() > h)
436 h = textSize.height();
437 } else { // TextOnly
438 w = textSize.width();
439 h = textSize.height();
440 }
441 }
442
443 opt.rect.setSize(QSize(w, h)); // PM_MenuButtonIndicator depends on the height
444 if (d->popupMode == MenuButtonPopup)
445 w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this);
446
447 d->sizeHint = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(w, h), this).
448 expandedTo(QApplication::globalStrut());
449 return d->sizeHint;
450}
451
452/*!
453 \reimp
454 */
455QSize QToolButton::minimumSizeHint() const
456{
457 return sizeHint();
458}
459
460/*!
461 \enum QToolButton::TextPosition
462 \compat
463
464 This enum describes the position of the tool button's text label in
465 relation to the tool button's icon.
466
467 \value BesideIcon The text appears beside the icon.
468 \value BelowIcon The text appears below the icon.
469 \omitvalue Right
470 \omitvalue Under
471*/
472
473/*!
474 \property QToolButton::toolButtonStyle
475 \brief whether the tool button displays an icon only, text only,
476 or text beside/below the icon.
477
478 The default is Qt::ToolButtonIconOnly.
479
480 QToolButton automatically connects this slot to the relevant
481 signal in the QMainWindow in which is resides.
482*/
483
484/*!
485 \property QToolButton::arrowType
486 \brief whether the button displays an arrow instead of a normal icon
487
488 This displays an arrow as the icon for the QToolButton.
489
490 By default, this property is set to Qt::NoArrow.
491*/
492
493Qt::ToolButtonStyle QToolButton::toolButtonStyle() const
494{
495 Q_D(const QToolButton);
496 return d->toolButtonStyle;
497}
498
499Qt::ArrowType QToolButton::arrowType() const
500{
501 Q_D(const QToolButton);
502 return d->arrowType;
503}
504
505
506void QToolButton::setToolButtonStyle(Qt::ToolButtonStyle style)
507{
508 Q_D(QToolButton);
509 if (d->toolButtonStyle == style)
510 return;
511
512 d->toolButtonStyle = style;
513 d->sizeHint = QSize();
514 updateGeometry();
515 if (isVisible()) {
516 update();
517 }
518}
519
520void QToolButton::setArrowType(Qt::ArrowType type)
521{
522 Q_D(QToolButton);
523 if (d->arrowType == type)
524 return;
525
526 d->arrowType = type;
527 d->sizeHint = QSize();
528 updateGeometry();
529 if (isVisible()) {
530 update();
531 }
532}
533
534/*!
535 \fn void QToolButton::paintEvent(QPaintEvent *event)
536
537 Paints the button in response to the paint \a event.
538*/
539void QToolButton::paintEvent(QPaintEvent *)
540{
541 QStylePainter p(this);
542 QStyleOptionToolButton opt;
543 initStyleOption(&opt);
544 p.drawComplexControl(QStyle::CC_ToolButton, opt);
545}
546
547/*!
548 \reimp
549 */
550void QToolButton::actionEvent(QActionEvent *event)
551{
552 Q_D(QToolButton);
553 QAction *action = event->action();
554 switch (event->type()) {
555 case QEvent::ActionChanged:
556 if (action == d->defaultAction)
557 setDefaultAction(action); // update button state
558 break;
559 case QEvent::ActionAdded:
560 connect(action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
561 break;
562 case QEvent::ActionRemoved:
563 if (d->defaultAction == action)
564 d->defaultAction = 0;
565#ifndef QT_NO_MENU
566 if (action == d->menuAction)
567 d->menuAction = 0;
568#endif
569 action->disconnect(this);
570 break;
571 default:
572 ;
573 }
574 QAbstractButton::actionEvent(event);
575}
576
577QStyle::SubControl QToolButtonPrivate::newHoverControl(const QPoint &pos)
578{
579 Q_Q(QToolButton);
580 QStyleOptionToolButton opt;
581 q->initStyleOption(&opt);
582 opt.subControls = QStyle::SC_All;
583 hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ToolButton, &opt, pos, q);
584 if (hoverControl == QStyle::SC_None)
585 hoverRect = QRect();
586 else
587 hoverRect = q->style()->subControlRect(QStyle::CC_ToolButton, &opt, hoverControl, q);
588 return hoverControl;
589}
590
591bool QToolButtonPrivate::updateHoverControl(const QPoint &pos)
592{
593 Q_Q(QToolButton);
594 QRect lastHoverRect = hoverRect;
595 QStyle::SubControl lastHoverControl = hoverControl;
596 bool doesHover = q->testAttribute(Qt::WA_Hover);
597 if (lastHoverControl != newHoverControl(pos) && doesHover) {
598 q->update(lastHoverRect);
599 q->update(hoverRect);
600 return true;
601 }
602 return !doesHover;
603}
604
605void QToolButtonPrivate::_q_actionTriggered()
606{
607 Q_Q(QToolButton);
608 if (QAction *action = qobject_cast<QAction *>(q->sender()))
609 emit q->triggered(action);
610}
611
612/*!
613 \reimp
614 */
615void QToolButton::enterEvent(QEvent * e)
616{
617 Q_D(QToolButton);
618 if (d->autoRaise)
619 update();
620 if (d->defaultAction)
621 d->defaultAction->hover();
622 QAbstractButton::enterEvent(e);
623}
624
625
626/*!
627 \reimp
628 */
629void QToolButton::leaveEvent(QEvent * e)
630{
631 Q_D(QToolButton);
632 if (d->autoRaise)
633 update();
634
635 QAbstractButton::leaveEvent(e);
636}
637
638
639/*!
640 \reimp
641 */
642void QToolButton::timerEvent(QTimerEvent *e)
643{
644#ifndef QT_NO_MENU
645 Q_D(QToolButton);
646 if (e->timerId() == d->popupTimer.timerId()) {
647 d->popupTimerDone();
648 return;
649 }
650#endif
651 QAbstractButton::timerEvent(e);
652}
653
654
655/*!
656 \reimp
657*/
658void QToolButton::changeEvent(QEvent *e)
659{
660#ifndef QT_NO_TOOLBAR
661 Q_D(QToolButton);
662 if (e->type() == QEvent::ParentChange) {
663 if (qobject_cast<QToolBar*>(parentWidget()))
664 d->autoRaise = true;
665 } else if (e->type() == QEvent::StyleChange
666#ifdef Q_WS_MAC
667 || e->type() == QEvent::MacSizeChange
668#endif
669 ) {
670#ifdef QT3_SUPPORT
671 if (!d->userDefinedPopupDelay)
672#endif
673 d->delay = style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, this);
674 d->setLayoutItemMargins(QStyle::SE_ToolButtonLayoutItem);
675 }
676#endif
677 QAbstractButton::changeEvent(e);
678}
679
680/*!
681 \reimp
682*/
683void QToolButton::mousePressEvent(QMouseEvent *e)
684{
685 Q_D(QToolButton);
686#ifndef QT_NO_MENU
687 QStyleOptionToolButton opt;
688 initStyleOption(&opt);
689 if (e->button() == Qt::LeftButton && (d->popupMode == MenuButtonPopup)) {
690 QRect popupr = style()->subControlRect(QStyle::CC_ToolButton, &opt,
691 QStyle::SC_ToolButtonMenu, this);
692 if (popupr.isValid() && popupr.contains(e->pos())) {
693 d->buttonPressed = QToolButtonPrivate::MenuButtonPressed;
694 showMenu();
695 return;
696 }
697 }
698#endif
699 d->buttonPressed = QToolButtonPrivate::ToolButtonPressed;
700 QAbstractButton::mousePressEvent(e);
701}
702
703/*!
704 \reimp
705*/
706void QToolButton::mouseReleaseEvent(QMouseEvent *e)
707{
708 Q_D(QToolButton);
709 QAbstractButton::mouseReleaseEvent(e);
710 d->buttonPressed = QToolButtonPrivate::NoButtonPressed;
711}
712
713/*!
714 \reimp
715*/
716bool QToolButton::hitButton(const QPoint &pos) const
717{
718 Q_D(const QToolButton);
719 if(QAbstractButton::hitButton(pos))
720 return (d->buttonPressed != QToolButtonPrivate::MenuButtonPressed);
721 return false;
722}
723
724#ifdef QT3_SUPPORT
725
726/*!
727 Use icon() instead.
728*/
729QIcon QToolButton::onIconSet() const
730{
731 return icon();
732}
733
734/*!
735 Use icon() instead.
736*/
737QIcon QToolButton::offIconSet() const
738{
739 return icon();
740}
741
742
743/*!
744 \obsolete
745
746 Use setIcon() instead.
747*/
748void QToolButton::setOnIconSet(const QIcon& set)
749{
750 setIcon(set);
751}
752
753/*!
754 \obsolete
755
756 Use setIcon() instead.
757*/
758void QToolButton::setOffIconSet(const QIcon& set)
759{
760 setIcon(set);
761}
762
763
764/*! \overload
765 \obsolete
766
767 Since Qt 3.0, QIcon contains both the On and Off icons.
768
769 For ease of porting, this function ignores the \a on parameter and
770 sets the \l{QAbstractButton::icon} {icon} property. If you relied on
771 the \a on parameter, you probably want to update your code to use
772 the QIcon On/Off mechanism.
773
774 \sa icon QIcon::State
775*/
776
777void QToolButton::setIconSet(const QIcon & set, bool /* on */)
778{
779 QAbstractButton::setIcon(set);
780}
781
782/*! \overload
783 \obsolete
784
785 Since Qt 3.0, QIcon contains both the On and Off icons.
786
787 For ease of porting, this function ignores the \a on parameter and
788 returns the \l{QAbstractButton::icon} {icon} property. If you relied
789 on the \a on parameter, you probably want to update your code to use
790 the QIcon On/Off mechanism.
791*/
792QIcon QToolButton::iconSet(bool /* on */) const
793{
794 return QAbstractButton::icon();
795}
796
797#endif
798
799#ifndef QT_NO_MENU
800/*!
801 Associates the given \a menu with this tool button.
802
803 The menu will be shown according to the button's \l popupMode.
804
805 Ownership of the menu is not transferred to the tool button.
806
807 \sa menu()
808*/
809void QToolButton::setMenu(QMenu* menu)
810{
811 Q_D(QToolButton);
812
813 if (d->menuAction)
814 removeAction(d->menuAction);
815
816 if (menu) {
817 d->menuAction = menu->menuAction();
818 addAction(d->menuAction);
819 } else {
820 d->menuAction = 0;
821 }
822 update();
823}
824
825/*!
826 Returns the associated menu, or 0 if no menu has been defined.
827
828 \sa setMenu()
829*/
830QMenu* QToolButton::menu() const
831{
832 Q_D(const QToolButton);
833 if (d->menuAction)
834 return d->menuAction->menu();
835 return 0;
836}
837
838/*!
839 Shows (pops up) the associated popup menu. If there is no such
840 menu, this function does nothing. This function does not return
841 until the popup menu has been closed by the user.
842*/
843void QToolButton::showMenu()
844{
845 Q_D(QToolButton);
846 if (!d->hasMenu()) {
847 d->menuButtonDown = false;
848 return; // no menu to show
849 }
850
851 d->menuButtonDown = true;
852 repaint();
853 d->popupTimer.stop();
854 d->popupTimerDone();
855}
856
857void QToolButtonPrivate::_q_buttonPressed()
858{
859 Q_Q(QToolButton);
860 if (!hasMenu())
861 return; // no menu to show
862
863 if (delay > 0 && popupMode == QToolButton::DelayedPopup)
864 popupTimer.start(delay, q);
865 else if (delay == 0 || popupMode == QToolButton::InstantPopup)
866 q->showMenu();
867}
868
869void QToolButtonPrivate::popupTimerDone()
870{
871 Q_Q(QToolButton);
872 popupTimer.stop();
873 if (!menuButtonDown && !down)
874 return;
875
876 menuButtonDown = true;
877 QPointer<QMenu> actualMenu;
878 bool mustDeleteActualMenu = false;
879 if(menuAction) {
880 actualMenu = menuAction->menu();
881 } else if (defaultAction && defaultAction->menu()) {
882 actualMenu = defaultAction->menu();
883 } else {
884 actualMenu = new QMenu(q);
885 mustDeleteActualMenu = true;
886 QList<QAction*> actions = q->actions();
887 for(int i = 0; i < actions.size(); i++)
888 actualMenu->addAction(actions.at(i));
889 }
890 repeat = q->autoRepeat();
891 q->setAutoRepeat(false);
892 bool horizontal = true;
893#if !defined(QT_NO_TOOLBAR)
894 QToolBar *tb = qobject_cast<QToolBar*>(q->parentWidget());
895 if (tb && tb->orientation() == Qt::Vertical)
896 horizontal = false;
897#endif
898 QPoint p;
899 QRect screen = qApp->desktop()->availableGeometry(q);
900 QSize sh = ((QToolButton*)(QMenu*)actualMenu)->receivers(SIGNAL(aboutToShow()))? QSize() : actualMenu->sizeHint();
901 QRect rect = q->rect();
902 if (horizontal) {
903 if (q->isRightToLeft()) {
904 if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) {
905 p = q->mapToGlobal(rect.bottomRight());
906 } else {
907 p = q->mapToGlobal(rect.topRight() - QPoint(0, sh.height()));
908 }
909 p.rx() -= sh.width();
910 } else {
911 if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) {
912 p = q->mapToGlobal(rect.bottomLeft());
913 } else {
914 p = q->mapToGlobal(rect.topLeft() - QPoint(0, sh.height()));
915 }
916 }
917 } else {
918 if (q->isRightToLeft()) {
919 if (q->mapToGlobal(QPoint(rect.left(), 0)).x() - sh.width() <= screen.x()) {
920 p = q->mapToGlobal(rect.topRight());
921 } else {
922 p = q->mapToGlobal(rect.topLeft());
923 p.rx() -= sh.width();
924 }
925 } else {
926 if (q->mapToGlobal(QPoint(rect.right(), 0)).x() + sh.width() <= screen.right()) {
927 p = q->mapToGlobal(rect.topRight());
928 } else {
929 p = q->mapToGlobal(rect.topLeft() - QPoint(sh.width(), 0));
930 }
931 }
932 }
933 p.rx() = qMax(screen.left(), qMin(p.x(), screen.right() - sh.width()));
934 p.ry() += 1;
935 QPointer<QToolButton> that = q;
936 actualMenu->setNoReplayFor(q);
937 if (!mustDeleteActualMenu) //only if action are not in this widget
938 QObject::connect(actualMenu, SIGNAL(triggered(QAction*)), q, SLOT(_q_menuTriggered(QAction*)));
939 QObject::connect(actualMenu, SIGNAL(aboutToHide()), q, SLOT(_q_updateButtonDown()));
940 actualMenu->d_func()->causedPopup.widget = q;
941 actualMenu->d_func()->causedPopup.action = defaultAction;
942 actionsCopy = q->actions(); //(the list of action may be modified in slots)
943 actualMenu->exec(p);
944 QObject::disconnect(actualMenu, SIGNAL(aboutToHide()), q, SLOT(_q_updateButtonDown()));
945 if (mustDeleteActualMenu)
946 delete actualMenu;
947 else
948 QObject::disconnect(actualMenu, SIGNAL(triggered(QAction*)), q, SLOT(_q_menuTriggered(QAction*)));
949
950 if (!that)
951 return;
952
953 actionsCopy.clear();
954
955 if (repeat)
956 q->setAutoRepeat(true);
957}
958
959void QToolButtonPrivate::_q_updateButtonDown()
960{
961 Q_Q(QToolButton);
962 menuButtonDown = false;
963 if (q->isDown())
964 q->setDown(false);
965 else
966 q->repaint();
967}
968
969void QToolButtonPrivate::_q_menuTriggered(QAction *action)
970{
971 Q_Q(QToolButton);
972 if (action && !actionsCopy.contains(action))
973 emit q->triggered(action);
974}
975#endif // QT_NO_MENU
976
977#ifdef QT3_SUPPORT
978/*!
979 \fn void QToolButton::setPopupDelay(int delay)
980
981 Use the style hint QStyle::SH_ToolButton_PopupDelay instead.
982*/
983void QToolButton::setPopupDelay(int delay)
984{
985 Q_D(QToolButton);
986 d->userDefinedPopupDelay = true;
987 d->delay = delay;
988
989 update();
990}
991
992/*!
993 Use the style hint QStyle::SH_ToolButton_PopupDelay instead.
994*/
995int QToolButton::popupDelay() const
996{
997 Q_D(const QToolButton);
998 return d->delay;
999}
1000#endif
1001
1002#ifndef QT_NO_MENU
1003/*! \enum QToolButton::ToolButtonPopupMode
1004
1005 Describes how a menu should be popped up for tool buttons that has
1006 a menu set or contains a list of actions.
1007
1008 \value DelayedPopup After pressing and holding the tool button
1009 down for a certain amount of time (the timeout is style dependant,
1010 see QStyle::SH_ToolButton_PopupDelay), the menu is displayed. A
1011 typical application example is the "back" button in some web
1012 browsers's tool bars. If the user clicks it, the browser simply
1013 browses back to the previous page. If the user presses and holds
1014 the button down for a while, the tool button shows a menu
1015 containing the current history list
1016
1017 \value MenuButtonPopup In this mode the tool button displays a
1018 special arrow to indicate that a menu is present. The menu is
1019 displayed when the arrow part of the button is pressed.
1020
1021 \value InstantPopup The menu is displayed, without delay, when
1022 the tool button is pressed. In this mode, the button's own action
1023 is not triggered.
1024*/
1025
1026/*!
1027 \property QToolButton::popupMode
1028 \brief describes the way that popup menus are used with tool buttons
1029
1030 By default, this property is set to \l DelayedPopup.
1031*/
1032
1033void QToolButton::setPopupMode(ToolButtonPopupMode mode)
1034{
1035 Q_D(QToolButton);
1036 d->popupMode = mode;
1037}
1038
1039QToolButton::ToolButtonPopupMode QToolButton::popupMode() const
1040{
1041 Q_D(const QToolButton);
1042 return d->popupMode;
1043}
1044#endif
1045
1046/*!
1047 \property QToolButton::autoRaise
1048 \brief whether auto-raising is enabled or not.
1049
1050 The default is disabled (i.e. false).
1051
1052 This property is currently ignored on Mac OS X when using QMacStyle.
1053*/
1054void QToolButton::setAutoRaise(bool enable)
1055{
1056 Q_D(QToolButton);
1057 d->autoRaise = enable;
1058
1059 update();
1060}
1061
1062bool QToolButton::autoRaise() const
1063{
1064 Q_D(const QToolButton);
1065 return d->autoRaise;
1066}
1067
1068/*!
1069 Sets the default action to \a action.
1070
1071 If a tool button has a default action, the action defines the
1072 button's properties like text, icon, tool tip, etc.
1073 */
1074void QToolButton::setDefaultAction(QAction *action)
1075{
1076 Q_D(QToolButton);
1077#ifndef QT_NO_MENU
1078 bool hadMenu = false;
1079 hadMenu = d->hasMenu();
1080#endif
1081 d->defaultAction = action;
1082 if (!action)
1083 return;
1084 if (!actions().contains(action))
1085 addAction(action);
1086 setText(action->iconText());
1087 setIcon(action->icon());
1088#ifndef QT_NO_TOOLTIP
1089 setToolTip(action->toolTip());
1090#endif
1091#ifndef QT_NO_STATUSTIP
1092 setStatusTip(action->statusTip());
1093#endif
1094#ifndef QT_NO_WHATSTHIS
1095 setWhatsThis(action->whatsThis());
1096#endif
1097#ifndef QT_NO_MENU
1098 if (action->menu() && !hadMenu) {
1099 // new 'default' popup mode defined introduced by tool bar. We
1100 // should have changed QToolButton's default instead. Do that
1101 // in 4.2.
1102 setPopupMode(QToolButton::MenuButtonPopup);
1103 }
1104#endif
1105 setCheckable(action->isCheckable());
1106 setChecked(action->isChecked());
1107 setEnabled(action->isEnabled());
1108 if (action->d_func()->fontSet)
1109 setFont(action->font());
1110}
1111
1112
1113/*!
1114 Returns the default action.
1115
1116 \sa setDefaultAction()
1117 */
1118QAction *QToolButton::defaultAction() const
1119{
1120 Q_D(const QToolButton);
1121 return d->defaultAction;
1122}
1123
1124
1125
1126/*!
1127 \reimp
1128 */
1129void QToolButton::nextCheckState()
1130{
1131 Q_D(QToolButton);
1132 if (!d->defaultAction)
1133 QAbstractButton::nextCheckState();
1134 else
1135 d->defaultAction->trigger();
1136}
1137
1138/*! \reimp */
1139bool QToolButton::event(QEvent *event)
1140{
1141 switch(event->type()) {
1142 case QEvent::HoverEnter:
1143 case QEvent::HoverLeave:
1144 case QEvent::HoverMove:
1145 if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
1146 d_func()->updateHoverControl(he->pos());
1147 break;
1148 default:
1149 break;
1150 }
1151 return QAbstractButton::event(event);
1152}
1153
1154/*! \internal
1155 */
1156QToolButton::QToolButton(QToolButtonPrivate &dd, QWidget *parent)
1157 :QAbstractButton(dd, parent)
1158{
1159 Q_D(QToolButton);
1160 d->init();
1161}
1162
1163/*!
1164 \fn void QToolButton::setPixmap(const QPixmap &pixmap)
1165
1166 Use setIcon(QIcon(pixmap)) instead.
1167*/
1168
1169/*!
1170 \fn void QToolButton::setIconSet(const QIcon &icon)
1171
1172 Use setIcon() instead.
1173*/
1174
1175/*!
1176 \fn void QToolButton::setTextLabel(const QString &text, bool tooltip)
1177
1178 Use setText() and setToolTip() instead.
1179*/
1180
1181/*!
1182 \fn QString QToolButton::textLabel() const
1183
1184 Use text() instead.
1185*/
1186
1187/*!
1188 \fn QIcon QToolButton::iconSet() const
1189
1190 Use icon() instead.
1191*/
1192
1193/*!
1194 \fn void QToolButton::openPopup()
1195
1196 Use showMenu() instead.
1197*/
1198
1199/*!
1200 \fn void QToolButton::setPopup(QMenu* popup)
1201
1202 Use setMenu() instead.
1203*/
1204
1205/*!
1206 \fn QMenu* QToolButton::popup() const
1207
1208 Use menu() instead.
1209*/
1210
1211/*!
1212 \fn TextPosition QToolButton::textPosition() const
1213
1214 Use toolButtonStyle() instead.
1215*/
1216
1217/*!
1218 \fn void QToolButton::setTextPosition(QToolButton::TextPosition pos)
1219
1220 Use setToolButtonStyle() instead.
1221*/
1222
1223/*!
1224 \fn bool QToolButton::usesBigPixmap() const
1225
1226 Use iconSize() instead.
1227*/
1228
1229/*!
1230 \fn void QToolButton::setUsesBigPixmap(bool enable)
1231
1232 Use setIconSize() instead.
1233*/
1234
1235/*!
1236 \fn bool QToolButton::usesTextLabel() const
1237
1238 Use toolButtonStyle() instead.
1239*/
1240
1241/*!
1242 \fn void QToolButton::setUsesTextLabel(bool enable)
1243
1244 Use setToolButtonStyle() instead.
1245*/
1246
1247QT_END_NAMESPACE
1248
1249#include "moc_qtoolbutton.cpp"
1250
1251#endif
Note: See TracBrowser for help on using the repository browser.