Remove documentation for non-existent QToolButton functions.
[profile/ivi/qtbase.git] / src / widgets / widgets / qtoolbutton.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
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
64 QT_BEGIN_NAMESPACE
65
66 class QToolButtonPrivate : public QAbstractButtonPrivate
67 {
68     Q_DECLARE_PUBLIC(QToolButton)
69 public:
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 };
100
101 #ifndef QT_NO_MENU
102 bool QToolButtonPrivate::hasMenu() const
103 {
104     return ((defaultAction && defaultAction->menu())
105             || (menuAction && menuAction->menu())
106             || actions.size() > (defaultAction ? 1 : 0));
107 }
108 #endif
109
110 /*!
111     \class QToolButton
112     \brief The QToolButton class provides a quick-access button to
113     commands or options, usually used inside a QToolBar.
114
115     \ingroup basicwidgets
116     \inmodule QtWidgets
117
118     A tool button is a special button that provides quick-access to
119     specific commands or options. As opposed to a normal command
120     button, a tool button usually doesn't show a text label, but shows
121     an icon instead.
122
123     Tool buttons are normally created when new QAction instances are
124     created with QToolBar::addAction() or existing actions are added
125     to a toolbar with QToolBar::addAction(). It is also possible to
126     construct tool buttons in the same way as any other widget, and
127     arrange them alongside other widgets in layouts.
128
129     One classic use of a tool button is to select tools; for example,
130     the "pen" tool in a drawing program. This would be implemented
131     by using a QToolButton as a toggle button (see setToggleButton()).
132
133     QToolButton supports auto-raising. In auto-raise mode, the button
134     draws a 3D frame only when the mouse points at it. The feature is
135     automatically turned on when a button is used inside a QToolBar.
136     Change it with setAutoRaise().
137
138     A tool button's icon is set as QIcon. This makes it possible to
139     specify different pixmaps for the disabled and active state. The
140     disabled pixmap is used when the button's functionality is not
141     available. The active pixmap is displayed when the button is
142     auto-raised because the mouse pointer is hovering over it.
143
144     The button's look and dimension is adjustable with
145     setToolButtonStyle() and setIconSize(). When used inside a
146     QToolBar in a QMainWindow, the button automatically adjusts to
147     QMainWindow's settings (see QMainWindow::setToolButtonStyle() and
148     QMainWindow::setIconSize()). Instead of an icon, a tool button can
149     also display an arrow symbol, specified with
150     \l{QToolButton::arrowType} {arrowType}.
151
152     A tool button can offer additional choices in a popup menu. The
153     popup menu can be set using setMenu(). Use setPopupMode() to
154     configure the different modes available for tool buttons with a
155     menu set. The default mode is DelayedPopupMode which is sometimes
156     used with the "Back" button in a web browser.  After pressing and
157     holding the button down for a while, a menu pops up showing a list
158     of possible pages to jump to. The default delay is 600 ms; you can
159     adjust it with setPopupDelay().
160
161     \table 100%
162     \row \li \inlineimage assistant-toolbar.png Qt Assistant's toolbar with tool buttons
163     \row \li Qt Assistant's toolbar contains tool buttons that are associated
164          with actions used in other parts of the main window.
165     \endtable
166
167     \sa QPushButton, QToolBar, QMainWindow, QAction,
168         {fowler}{GUI Design Handbook: Push Button}
169 */
170
171 /*!
172     \fn void QToolButton::triggered(QAction *action)
173
174     This signal is emitted when the given \a action is triggered.
175
176     The action may also be associated with other parts of the user interface,
177     such as menu items and keyboard shortcuts. Sharing actions in this
178     way helps make the user interface more consistent and is often less work
179     to implement.
180 */
181
182 /*!
183     Constructs an empty tool button with parent \a
184     parent.
185 */
186 QToolButton::QToolButton(QWidget * parent)
187     : QAbstractButton(*new QToolButtonPrivate, parent)
188 {
189     Q_D(QToolButton);
190     d->init();
191 }
192
193
194
195 /*  Set-up code common to all the constructors */
196
197 void QToolButtonPrivate::init()
198 {
199     Q_Q(QToolButton);
200     delay = q->style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, q);
201     defaultAction = 0;
202 #ifndef QT_NO_TOOLBAR
203     if (qobject_cast<QToolBar*>(parent))
204         autoRaise = true;
205     else
206 #endif
207         autoRaise = false;
208     arrowType = Qt::NoArrow;
209     menuButtonDown = false;
210     popupMode = QToolButton::DelayedPopup;
211     buttonPressed = QToolButtonPrivate::NoButtonPressed;
212
213     toolButtonStyle = Qt::ToolButtonIconOnly;
214     hoverControl = QStyle::SC_None;
215
216     q->setFocusPolicy(Qt::TabFocus);
217     q->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed,
218                                  QSizePolicy::ToolButton));
219
220 #ifndef QT_NO_MENU
221     QObject::connect(q, SIGNAL(pressed()), q, SLOT(_q_buttonPressed()));
222 #endif
223
224     setLayoutItemMargins(QStyle::SE_ToolButtonLayoutItem);
225
226 }
227
228 /*!
229     Initialize \a option with the values from this QToolButton. This method
230     is useful for subclasses when they need a QStyleOptionToolButton, but don't want
231     to fill in all the information themselves.
232
233     \sa QStyleOption::initFrom()
234 */
235 void QToolButton::initStyleOption(QStyleOptionToolButton *option) const
236 {
237     if (!option)
238         return;
239
240     Q_D(const QToolButton);
241     option->initFrom(this);
242     bool forceNoText = false;
243     option->iconSize = iconSize(); //default value
244
245 #ifndef QT_NO_TOOLBAR
246     if (parentWidget()) {
247         if (QToolBar *toolBar = qobject_cast<QToolBar *>(parentWidget())) {
248             option->iconSize = toolBar->iconSize();
249         }
250     }
251 #endif // QT_NO_TOOLBAR
252
253     if (!forceNoText)
254         option->text = d->text;
255     option->icon = d->icon;
256     option->arrowType = d->arrowType;
257     if (d->down)
258         option->state |= QStyle::State_Sunken;
259     if (d->checked)
260         option->state |= QStyle::State_On;
261     if (d->autoRaise)
262         option->state |= QStyle::State_AutoRaise;
263     if (!d->checked && !d->down)
264         option->state |= QStyle::State_Raised;
265
266     option->subControls = QStyle::SC_ToolButton;
267     option->activeSubControls = QStyle::SC_None;
268
269     option->features = QStyleOptionToolButton::None;
270     if (d->popupMode == QToolButton::MenuButtonPopup) {
271         option->subControls |= QStyle::SC_ToolButtonMenu;
272         option->features |= QStyleOptionToolButton::MenuButtonPopup;
273     }
274     if (option->state & QStyle::State_MouseOver) {
275         option->activeSubControls = d->hoverControl;
276     }
277     if (d->menuButtonDown) {
278         option->state |= QStyle::State_Sunken;
279         option->activeSubControls |= QStyle::SC_ToolButtonMenu;
280     }
281     if (d->down) {
282         option->state |= QStyle::State_Sunken;
283         option->activeSubControls |= QStyle::SC_ToolButton;
284     }
285
286
287     if (d->arrowType != Qt::NoArrow)
288         option->features |= QStyleOptionToolButton::Arrow;
289     if (d->popupMode == QToolButton::DelayedPopup)
290         option->features |= QStyleOptionToolButton::PopupDelay;
291 #ifndef QT_NO_MENU
292     if (d->hasMenu())
293         option->features |= QStyleOptionToolButton::HasMenu;
294 #endif
295     if (d->toolButtonStyle == Qt::ToolButtonFollowStyle) {
296         option->toolButtonStyle = Qt::ToolButtonStyle(style()->styleHint(QStyle::SH_ToolButtonStyle, option, this));
297     } else
298         option->toolButtonStyle = d->toolButtonStyle;
299
300     if (option->toolButtonStyle == Qt::ToolButtonTextBesideIcon) {
301         // If the action is not prioritized, remove the text label to save space
302         if (d->defaultAction && d->defaultAction->priority() < QAction::NormalPriority)
303             option->toolButtonStyle = Qt::ToolButtonIconOnly;
304     }
305
306     if (d->icon.isNull() && d->arrowType == Qt::NoArrow && !forceNoText) {
307         if (!d->text.isEmpty())
308             option->toolButtonStyle = Qt::ToolButtonTextOnly;
309         else if (option->toolButtonStyle != Qt::ToolButtonTextOnly)
310             option->toolButtonStyle = Qt::ToolButtonIconOnly;
311     }
312
313     option->pos = pos();
314     option->font = font();
315 }
316
317 /*!
318     Destroys the object and frees any allocated resources.
319 */
320
321 QToolButton::~QToolButton()
322 {
323 }
324
325 /*!
326     \reimp
327 */
328 QSize QToolButton::sizeHint() const
329 {
330     Q_D(const QToolButton);
331     if (d->sizeHint.isValid())
332         return d->sizeHint;
333     ensurePolished();
334
335     int w = 0, h = 0;
336     QStyleOptionToolButton opt;
337     initStyleOption(&opt);
338
339     QFontMetrics fm = fontMetrics();
340     if (opt.toolButtonStyle != Qt::ToolButtonTextOnly) {
341         QSize icon = opt.iconSize;
342         w = icon.width();
343         h = icon.height();
344     }
345
346     if (opt.toolButtonStyle != Qt::ToolButtonIconOnly) {
347         QSize textSize = fm.size(Qt::TextShowMnemonic, text());
348         textSize.setWidth(textSize.width() + fm.width(QLatin1Char(' '))*2);
349         if (opt.toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
350             h += 4 + textSize.height();
351             if (textSize.width() > w)
352                 w = textSize.width();
353         } else if (opt.toolButtonStyle == Qt::ToolButtonTextBesideIcon) {
354             w += 4 + textSize.width();
355             if (textSize.height() > h)
356                 h = textSize.height();
357         } else { // TextOnly
358             w = textSize.width();
359             h = textSize.height();
360         }
361     }
362
363     opt.rect.setSize(QSize(w, h)); // PM_MenuButtonIndicator depends on the height
364     if (d->popupMode == MenuButtonPopup)
365         w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this);
366
367     d->sizeHint = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(w, h), this).
368                   expandedTo(QApplication::globalStrut());
369     return d->sizeHint;
370 }
371
372 /*!
373     \reimp
374  */
375 QSize QToolButton::minimumSizeHint() const
376 {
377     return sizeHint();
378 }
379
380 /*!
381     \property QToolButton::toolButtonStyle
382     \brief whether the tool button displays an icon only, text only,
383     or text beside/below the icon.
384
385     The default is Qt::ToolButtonIconOnly.
386
387     To have the style of toolbuttons follow the system settings (as available
388     in GNOME and KDE desktop environments), set this property to Qt::ToolButtonFollowStyle.
389
390     QToolButton automatically connects this slot to the relevant
391     signal in the QMainWindow in which is resides.
392 */
393
394 /*!
395     \property QToolButton::arrowType
396     \brief whether the button displays an arrow instead of a normal icon
397
398     This displays an arrow as the icon for the QToolButton.
399
400     By default, this property is set to Qt::NoArrow.
401 */
402
403 Qt::ToolButtonStyle QToolButton::toolButtonStyle() const
404 {
405     Q_D(const QToolButton);
406     return d->toolButtonStyle;
407 }
408
409 Qt::ArrowType QToolButton::arrowType() const
410 {
411     Q_D(const QToolButton);
412     return d->arrowType;
413 }
414
415
416 void QToolButton::setToolButtonStyle(Qt::ToolButtonStyle style)
417 {
418     Q_D(QToolButton);
419     if (d->toolButtonStyle == style)
420         return;
421
422     d->toolButtonStyle = style;
423     d->sizeHint = QSize();
424     updateGeometry();
425     if (isVisible()) {
426         update();
427     }
428 }
429
430 void QToolButton::setArrowType(Qt::ArrowType type)
431 {
432     Q_D(QToolButton);
433     if (d->arrowType == type)
434         return;
435
436     d->arrowType = type;
437     d->sizeHint = QSize();
438     updateGeometry();
439     if (isVisible()) {
440         update();
441     }
442 }
443
444 /*!
445     \fn void QToolButton::paintEvent(QPaintEvent *event)
446
447     Paints the button in response to the paint \a event.
448 */
449 void QToolButton::paintEvent(QPaintEvent *)
450 {
451     QStylePainter p(this);
452     QStyleOptionToolButton opt;
453     initStyleOption(&opt);
454     p.drawComplexControl(QStyle::CC_ToolButton, opt);
455 }
456
457 /*!
458     \reimp
459  */
460 void QToolButton::actionEvent(QActionEvent *event)
461 {
462     Q_D(QToolButton);
463     QAction *action = event->action();
464     switch (event->type()) {
465     case QEvent::ActionChanged:
466         if (action == d->defaultAction)
467             setDefaultAction(action); // update button state
468         break;
469     case QEvent::ActionAdded:
470         connect(action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
471         break;
472     case QEvent::ActionRemoved:
473         if (d->defaultAction == action)
474             d->defaultAction = 0;
475 #ifndef QT_NO_MENU
476         if (action == d->menuAction)
477             d->menuAction = 0;
478 #endif
479         action->disconnect(this);
480         break;
481     default:
482         ;
483     }
484     QAbstractButton::actionEvent(event);
485 }
486
487 QStyle::SubControl QToolButtonPrivate::newHoverControl(const QPoint &pos)
488 {
489     Q_Q(QToolButton);
490     QStyleOptionToolButton opt;
491     q->initStyleOption(&opt);
492     opt.subControls = QStyle::SC_All;
493     hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ToolButton, &opt, pos, q);
494     if (hoverControl == QStyle::SC_None)
495         hoverRect = QRect();
496     else
497         hoverRect = q->style()->subControlRect(QStyle::CC_ToolButton, &opt, hoverControl, q);
498     return hoverControl;
499 }
500
501 bool QToolButtonPrivate::updateHoverControl(const QPoint &pos)
502 {
503     Q_Q(QToolButton);
504     QRect lastHoverRect = hoverRect;
505     QStyle::SubControl lastHoverControl = hoverControl;
506     bool doesHover = q->testAttribute(Qt::WA_Hover);
507     if (lastHoverControl != newHoverControl(pos) && doesHover) {
508         q->update(lastHoverRect);
509         q->update(hoverRect);
510         return true;
511     }
512     return !doesHover;
513 }
514
515 void QToolButtonPrivate::_q_actionTriggered()
516 {
517     Q_Q(QToolButton);
518     if (QAction *action = qobject_cast<QAction *>(q->sender()))
519         emit q->triggered(action);
520 }
521
522 /*!
523     \reimp
524  */
525 void QToolButton::enterEvent(QEvent * e)
526 {
527     Q_D(QToolButton);
528     if (d->autoRaise)
529         update();
530     if (d->defaultAction)
531         d->defaultAction->hover();
532     QAbstractButton::enterEvent(e);
533 }
534
535
536 /*!
537     \reimp
538  */
539 void QToolButton::leaveEvent(QEvent * e)
540 {
541     Q_D(QToolButton);
542     if (d->autoRaise)
543         update();
544
545     QAbstractButton::leaveEvent(e);
546 }
547
548
549 /*!
550     \reimp
551  */
552 void QToolButton::timerEvent(QTimerEvent *e)
553 {
554 #ifndef QT_NO_MENU
555     Q_D(QToolButton);
556     if (e->timerId() == d->popupTimer.timerId()) {
557         d->popupTimerDone();
558         return;
559     }
560 #endif
561     QAbstractButton::timerEvent(e);
562 }
563
564
565 /*!
566     \reimp
567 */
568 void QToolButton::changeEvent(QEvent *e)
569 {
570 #ifndef QT_NO_TOOLBAR
571     Q_D(QToolButton);
572     if (e->type() == QEvent::ParentChange) {
573         if (qobject_cast<QToolBar*>(parentWidget()))
574             d->autoRaise = true;
575     } else if (e->type() == QEvent::StyleChange
576 #ifdef Q_WS_MAC
577                || e->type() == QEvent::MacSizeChange
578 #endif
579                ) {
580         d->delay = style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, this);
581         d->setLayoutItemMargins(QStyle::SE_ToolButtonLayoutItem);
582     }
583 #endif
584     QAbstractButton::changeEvent(e);
585 }
586
587 /*!
588     \reimp
589 */
590 void QToolButton::mousePressEvent(QMouseEvent *e)
591 {
592     Q_D(QToolButton);
593 #ifndef QT_NO_MENU
594     QStyleOptionToolButton opt;
595     initStyleOption(&opt);
596     if (e->button() == Qt::LeftButton && (d->popupMode == MenuButtonPopup)) {
597         QRect popupr = style()->subControlRect(QStyle::CC_ToolButton, &opt,
598                                                QStyle::SC_ToolButtonMenu, this);
599         if (popupr.isValid() && popupr.contains(e->pos())) {
600             d->buttonPressed = QToolButtonPrivate::MenuButtonPressed;
601             showMenu();
602             return;
603         }
604     }
605 #endif
606     d->buttonPressed = QToolButtonPrivate::ToolButtonPressed;
607     QAbstractButton::mousePressEvent(e);
608 }
609
610 /*!
611     \reimp
612 */
613 void QToolButton::mouseReleaseEvent(QMouseEvent *e)
614 {
615     Q_D(QToolButton);
616     QAbstractButton::mouseReleaseEvent(e);
617     d->buttonPressed = QToolButtonPrivate::NoButtonPressed;
618 }
619
620 /*!
621     \reimp
622 */
623 bool QToolButton::hitButton(const QPoint &pos) const
624 {
625     Q_D(const QToolButton);
626     if(QAbstractButton::hitButton(pos))
627         return (d->buttonPressed != QToolButtonPrivate::MenuButtonPressed);
628     return false;
629 }
630
631
632 #ifndef QT_NO_MENU
633 /*!
634     Associates the given \a menu with this tool button.
635
636     The menu will be shown according to the button's \l popupMode.
637
638     Ownership of the menu is not transferred to the tool button.
639
640     \sa menu()
641 */
642 void QToolButton::setMenu(QMenu* menu)
643 {
644     Q_D(QToolButton);
645
646     if (d->menuAction)
647         removeAction(d->menuAction);
648
649     if (menu) {
650         d->menuAction = menu->menuAction();
651         addAction(d->menuAction);
652     } else {
653         d->menuAction = 0;
654     }
655     update();
656 }
657
658 /*!
659     Returns the associated menu, or 0 if no menu has been defined.
660
661     \sa setMenu()
662 */
663 QMenu* QToolButton::menu() const
664 {
665     Q_D(const QToolButton);
666     if (d->menuAction)
667         return d->menuAction->menu();
668     return 0;
669 }
670
671 /*!
672     Shows (pops up) the associated popup menu. If there is no such
673     menu, this function does nothing. This function does not return
674     until the popup menu has been closed by the user.
675 */
676 void QToolButton::showMenu()
677 {
678     Q_D(QToolButton);
679     if (!d->hasMenu()) {
680         d->menuButtonDown = false;
681         return; // no menu to show
682     }
683
684     d->menuButtonDown = true;
685     repaint();
686     d->popupTimer.stop();
687     d->popupTimerDone();
688 }
689
690 void QToolButtonPrivate::_q_buttonPressed()
691 {
692     Q_Q(QToolButton);
693     if (!hasMenu())
694         return; // no menu to show
695     if (popupMode == QToolButton::MenuButtonPopup)
696         return;
697     else if (delay > 0 && !popupTimer.isActive() && popupMode == QToolButton::DelayedPopup)
698         popupTimer.start(delay, q);
699     else if (delay == 0 || popupMode == QToolButton::InstantPopup)
700         q->showMenu();
701 }
702
703 void QToolButtonPrivate::popupTimerDone()
704 {
705     Q_Q(QToolButton);
706     popupTimer.stop();
707     if (!menuButtonDown && !down)
708         return;
709
710     menuButtonDown = true;
711     QPointer<QMenu> actualMenu;
712     bool mustDeleteActualMenu = false;
713     if(menuAction) {
714         actualMenu = menuAction->menu();
715     } else if (defaultAction && defaultAction->menu()) {
716         actualMenu = defaultAction->menu();
717     } else {
718         actualMenu = new QMenu(q);
719         mustDeleteActualMenu = true;
720         for(int i = 0; i < actions.size(); i++)
721             actualMenu->addAction(actions.at(i));
722     }
723     repeat = q->autoRepeat();
724     q->setAutoRepeat(false);
725     bool horizontal = true;
726 #if !defined(QT_NO_TOOLBAR)
727     QToolBar *tb = qobject_cast<QToolBar*>(parent);
728     if (tb && tb->orientation() == Qt::Vertical)
729         horizontal = false;
730 #endif
731     QPoint p;
732     QRect screen = QApplication::desktop()->availableGeometry(q);
733     QSize sh = ((QToolButton*)(QMenu*)actualMenu)->receivers(SIGNAL(aboutToShow()))? QSize() : actualMenu->sizeHint();
734     QRect rect = q->rect();
735     if (horizontal) {
736         if (q->isRightToLeft()) {
737             if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) {
738                 p = q->mapToGlobal(rect.bottomRight());
739             } else {
740                 p = q->mapToGlobal(rect.topRight() - QPoint(0, sh.height()));
741             }
742             p.rx() -= sh.width();
743         } else {
744             if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) {
745                 p = q->mapToGlobal(rect.bottomLeft());
746             } else {
747                 p = q->mapToGlobal(rect.topLeft() - QPoint(0, sh.height()));
748             }
749         }
750     } else {
751         if (q->isRightToLeft()) {
752             if (q->mapToGlobal(QPoint(rect.left(), 0)).x() - sh.width() <= screen.x()) {
753                 p = q->mapToGlobal(rect.topRight());
754             } else {
755                 p = q->mapToGlobal(rect.topLeft());
756                 p.rx() -= sh.width();
757             }
758         } else {
759             if (q->mapToGlobal(QPoint(rect.right(), 0)).x() + sh.width() <= screen.right()) {
760                 p = q->mapToGlobal(rect.topRight());
761             } else {
762                 p = q->mapToGlobal(rect.topLeft() - QPoint(sh.width(), 0));
763             }
764         }
765     }
766     p.rx() = qMax(screen.left(), qMin(p.x(), screen.right() - sh.width()));
767     p.ry() += 1;
768     QPointer<QToolButton> that = q;
769     actualMenu->setNoReplayFor(q);
770     if (!mustDeleteActualMenu) //only if action are not in this widget
771         QObject::connect(actualMenu, SIGNAL(triggered(QAction*)), q, SLOT(_q_menuTriggered(QAction*)));
772     QObject::connect(actualMenu, SIGNAL(aboutToHide()), q, SLOT(_q_updateButtonDown()));
773     actualMenu->d_func()->causedPopup.widget = q;
774     actualMenu->d_func()->causedPopup.action = defaultAction;
775     actionsCopy = q->actions(); //(the list of action may be modified in slots)
776     actualMenu->exec(p);
777     QObject::disconnect(actualMenu, SIGNAL(aboutToHide()), q, SLOT(_q_updateButtonDown()));
778     if (mustDeleteActualMenu)
779         delete actualMenu;
780     else
781         QObject::disconnect(actualMenu, SIGNAL(triggered(QAction*)), q, SLOT(_q_menuTriggered(QAction*)));
782
783     if (!that)
784         return;
785
786     actionsCopy.clear();
787
788     if (repeat)
789         q->setAutoRepeat(true);
790 }
791
792 void QToolButtonPrivate::_q_updateButtonDown()
793 {
794     Q_Q(QToolButton);
795     menuButtonDown = false;
796     if (q->isDown())
797         q->setDown(false);
798     else
799         q->repaint();
800 }
801
802 void QToolButtonPrivate::_q_menuTriggered(QAction *action)
803 {
804     Q_Q(QToolButton);
805     if (action && !actionsCopy.contains(action))
806         emit q->triggered(action);
807 }
808 #endif // QT_NO_MENU
809
810
811 #ifndef QT_NO_MENU
812 /*! \enum QToolButton::ToolButtonPopupMode
813
814     Describes how a menu should be popped up for tool buttons that has
815     a menu set or contains a list of actions.
816
817     \value DelayedPopup After pressing and holding the tool button
818     down for a certain amount of time (the timeout is style dependant,
819     see QStyle::SH_ToolButton_PopupDelay), the menu is displayed.  A
820     typical application example is the "back" button in some web
821     browsers's tool bars. If the user clicks it, the browser simply
822     browses back to the previous page.  If the user presses and holds
823     the button down for a while, the tool button shows a menu
824     containing the current history list
825
826     \value MenuButtonPopup In this mode the tool button displays a
827     special arrow to indicate that a menu is present. The menu is
828     displayed when the arrow part of the button is pressed.
829
830     \value InstantPopup The menu is displayed, without delay, when
831     the tool button is pressed. In this mode, the button's own action
832     is not triggered.
833 */
834
835 /*!
836     \property QToolButton::popupMode
837     \brief describes the way that popup menus are used with tool buttons
838
839     By default, this property is set to \l DelayedPopup.
840 */
841
842 void QToolButton::setPopupMode(ToolButtonPopupMode mode)
843 {
844     Q_D(QToolButton);
845     d->popupMode = mode;
846 }
847
848 QToolButton::ToolButtonPopupMode QToolButton::popupMode() const
849 {
850     Q_D(const QToolButton);
851     return d->popupMode;
852 }
853 #endif
854
855 /*!
856     \property QToolButton::autoRaise
857     \brief whether auto-raising is enabled or not.
858
859     The default is disabled (i.e. false).
860
861     This property is currently ignored on Mac OS X when using QMacStyle.
862 */
863 void QToolButton::setAutoRaise(bool enable)
864 {
865     Q_D(QToolButton);
866     d->autoRaise = enable;
867
868     update();
869 }
870
871 bool QToolButton::autoRaise() const
872 {
873     Q_D(const QToolButton);
874     return d->autoRaise;
875 }
876
877 /*!
878   Sets the default action to \a action.
879
880   If a tool button has a default action, the action defines the
881   button's properties like text, icon, tool tip, etc.
882  */
883 void QToolButton::setDefaultAction(QAction *action)
884 {
885     Q_D(QToolButton);
886 #ifndef QT_NO_MENU
887     bool hadMenu = false;
888     hadMenu = d->hasMenu();
889 #endif
890     d->defaultAction = action;
891     if (!action)
892         return;
893     if (!actions().contains(action))
894         addAction(action);
895     setText(action->iconText());
896     setIcon(action->icon());
897 #ifndef QT_NO_TOOLTIP
898     setToolTip(action->toolTip());
899 #endif
900 #ifndef QT_NO_STATUSTIP
901     setStatusTip(action->statusTip());
902 #endif
903 #ifndef QT_NO_WHATSTHIS
904     setWhatsThis(action->whatsThis());
905 #endif
906 #ifndef QT_NO_MENU
907     if (action->menu() && !hadMenu) {
908         // new 'default' popup mode defined introduced by tool bar. We
909         // should have changed QToolButton's default instead. Do that
910         // in 4.2.
911         setPopupMode(QToolButton::MenuButtonPopup);
912     }
913 #endif
914     setCheckable(action->isCheckable());
915     setChecked(action->isChecked());
916     setEnabled(action->isEnabled());
917     if (action->d_func()->fontSet)
918         setFont(action->font());
919 }
920
921
922 /*!
923   Returns the default action.
924
925   \sa setDefaultAction()
926  */
927 QAction *QToolButton::defaultAction() const
928 {
929     Q_D(const QToolButton);
930     return d->defaultAction;
931 }
932
933
934
935 /*!
936   \reimp
937  */
938 void QToolButton::nextCheckState()
939 {
940     Q_D(QToolButton);
941     if (!d->defaultAction)
942         QAbstractButton::nextCheckState();
943     else
944         d->defaultAction->trigger();
945 }
946
947 /*! \reimp */
948 bool QToolButton::event(QEvent *event)
949 {
950     switch(event->type()) {
951     case QEvent::HoverEnter:
952     case QEvent::HoverLeave:
953     case QEvent::HoverMove:
954     if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
955         d_func()->updateHoverControl(he->pos());
956         break;
957     default:
958         break;
959     }
960     return QAbstractButton::event(event);
961 }
962
963 QT_END_NAMESPACE
964
965 #include "moc_qtoolbutton.cpp"
966
967 #endif