1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qabstractbutton.h"
43 #include "qabstractitemview.h"
44 #include "qbuttongroup.h"
45 #include "qabstractbutton_p.h"
48 #include "qapplication.h"
51 #ifndef QT_NO_ACCESSIBILITY
52 #include "qaccessible.h"
57 #define AUTO_REPEAT_DELAY 300
58 #define AUTO_REPEAT_INTERVAL 100
60 Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets;
63 \class QAbstractButton
65 \brief The QAbstractButton class is the abstract base class of
66 button widgets, providing functionality common to buttons.
68 \ingroup abstractwidgets
70 This class implements an \e abstract button.
71 Subclasses of this class handle user actions, and specify how the button
74 QAbstractButton provides support for both push buttons and checkable
75 (toggle) buttons. Checkable buttons are implemented in the QRadioButton
76 and QCheckBox classes. Push buttons are implemented in the
77 QPushButton and QToolButton classes; these also provide toggle
80 Any button can display a label containing text and an icon. setText()
81 sets the text; setIcon() sets the icon. If a button is disabled, its label
82 is changed to give the button a "disabled" appearance.
84 If the button is a text button with a string containing an
85 ampersand ('&'), QAbstractButton automatically creates a shortcut
88 \snippet doc/src/snippets/code/src_gui_widgets_qabstractbutton.cpp 0
90 The \key Alt+C shortcut is assigned to the button, i.e., when the
91 user presses \key Alt+C the button will call animateClick(). See
92 the \l {QShortcut#mnemonic}{QShortcut} documentation for details
93 (to display an actual ampersand, use '&&').
95 You can also set a custom shortcut key using the setShortcut()
96 function. This is useful mostly for buttons that do not have any
97 text, because they have no automatic shortcut.
99 \snippet doc/src/snippets/code/src_gui_widgets_qabstractbutton.cpp 1
101 All of the buttons provided by Qt (QPushButton, QToolButton,
102 QCheckBox, and QRadioButton) can display both \l text and \l{icon}{icons}.
104 A button can be made the default button in a dialog are provided by
105 QPushButton::setDefault() and QPushButton::setAutoDefault().
107 QAbstractButton provides most of the states used for buttons:
111 \o isDown() indicates whether the button is \e pressed down.
113 \o isChecked() indicates whether the button is \e checked. Only
114 checkable buttons can be checked and unchecked (see below).
116 \o isEnabled() indicates whether the button can be pressed by the
119 \o setAutoRepeat() sets whether the button will auto-repeat if the
120 user holds it down. \l autoRepeatDelay and \l autoRepeatInterval
121 define how auto-repetition is done.
123 \o setCheckable() sets whether the button is a toggle button or not.
127 The difference between isDown() and isChecked() is as follows.
128 When the user clicks a toggle button to check it, the button is first
129 \e pressed then released into the \e checked state. When the user
130 clicks it again (to uncheck it), the button moves first to the
131 \e pressed state, then to the \e unchecked state (isChecked() and
132 isDown() are both false).
134 QAbstractButton provides four signals:
138 \o pressed() is emitted when the left mouse button is pressed while
139 the mouse cursor is inside the button.
141 \o released() is emitted when the left mouse button is released.
143 \o clicked() is emitted when the button is first pressed and then
144 released, when the shortcut key is typed, or when click() or
145 animateClick() is called.
147 \o toggled() is emitted when the state of a toggle button changes.
151 To subclass QAbstractButton, you must reimplement at least
152 paintEvent() to draw the button's outline and its text or pixmap. It
153 is generally advisable to reimplement sizeHint() as well, and
154 sometimes hitButton() (to determine whether a button press is within
155 the button). For buttons with more than two states (like tri-state
156 buttons), you will also have to reimplement checkStateSet() and
162 QAbstractButtonPrivate::QAbstractButtonPrivate(QSizePolicy::ControlType type)
164 #ifndef QT_NO_SHORTCUT
167 checkable(false), checked(false), autoRepeat(false), autoExclusive(false),
168 down(false), blockRefresh(false), pressed(false),
169 #ifndef QT_NO_BUTTONGROUP
172 autoRepeatDelay(AUTO_REPEAT_DELAY),
173 autoRepeatInterval(AUTO_REPEAT_INTERVAL),
177 #ifndef QT_NO_BUTTONGROUP
179 class QButtonGroupPrivate: public QObjectPrivate
181 Q_DECLARE_PUBLIC(QButtonGroup)
184 QButtonGroupPrivate():exclusive(true){}
185 QList<QAbstractButton *> buttonList;
186 QPointer<QAbstractButton> checkedButton;
187 void detectCheckedButton();
188 void notifyChecked(QAbstractButton *button);
190 QMap<QAbstractButton*, int> mapping;
193 QButtonGroup::QButtonGroup(QObject *parent)
194 : QObject(*new QButtonGroupPrivate, parent)
198 QButtonGroup::~QButtonGroup()
201 for (int i = 0; i < d->buttonList.count(); ++i)
202 d->buttonList.at(i)->d_func()->group = 0;
206 bool QButtonGroup::exclusive() const
208 Q_D(const QButtonGroup);
212 void QButtonGroup::setExclusive(bool exclusive)
215 d->exclusive = exclusive;
219 // TODO: Qt 5: Merge with addButton(QAbstractButton *button, int id)
220 void QButtonGroup::addButton(QAbstractButton *button)
222 addButton(button, -1);
225 void QButtonGroup::addButton(QAbstractButton *button, int id)
228 if (QButtonGroup *previous = button->d_func()->group)
229 previous->removeButton(button);
230 button->d_func()->group = this;
231 d->buttonList.append(button);
233 QList<int> ids = d->mapping.values();
235 d->mapping[button] = -2;
238 d->mapping[button] = ids.first()-1;
241 d->mapping[button] = id;
244 if (d->exclusive && button->isChecked())
245 button->d_func()->notifyChecked();
248 void QButtonGroup::removeButton(QAbstractButton *button)
251 if (d->checkedButton == button) {
252 d->detectCheckedButton();
254 if (button->d_func()->group == this) {
255 button->d_func()->group = 0;
256 d->buttonList.removeAll(button);
257 d->mapping.remove(button);
261 QList<QAbstractButton*> QButtonGroup::buttons() const
263 Q_D(const QButtonGroup);
264 return d->buttonList;
267 QAbstractButton *QButtonGroup::checkedButton() const
269 Q_D(const QButtonGroup);
270 return d->checkedButton;
273 QAbstractButton *QButtonGroup::button(int id) const
275 Q_D(const QButtonGroup);
276 return d->mapping.key(id);
279 void QButtonGroup::setId(QAbstractButton *button, int id)
282 if (button && id != -1)
283 d->mapping[button] = id;
286 int QButtonGroup::id(QAbstractButton *button) const
288 Q_D(const QButtonGroup);
289 return d->mapping.value(button, -1);
292 int QButtonGroup::checkedId() const
294 Q_D(const QButtonGroup);
295 return d->mapping.value(d->checkedButton, -1);
298 // detect a checked button other than the current one
299 void QButtonGroupPrivate::detectCheckedButton()
301 QAbstractButton *previous = checkedButton;
305 for (int i = 0; i < buttonList.count(); i++) {
306 if (buttonList.at(i) != previous && buttonList.at(i)->isChecked()) {
307 checkedButton = buttonList.at(i);
313 #endif // QT_NO_BUTTONGROUP
315 QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const
317 #ifndef QT_NO_BUTTONGROUP
319 return group->d_func()->buttonList;
322 QList<QAbstractButton*>candidates = parent->findChildren<QAbstractButton *>();
324 for (int i = candidates.count() - 1; i >= 0; --i) {
325 QAbstractButton *candidate = candidates.at(i);
326 if (!candidate->autoExclusive()
327 #ifndef QT_NO_BUTTONGROUP
328 || candidate->group()
331 candidates.removeAt(i);
337 QAbstractButton *QAbstractButtonPrivate::queryCheckedButton() const
339 #ifndef QT_NO_BUTTONGROUP
341 return group->d_func()->checkedButton;
344 Q_Q(const QAbstractButton);
345 QList<QAbstractButton *> buttonList = queryButtonList();
346 if (!autoExclusive || buttonList.count() == 1) // no group
349 for (int i = 0; i < buttonList.count(); ++i) {
350 QAbstractButton *b = buttonList.at(i);
351 if (b->d_func()->checked && b != q)
354 return checked ? const_cast<QAbstractButton *>(q) : 0;
357 void QAbstractButtonPrivate::notifyChecked()
359 #ifndef QT_NO_BUTTONGROUP
360 Q_Q(QAbstractButton);
362 QAbstractButton *previous = group->d_func()->checkedButton;
363 group->d_func()->checkedButton = q;
364 if (group->d_func()->exclusive && previous && previous != q)
365 previous->nextCheckState();
369 if (QAbstractButton *b = queryCheckedButton())
370 b->setChecked(false);
374 void QAbstractButtonPrivate::moveFocus(int key)
376 QList<QAbstractButton *> buttonList = queryButtonList();;
377 #ifndef QT_NO_BUTTONGROUP
378 bool exclusive = group ? group->d_func()->exclusive : autoExclusive;
380 bool exclusive = autoExclusive;
382 QWidget *f = QApplication::focusWidget();
383 QAbstractButton *fb = qobject_cast<QAbstractButton *>(f);
384 if (!fb || !buttonList.contains(fb))
387 QAbstractButton *candidate = 0;
389 QRect target = f->rect().translated(f->mapToGlobal(QPoint(0,0)));
390 QPoint goal = target.center();
391 uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
393 for (int i = 0; i < buttonList.count(); ++i) {
394 QAbstractButton *button = buttonList.at(i);
395 if (button != f && button->window() == f->window() && button->isEnabled() && !button->isHidden() &&
396 (autoExclusive || (button->focusPolicy() & focus_flag) == focus_flag)) {
397 QRect buttonRect = button->rect().translated(button->mapToGlobal(QPoint(0,0)));
398 QPoint p = buttonRect.center();
400 //Priority to widgets that overlap on the same coordinate.
401 //In that case, the distance in the direction will be used as significant score,
402 //take also in account orthogonal distance in case two widget are in the same distance.
404 if ((buttonRect.x() < target.right() && target.x() < buttonRect.right())
405 && (key == Qt::Key_Up || key == Qt::Key_Down)) {
406 //one item's is at the vertical of the other
407 score = (qAbs(p.y() - goal.y()) << 16) + qAbs(p.x() - goal.x());
408 } else if ((buttonRect.y() < target.bottom() && target.y() < buttonRect.bottom())
409 && (key == Qt::Key_Left || key == Qt::Key_Right) ) {
410 //one item's is at the horizontal of the other
411 score = (qAbs(p.x() - goal.x()) << 16) + qAbs(p.y() - goal.y());
413 score = (1 << 30) + (p.y() - goal.y()) * (p.y() - goal.y()) + (p.x() - goal.x()) * (p.x() - goal.x());
416 if (score > bestScore && candidate)
421 if (p.y() < goal.y()) {
427 if (p.y() > goal.y()) {
433 if (p.x() < goal.x()) {
439 if (p.x() > goal.x()) {
449 #ifdef QT_KEYPAD_NAVIGATION
450 && !QApplication::keypadNavigationEnabled()
453 && fb->d_func()->checked
454 && candidate->d_func()->checkable)
458 if (key == Qt::Key_Up || key == Qt::Key_Left)
459 candidate->setFocus(Qt::BacktabFocusReason);
461 candidate->setFocus(Qt::TabFocusReason);
465 void QAbstractButtonPrivate::fixFocusPolicy()
467 Q_Q(QAbstractButton);
468 #ifndef QT_NO_BUTTONGROUP
469 if (!group && !autoExclusive)
475 QList<QAbstractButton *> buttonList = queryButtonList();
476 for (int i = 0; i < buttonList.count(); ++i) {
477 QAbstractButton *b = buttonList.at(i);
478 if (!b->isCheckable())
480 b->setFocusPolicy((Qt::FocusPolicy) ((b == q || !q->isCheckable())
481 ? (b->focusPolicy() | Qt::TabFocus)
482 : (b->focusPolicy() & ~Qt::TabFocus)));
486 void QAbstractButtonPrivate::init()
488 Q_Q(QAbstractButton);
490 q->setFocusPolicy(Qt::FocusPolicy(q->style()->styleHint(QStyle::SH_Button_FocusPolicy)));
491 q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, controlType));
492 q->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
493 q->setForegroundRole(QPalette::ButtonText);
494 q->setBackgroundRole(QPalette::Button);
497 void QAbstractButtonPrivate::refresh()
499 Q_Q(QAbstractButton);
504 #ifndef QT_NO_ACCESSIBILITY
505 QAccessible::updateAccessibility(q, 0, QAccessible::StateChanged);
509 void QAbstractButtonPrivate::click()
511 Q_Q(QAbstractButton);
515 bool changeState = true;
516 if (checked && queryCheckedButton() == q) {
517 // the checked button of an exclusive or autoexclusive group cannot be unchecked
518 #ifndef QT_NO_BUTTONGROUP
519 if (group ? group->d_func()->exclusive : autoExclusive)
526 QPointer<QAbstractButton> guard(q);
532 blockRefresh = false;
534 q->repaint(); //flush paint event before invoking potentially expensive operation
535 QApplication::flush();
542 void QAbstractButtonPrivate::emitClicked()
544 Q_Q(QAbstractButton);
545 QPointer<QAbstractButton> guard(q);
546 emit q->clicked(checked);
547 #ifndef QT_NO_BUTTONGROUP
548 if (guard && group) {
549 emit group->buttonClicked(group->id(q));
551 emit group->buttonClicked(q);
556 void QAbstractButtonPrivate::emitPressed()
558 Q_Q(QAbstractButton);
559 QPointer<QAbstractButton> guard(q);
561 #ifndef QT_NO_BUTTONGROUP
562 if (guard && group) {
563 emit group->buttonPressed(group->id(q));
565 emit group->buttonPressed(q);
570 void QAbstractButtonPrivate::emitReleased()
572 Q_Q(QAbstractButton);
573 QPointer<QAbstractButton> guard(q);
575 #ifndef QT_NO_BUTTONGROUP
576 if (guard && group) {
577 emit group->buttonReleased(group->id(q));
579 emit group->buttonReleased(q);
585 Constructs an abstract button with a \a parent.
587 QAbstractButton::QAbstractButton(QWidget *parent)
588 : QWidget(*new QAbstractButtonPrivate, parent, 0)
590 Q_D(QAbstractButton);
597 QAbstractButton::~QAbstractButton()
599 #ifndef QT_NO_BUTTONGROUP
600 Q_D(QAbstractButton);
602 d->group->removeButton(this);
609 QAbstractButton::QAbstractButton(QAbstractButtonPrivate &dd, QWidget *parent)
610 : QWidget(dd, parent, 0)
612 Q_D(QAbstractButton);
617 \property QAbstractButton::text
618 \brief the text shown on the button
620 If the button has no text, the text() function will return a an empty
623 If the text contains an ampersand character ('&'), a shortcut is
624 automatically created for it. The character that follows the '&' will
625 be used as the shortcut key. Any previous shortcut will be
626 overwritten, or cleared if no shortcut is defined by the text. See the
627 \l {QShortcut#mnemonic}{QShortcut} documentation for details (to
628 display an actual ampersand, use '&&').
630 There is no default text.
633 void QAbstractButton::setText(const QString &text)
635 Q_D(QAbstractButton);
639 #ifndef QT_NO_SHORTCUT
640 QKeySequence newMnemonic = QKeySequence::mnemonic(text);
641 setShortcut(newMnemonic);
643 d->sizeHint = QSize();
646 #ifndef QT_NO_ACCESSIBILITY
647 QAccessible::updateAccessibility(this, 0, QAccessible::NameChanged);
651 QString QAbstractButton::text() const
653 Q_D(const QAbstractButton);
659 \property QAbstractButton::icon
660 \brief the icon shown on the button
662 The icon's default size is defined by the GUI style, but can be
663 adjusted by setting the \l iconSize property.
665 void QAbstractButton::setIcon(const QIcon &icon)
667 Q_D(QAbstractButton);
669 d->sizeHint = QSize();
674 QIcon QAbstractButton::icon() const
676 Q_D(const QAbstractButton);
680 #ifndef QT_NO_SHORTCUT
682 \property QAbstractButton::shortcut
683 \brief the mnemonic associated with the button
686 void QAbstractButton::setShortcut(const QKeySequence &key)
688 Q_D(QAbstractButton);
689 if (d->shortcutId != 0)
690 releaseShortcut(d->shortcutId);
692 d->shortcutId = grabShortcut(key);
695 QKeySequence QAbstractButton::shortcut() const
697 Q_D(const QAbstractButton);
700 #endif // QT_NO_SHORTCUT
703 \property QAbstractButton::checkable
704 \brief whether the button is checkable
706 By default, the button is not checkable.
710 void QAbstractButton::setCheckable(bool checkable)
712 Q_D(QAbstractButton);
713 if (d->checkable == checkable)
716 d->checkable = checkable;
720 bool QAbstractButton::isCheckable() const
722 Q_D(const QAbstractButton);
727 \property QAbstractButton::checked
728 \brief whether the button is checked
730 Only checkable buttons can be checked. By default, the button is unchecked.
734 void QAbstractButton::setChecked(bool checked)
736 Q_D(QAbstractButton);
737 if (!d->checkable || d->checked == checked) {
738 if (!d->blockRefresh)
743 if (!checked && d->queryCheckedButton() == this) {
744 // the checked button of an exclusive or autoexclusive group cannot be unchecked
745 #ifndef QT_NO_BUTTONGROUP
746 if (d->group ? d->group->d_func()->exclusive : d->autoExclusive)
749 d->group->d_func()->detectCheckedButton();
751 if (d->autoExclusive)
756 QPointer<QAbstractButton> guard(this);
758 d->checked = checked;
759 if (!d->blockRefresh)
763 if (guard && checked)
766 emit toggled(checked);
769 bool QAbstractButton::isChecked() const
771 Q_D(const QAbstractButton);
776 \property QAbstractButton::down
777 \brief whether the button is pressed down
779 If this property is true, the button is pressed down. The signals
780 pressed() and clicked() are not emitted if you set this property
781 to true. The default is false.
784 void QAbstractButton::setDown(bool down)
786 Q_D(QAbstractButton);
791 if (d->autoRepeat && d->down)
792 d->repeatTimer.start(d->autoRepeatDelay, this);
794 d->repeatTimer.stop();
797 bool QAbstractButton::isDown() const
799 Q_D(const QAbstractButton);
804 \property QAbstractButton::autoRepeat
805 \brief whether autoRepeat is enabled
807 If autoRepeat is enabled, then the pressed(), released(), and clicked() signals are emitted at
808 regular intervals when the button is down. autoRepeat is off by default.
809 The initial delay and the repetition interval are defined in milliseconds by \l
810 autoRepeatDelay and \l autoRepeatInterval.
812 Note: If a button is pressed down by a shortcut key, then auto-repeat is enabled and timed by the
813 system and not by this class. The pressed(), released(), and clicked() signals will be emitted
814 like in the normal case.
817 void QAbstractButton::setAutoRepeat(bool autoRepeat)
819 Q_D(QAbstractButton);
820 if (d->autoRepeat == autoRepeat)
822 d->autoRepeat = autoRepeat;
823 if (d->autoRepeat && d->down)
824 d->repeatTimer.start(d->autoRepeatDelay, this);
826 d->repeatTimer.stop();
829 bool QAbstractButton::autoRepeat() const
831 Q_D(const QAbstractButton);
832 return d->autoRepeat;
836 \property QAbstractButton::autoRepeatDelay
837 \brief the initial delay of auto-repetition
840 If \l autoRepeat is enabled, then autoRepeatDelay defines the initial
841 delay in milliseconds before auto-repetition kicks in.
843 \sa autoRepeat, autoRepeatInterval
846 void QAbstractButton::setAutoRepeatDelay(int autoRepeatDelay)
848 Q_D(QAbstractButton);
849 d->autoRepeatDelay = autoRepeatDelay;
852 int QAbstractButton::autoRepeatDelay() const
854 Q_D(const QAbstractButton);
855 return d->autoRepeatDelay;
859 \property QAbstractButton::autoRepeatInterval
860 \brief the interval of auto-repetition
863 If \l autoRepeat is enabled, then autoRepeatInterval defines the
864 length of the auto-repetition interval in millisecons.
866 \sa autoRepeat, autoRepeatDelay
869 void QAbstractButton::setAutoRepeatInterval(int autoRepeatInterval)
871 Q_D(QAbstractButton);
872 d->autoRepeatInterval = autoRepeatInterval;
875 int QAbstractButton::autoRepeatInterval() const
877 Q_D(const QAbstractButton);
878 return d->autoRepeatInterval;
884 \property QAbstractButton::autoExclusive
885 \brief whether auto-exclusivity is enabled
887 If auto-exclusivity is enabled, checkable buttons that belong to the
888 same parent widget behave as if they were part of the same
889 exclusive button group. In an exclusive button group, only one button
890 can be checked at any time; checking another button automatically
891 unchecks the previously checked one.
893 The property has no effect on buttons that belong to a button
896 autoExclusive is off by default, except for radio buttons.
900 void QAbstractButton::setAutoExclusive(bool autoExclusive)
902 Q_D(QAbstractButton);
903 d->autoExclusive = autoExclusive;
906 bool QAbstractButton::autoExclusive() const
908 Q_D(const QAbstractButton);
909 return d->autoExclusive;
912 #ifndef QT_NO_BUTTONGROUP
914 Returns the group that this button belongs to.
916 If the button is not a member of any QButtonGroup, this function
921 QButtonGroup *QAbstractButton::group() const
923 Q_D(const QAbstractButton);
926 #endif // QT_NO_BUTTONGROUP
929 Performs an animated click: the button is pressed immediately, and
930 released \a msec milliseconds later (the default is 100 ms).
932 Calling this function again before the button was released will reset
935 All signals associated with a click are emitted as appropriate.
937 This function does nothing if the button is \link setEnabled()
942 void QAbstractButton::animateClick(int msec)
946 Q_D(QAbstractButton);
947 if (d->checkable && focusPolicy() & Qt::ClickFocus)
950 repaint(); //flush paint event before invoking potentially expensive operation
951 QApplication::flush();
952 if (!d->animateTimer.isActive())
954 d->animateTimer.start(msec, this);
960 All the usual signals associated with a click are emitted as
961 appropriate. If the button is checkable, the state of the button is
964 This function does nothing if the button is \link setEnabled()
969 void QAbstractButton::click()
973 Q_D(QAbstractButton);
974 QPointer<QAbstractButton> guard(this);
987 /*! \fn void QAbstractButton::toggle()
989 Toggles the state of a checkable button.
993 void QAbstractButton::toggle()
995 Q_D(QAbstractButton);
996 setChecked(!d->checked);
1000 /*! This virtual handler is called when setChecked() was called,
1001 unless it was called from within nextCheckState(). It allows
1002 subclasses to reset their intermediate button states.
1004 \sa nextCheckState()
1006 void QAbstractButton::checkStateSet()
1010 /*! This virtual handler is called when a button is clicked. The
1011 default implementation calls setChecked(!isChecked()) if the button
1012 isCheckable(). It allows subclasses to implement intermediate button
1017 void QAbstractButton::nextCheckState()
1020 setChecked(!isChecked());
1024 Returns true if \a pos is inside the clickable button rectangle;
1025 otherwise returns false.
1027 By default, the clickable area is the entire widget. Subclasses
1028 may reimplement this function to provide support for clickable
1029 areas of different shapes and sizes.
1031 bool QAbstractButton::hitButton(const QPoint &pos) const
1033 return rect().contains(pos);
1037 bool QAbstractButton::event(QEvent *e)
1039 // as opposed to other widgets, disabled buttons accept mouse
1040 // events. This avoids surprising click-through scenarios
1043 case QEvent::TabletPress:
1044 case QEvent::TabletRelease:
1045 case QEvent::TabletMove:
1046 case QEvent::MouseButtonPress:
1047 case QEvent::MouseButtonRelease:
1048 case QEvent::MouseButtonDblClick:
1049 case QEvent::MouseMove:
1050 case QEvent::HoverMove:
1051 case QEvent::HoverEnter:
1052 case QEvent::HoverLeave:
1053 case QEvent::ContextMenu:
1054 #ifndef QT_NO_WHEELEVENT
1063 #ifndef QT_NO_SHORTCUT
1064 if (e->type() == QEvent::Shortcut) {
1065 Q_D(QAbstractButton);
1066 QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
1067 if (d->shortcutId != se->shortcutId())
1069 if (!se->isAmbiguous()) {
1070 if (!d->animateTimer.isActive())
1073 if (focusPolicy() != Qt::NoFocus)
1074 setFocus(Qt::ShortcutFocusReason);
1075 window()->setAttribute(Qt::WA_KeyboardFocusChange);
1080 return QWidget::event(e);
1084 void QAbstractButton::mousePressEvent(QMouseEvent *e)
1086 Q_D(QAbstractButton);
1087 if (e->button() != Qt::LeftButton) {
1091 if (hitButton(e->pos())) {
1094 repaint(); //flush paint event before invoking potentially expensive operation
1095 QApplication::flush();
1104 void QAbstractButton::mouseReleaseEvent(QMouseEvent *e)
1106 Q_D(QAbstractButton);
1109 if (e->button() != Qt::LeftButton) {
1119 if (hitButton(e->pos())) {
1120 d->repeatTimer.stop();
1130 void QAbstractButton::mouseMoveEvent(QMouseEvent *e)
1132 Q_D(QAbstractButton);
1133 if (!(e->buttons() & Qt::LeftButton) || !d->pressed) {
1138 if (hitButton(e->pos()) != d->down) {
1140 repaint(); //flush paint event before invoking potentially expensive operation
1141 QApplication::flush();
1147 } else if (!hitButton(e->pos())) {
1153 void QAbstractButton::keyPressEvent(QKeyEvent *e)
1155 Q_D(QAbstractButton);
1159 case Qt::Key_Return:
1162 case Qt::Key_Select:
1164 if (!e->isAutoRepeat()) {
1166 repaint(); //flush paint event before invoking potentially expensive operation
1167 QApplication::flush();
1177 #ifdef QT_KEYPAD_NAVIGATION
1178 if ((QApplication::keypadNavigationEnabled()
1179 && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right))
1180 || (!QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional
1181 || (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down))) {
1187 if (d->autoExclusive
1188 #ifndef QT_NO_BUTTONGROUP
1191 #ifndef QT_NO_ITEMVIEWS
1192 || ((pw = parentWidget()) && qobject_cast<QAbstractItemView *>(pw->parentWidget()))
1195 // ### Using qobject_cast to check if the parent is a viewport of
1196 // QAbstractItemView is a crude hack, and should be revisited and
1197 // cleaned up when fixing task 194373. It's here to ensure that we
1198 // keep compatibility outside QAbstractItemView.
1199 d->moveFocus(e->key());
1200 if (hasFocus()) // nothing happend, propagate
1203 focusNextPrevChild(next);
1206 case Qt::Key_Escape:
1209 repaint(); //flush paint event before invoking potentially expensive operation
1210 QApplication::flush();
1221 void QAbstractButton::keyReleaseEvent(QKeyEvent *e)
1223 Q_D(QAbstractButton);
1225 if (!e->isAutoRepeat())
1226 d->repeatTimer.stop();
1229 case Qt::Key_Select:
1231 if (!e->isAutoRepeat() && d->down)
1241 void QAbstractButton::timerEvent(QTimerEvent *e)
1243 Q_D(QAbstractButton);
1244 if (e->timerId() == d->repeatTimer.timerId()) {
1245 d->repeatTimer.start(d->autoRepeatInterval, this);
1247 QPointer<QAbstractButton> guard(this);
1256 } else if (e->timerId() == d->animateTimer.timerId()) {
1257 d->animateTimer.stop();
1263 void QAbstractButton::focusInEvent(QFocusEvent *e)
1265 Q_D(QAbstractButton);
1266 #ifdef QT_KEYPAD_NAVIGATION
1267 if (!QApplication::keypadNavigationEnabled())
1269 d->fixFocusPolicy();
1270 QWidget::focusInEvent(e);
1274 void QAbstractButton::focusOutEvent(QFocusEvent *e)
1276 Q_D(QAbstractButton);
1277 if (e->reason() != Qt::PopupFocusReason)
1279 QWidget::focusOutEvent(e);
1283 void QAbstractButton::changeEvent(QEvent *e)
1285 Q_D(QAbstractButton);
1286 switch (e->type()) {
1287 case QEvent::EnabledChange:
1292 d->sizeHint = QSize();
1295 QWidget::changeEvent(e);
1299 \fn void QAbstractButton::paintEvent(QPaintEvent *e)
1304 \fn void QAbstractButton::pressed()
1306 This signal is emitted when the button is pressed down.
1308 \sa released(), clicked()
1312 \fn void QAbstractButton::released()
1314 This signal is emitted when the button is released.
1316 \sa pressed(), clicked(), toggled()
1320 \fn void QAbstractButton::clicked(bool checked)
1322 This signal is emitted when the button is activated (i.e. pressed down
1323 then released while the mouse cursor is inside the button), when the
1324 shortcut key is typed, or when click() or animateClick() is called.
1325 Notably, this signal is \e not emitted if you call setDown(),
1326 setChecked() or toggle().
1328 If the button is checkable, \a checked is true if the button is
1329 checked, or false if the button is unchecked.
1331 \sa pressed(), released(), toggled()
1335 \fn void QAbstractButton::toggled(bool checked)
1337 This signal is emitted whenever a checkable button changes its state.
1338 \a checked is true if the button is checked, or false if the button is
1341 This may be the result of a user action, click() slot activation,
1342 or because setChecked() was called.
1344 The states of buttons in exclusive button groups are updated before this
1345 signal is emitted. This means that slots can act on either the "off"
1346 signal or the "on" signal emitted by the buttons in the group whose
1347 states have changed.
1349 For example, a slot that reacts to signals emitted by newly checked
1350 buttons but which ignores signals from buttons that have been unchecked
1351 can be implemented using the following pattern:
1353 \snippet doc/src/snippets/code/src_gui_widgets_qabstractbutton.cpp 2
1355 Button groups can be created using the QButtonGroup class, and
1356 updates to the button states monitored with the
1357 \l{QButtonGroup::buttonClicked()} signal.
1359 \sa checked, clicked()
1363 \property QAbstractButton::iconSize
1364 \brief the icon size used for this button.
1366 The default size is defined by the GUI style. This is a maximum
1367 size for the icons. Smaller icons will not be scaled up.
1370 QSize QAbstractButton::iconSize() const
1372 Q_D(const QAbstractButton);
1373 if (d->iconSize.isValid())
1375 int e = style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, this);
1379 void QAbstractButton::setIconSize(const QSize &size)
1381 Q_D(QAbstractButton);
1382 if (d->iconSize == size)
1386 d->sizeHint = QSize();
1398 QIcon *QAbstractButton::iconSet() const
1400 Q_D(const QAbstractButton);
1401 if (!d->icon.isNull())
1402 return const_cast<QIcon *>(&d->icon);
1407 Use QAbstractButton(QWidget *) instead.
1409 Call setObjectName() if you want to specify an object name, and
1410 setParent() if you want to set the window flags.
1412 QAbstractButton::QAbstractButton(QWidget *parent, const char *name, Qt::WindowFlags f)
1413 : QWidget(*new QAbstractButtonPrivate, parent, f)
1415 Q_D(QAbstractButton);
1416 setObjectName(QString::fromAscii(name));
1420 /*! \fn bool QAbstractButton::isOn() const
1422 Use isChecked() instead.
1426 \fn QPixmap *QAbstractButton::pixmap() const
1428 This compatibility function always returns 0.
1433 /*! \fn void QAbstractButton::setPixmap(const QPixmap &p)
1435 Use setIcon() instead.
1438 /*! \fn void QAbstractButton::setIconSet(const QIcon &icon)
1440 Use setIcon() instead.
1443 /*! \fn void QAbstractButton::setOn(bool b)
1445 Use setChecked() instead.
1448 /*! \fn bool QAbstractButton::isToggleButton() const
1450 Use isCheckable() instead.
1454 \fn void QAbstractButton::setToggleButton(bool b)
1456 Use setCheckable() instead.
1459 /*! \fn void QAbstractButton::setAccel(const QKeySequence &key)
1461 Use setShortcut() instead.
1464 /*! \fn QKeySequence QAbstractButton::accel() const
1466 Use shortcut() instead.