1 /****************************************************************************
3 ** Copyright (C) 2012 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
71 This class implements an \e abstract button.
72 Subclasses of this class handle user actions, and specify how the button
75 QAbstractButton provides support for both push buttons and checkable
76 (toggle) buttons. Checkable buttons are implemented in the QRadioButton
77 and QCheckBox classes. Push buttons are implemented in the
78 QPushButton and QToolButton classes; these also provide toggle
81 Any button can display a label containing text and an icon. setText()
82 sets the text; setIcon() sets the icon. If a button is disabled, its label
83 is changed to give the button a "disabled" appearance.
85 If the button is a text button with a string containing an
86 ampersand ('&'), QAbstractButton automatically creates a shortcut
89 \snippet doc/src/snippets/code/src_gui_widgets_qabstractbutton.cpp 0
91 The \key Alt+C shortcut is assigned to the button, i.e., when the
92 user presses \key Alt+C the button will call animateClick(). See
93 the \l {QShortcut#mnemonic}{QShortcut} documentation for details
94 (to display an actual ampersand, use '&&').
96 You can also set a custom shortcut key using the setShortcut()
97 function. This is useful mostly for buttons that do not have any
98 text, because they have no automatic shortcut.
100 \snippet doc/src/snippets/code/src_gui_widgets_qabstractbutton.cpp 1
102 All of the buttons provided by Qt (QPushButton, QToolButton,
103 QCheckBox, and QRadioButton) can display both \l text and \l{icon}{icons}.
105 A button can be made the default button in a dialog are provided by
106 QPushButton::setDefault() and QPushButton::setAutoDefault().
108 QAbstractButton provides most of the states used for buttons:
112 \o isDown() indicates whether the button is \e pressed down.
114 \o isChecked() indicates whether the button is \e checked. Only
115 checkable buttons can be checked and unchecked (see below).
117 \o isEnabled() indicates whether the button can be pressed by the
120 \o setAutoRepeat() sets whether the button will auto-repeat if the
121 user holds it down. \l autoRepeatDelay and \l autoRepeatInterval
122 define how auto-repetition is done.
124 \o setCheckable() sets whether the button is a toggle button or not.
128 The difference between isDown() and isChecked() is as follows.
129 When the user clicks a toggle button to check it, the button is first
130 \e pressed then released into the \e checked state. When the user
131 clicks it again (to uncheck it), the button moves first to the
132 \e pressed state, then to the \e unchecked state (isChecked() and
133 isDown() are both false).
135 QAbstractButton provides four signals:
139 \o pressed() is emitted when the left mouse button is pressed while
140 the mouse cursor is inside the button.
142 \o released() is emitted when the left mouse button is released.
144 \o clicked() is emitted when the button is first pressed and then
145 released, when the shortcut key is typed, or when click() or
146 animateClick() is called.
148 \o toggled() is emitted when the state of a toggle button changes.
152 To subclass QAbstractButton, you must reimplement at least
153 paintEvent() to draw the button's outline and its text or pixmap. It
154 is generally advisable to reimplement sizeHint() as well, and
155 sometimes hitButton() (to determine whether a button press is within
156 the button). For buttons with more than two states (like tri-state
157 buttons), you will also have to reimplement checkStateSet() and
163 QAbstractButtonPrivate::QAbstractButtonPrivate(QSizePolicy::ControlType type)
165 #ifndef QT_NO_SHORTCUT
168 checkable(false), checked(false), autoRepeat(false), autoExclusive(false),
169 down(false), blockRefresh(false), pressed(false),
170 #ifndef QT_NO_BUTTONGROUP
173 autoRepeatDelay(AUTO_REPEAT_DELAY),
174 autoRepeatInterval(AUTO_REPEAT_INTERVAL),
178 #ifndef QT_NO_BUTTONGROUP
180 class QButtonGroupPrivate: public QObjectPrivate
182 Q_DECLARE_PUBLIC(QButtonGroup)
185 QButtonGroupPrivate():exclusive(true){}
186 QList<QAbstractButton *> buttonList;
187 QPointer<QAbstractButton> checkedButton;
188 void detectCheckedButton();
189 void notifyChecked(QAbstractButton *button);
191 QMap<QAbstractButton*, int> mapping;
194 QButtonGroup::QButtonGroup(QObject *parent)
195 : QObject(*new QButtonGroupPrivate, parent)
199 QButtonGroup::~QButtonGroup()
202 for (int i = 0; i < d->buttonList.count(); ++i)
203 d->buttonList.at(i)->d_func()->group = 0;
207 bool QButtonGroup::exclusive() const
209 Q_D(const QButtonGroup);
213 void QButtonGroup::setExclusive(bool exclusive)
216 d->exclusive = exclusive;
220 // TODO: Qt 5: Merge with addButton(QAbstractButton *button, int id)
221 void QButtonGroup::addButton(QAbstractButton *button)
223 addButton(button, -1);
226 void QButtonGroup::addButton(QAbstractButton *button, int id)
229 if (QButtonGroup *previous = button->d_func()->group)
230 previous->removeButton(button);
231 button->d_func()->group = this;
232 d->buttonList.append(button);
234 QList<int> ids = d->mapping.values();
236 d->mapping[button] = -2;
239 d->mapping[button] = ids.first()-1;
242 d->mapping[button] = id;
245 if (d->exclusive && button->isChecked())
246 button->d_func()->notifyChecked();
249 void QButtonGroup::removeButton(QAbstractButton *button)
252 if (d->checkedButton == button) {
253 d->detectCheckedButton();
255 if (button->d_func()->group == this) {
256 button->d_func()->group = 0;
257 d->buttonList.removeAll(button);
258 d->mapping.remove(button);
262 QList<QAbstractButton*> QButtonGroup::buttons() const
264 Q_D(const QButtonGroup);
265 return d->buttonList;
268 QAbstractButton *QButtonGroup::checkedButton() const
270 Q_D(const QButtonGroup);
271 return d->checkedButton;
274 QAbstractButton *QButtonGroup::button(int id) const
276 Q_D(const QButtonGroup);
277 return d->mapping.key(id);
280 void QButtonGroup::setId(QAbstractButton *button, int id)
283 if (button && id != -1)
284 d->mapping[button] = id;
287 int QButtonGroup::id(QAbstractButton *button) const
289 Q_D(const QButtonGroup);
290 return d->mapping.value(button, -1);
293 int QButtonGroup::checkedId() const
295 Q_D(const QButtonGroup);
296 return d->mapping.value(d->checkedButton, -1);
299 // detect a checked button other than the current one
300 void QButtonGroupPrivate::detectCheckedButton()
302 QAbstractButton *previous = checkedButton;
306 for (int i = 0; i < buttonList.count(); i++) {
307 if (buttonList.at(i) != previous && buttonList.at(i)->isChecked()) {
308 checkedButton = buttonList.at(i);
314 #endif // QT_NO_BUTTONGROUP
316 QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const
318 #ifndef QT_NO_BUTTONGROUP
320 return group->d_func()->buttonList;
323 QList<QAbstractButton*>candidates = parent->findChildren<QAbstractButton *>();
325 for (int i = candidates.count() - 1; i >= 0; --i) {
326 QAbstractButton *candidate = candidates.at(i);
327 if (!candidate->autoExclusive()
328 #ifndef QT_NO_BUTTONGROUP
329 || candidate->group()
332 candidates.removeAt(i);
338 QAbstractButton *QAbstractButtonPrivate::queryCheckedButton() const
340 #ifndef QT_NO_BUTTONGROUP
342 return group->d_func()->checkedButton;
345 Q_Q(const QAbstractButton);
346 QList<QAbstractButton *> buttonList = queryButtonList();
347 if (!autoExclusive || buttonList.count() == 1) // no group
350 for (int i = 0; i < buttonList.count(); ++i) {
351 QAbstractButton *b = buttonList.at(i);
352 if (b->d_func()->checked && b != q)
355 return checked ? const_cast<QAbstractButton *>(q) : 0;
358 void QAbstractButtonPrivate::notifyChecked()
360 #ifndef QT_NO_BUTTONGROUP
361 Q_Q(QAbstractButton);
363 QAbstractButton *previous = group->d_func()->checkedButton;
364 group->d_func()->checkedButton = q;
365 if (group->d_func()->exclusive && previous && previous != q)
366 previous->nextCheckState();
370 if (QAbstractButton *b = queryCheckedButton())
371 b->setChecked(false);
375 void QAbstractButtonPrivate::moveFocus(int key)
377 QList<QAbstractButton *> buttonList = queryButtonList();;
378 #ifndef QT_NO_BUTTONGROUP
379 bool exclusive = group ? group->d_func()->exclusive : autoExclusive;
381 bool exclusive = autoExclusive;
383 QWidget *f = QApplication::focusWidget();
384 QAbstractButton *fb = qobject_cast<QAbstractButton *>(f);
385 if (!fb || !buttonList.contains(fb))
388 QAbstractButton *candidate = 0;
390 QRect target = f->rect().translated(f->mapToGlobal(QPoint(0,0)));
391 QPoint goal = target.center();
392 uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
394 for (int i = 0; i < buttonList.count(); ++i) {
395 QAbstractButton *button = buttonList.at(i);
396 if (button != f && button->window() == f->window() && button->isEnabled() && !button->isHidden() &&
397 (autoExclusive || (button->focusPolicy() & focus_flag) == focus_flag)) {
398 QRect buttonRect = button->rect().translated(button->mapToGlobal(QPoint(0,0)));
399 QPoint p = buttonRect.center();
401 //Priority to widgets that overlap on the same coordinate.
402 //In that case, the distance in the direction will be used as significant score,
403 //take also in account orthogonal distance in case two widget are in the same distance.
405 if ((buttonRect.x() < target.right() && target.x() < buttonRect.right())
406 && (key == Qt::Key_Up || key == Qt::Key_Down)) {
407 //one item's is at the vertical of the other
408 score = (qAbs(p.y() - goal.y()) << 16) + qAbs(p.x() - goal.x());
409 } else if ((buttonRect.y() < target.bottom() && target.y() < buttonRect.bottom())
410 && (key == Qt::Key_Left || key == Qt::Key_Right) ) {
411 //one item's is at the horizontal of the other
412 score = (qAbs(p.x() - goal.x()) << 16) + qAbs(p.y() - goal.y());
414 score = (1 << 30) + (p.y() - goal.y()) * (p.y() - goal.y()) + (p.x() - goal.x()) * (p.x() - goal.x());
417 if (score > bestScore && candidate)
422 if (p.y() < goal.y()) {
428 if (p.y() > goal.y()) {
434 if (p.x() < goal.x()) {
440 if (p.x() > goal.x()) {
450 #ifdef QT_KEYPAD_NAVIGATION
451 && !QApplication::keypadNavigationEnabled()
454 && fb->d_func()->checked
455 && candidate->d_func()->checkable)
459 if (key == Qt::Key_Up || key == Qt::Key_Left)
460 candidate->setFocus(Qt::BacktabFocusReason);
462 candidate->setFocus(Qt::TabFocusReason);
466 void QAbstractButtonPrivate::fixFocusPolicy()
468 Q_Q(QAbstractButton);
469 #ifndef QT_NO_BUTTONGROUP
470 if (!group && !autoExclusive)
476 QList<QAbstractButton *> buttonList = queryButtonList();
477 for (int i = 0; i < buttonList.count(); ++i) {
478 QAbstractButton *b = buttonList.at(i);
479 if (!b->isCheckable())
481 b->setFocusPolicy((Qt::FocusPolicy) ((b == q || !q->isCheckable())
482 ? (b->focusPolicy() | Qt::TabFocus)
483 : (b->focusPolicy() & ~Qt::TabFocus)));
487 void QAbstractButtonPrivate::init()
489 Q_Q(QAbstractButton);
491 q->setFocusPolicy(Qt::FocusPolicy(q->style()->styleHint(QStyle::SH_Button_FocusPolicy)));
492 q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, controlType));
493 q->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
494 q->setForegroundRole(QPalette::ButtonText);
495 q->setBackgroundRole(QPalette::Button);
498 void QAbstractButtonPrivate::refresh()
500 Q_Q(QAbstractButton);
505 #ifndef QT_NO_ACCESSIBILITY
506 QAccessible::updateAccessibility(q, 0, QAccessible::StateChanged);
510 void QAbstractButtonPrivate::click()
512 Q_Q(QAbstractButton);
516 bool changeState = true;
517 if (checked && queryCheckedButton() == q) {
518 // the checked button of an exclusive or autoexclusive group cannot be unchecked
519 #ifndef QT_NO_BUTTONGROUP
520 if (group ? group->d_func()->exclusive : autoExclusive)
527 QPointer<QAbstractButton> guard(q);
533 blockRefresh = false;
535 q->repaint(); //flush paint event before invoking potentially expensive operation
536 QApplication::flush();
543 void QAbstractButtonPrivate::emitClicked()
545 Q_Q(QAbstractButton);
546 QPointer<QAbstractButton> guard(q);
547 emit q->clicked(checked);
548 #ifndef QT_NO_BUTTONGROUP
549 if (guard && group) {
550 emit group->buttonClicked(group->id(q));
552 emit group->buttonClicked(q);
557 void QAbstractButtonPrivate::emitPressed()
559 Q_Q(QAbstractButton);
560 QPointer<QAbstractButton> guard(q);
562 #ifndef QT_NO_BUTTONGROUP
563 if (guard && group) {
564 emit group->buttonPressed(group->id(q));
566 emit group->buttonPressed(q);
571 void QAbstractButtonPrivate::emitReleased()
573 Q_Q(QAbstractButton);
574 QPointer<QAbstractButton> guard(q);
576 #ifndef QT_NO_BUTTONGROUP
577 if (guard && group) {
578 emit group->buttonReleased(group->id(q));
580 emit group->buttonReleased(q);
586 Constructs an abstract button with a \a parent.
588 QAbstractButton::QAbstractButton(QWidget *parent)
589 : QWidget(*new QAbstractButtonPrivate, parent, 0)
591 Q_D(QAbstractButton);
598 QAbstractButton::~QAbstractButton()
600 #ifndef QT_NO_BUTTONGROUP
601 Q_D(QAbstractButton);
603 d->group->removeButton(this);
610 QAbstractButton::QAbstractButton(QAbstractButtonPrivate &dd, QWidget *parent)
611 : QWidget(dd, parent, 0)
613 Q_D(QAbstractButton);
618 \property QAbstractButton::text
619 \brief the text shown on the button
621 If the button has no text, the text() function will return a an empty
624 If the text contains an ampersand character ('&'), a shortcut is
625 automatically created for it. The character that follows the '&' will
626 be used as the shortcut key. Any previous shortcut will be
627 overwritten, or cleared if no shortcut is defined by the text. See the
628 \l {QShortcut#mnemonic}{QShortcut} documentation for details (to
629 display an actual ampersand, use '&&').
631 There is no default text.
634 void QAbstractButton::setText(const QString &text)
636 Q_D(QAbstractButton);
640 #ifndef QT_NO_SHORTCUT
641 QKeySequence newMnemonic = QKeySequence::mnemonic(text);
642 setShortcut(newMnemonic);
644 d->sizeHint = QSize();
647 #ifndef QT_NO_ACCESSIBILITY
648 QAccessible::updateAccessibility(this, 0, QAccessible::NameChanged);
652 QString QAbstractButton::text() const
654 Q_D(const QAbstractButton);
660 \property QAbstractButton::icon
661 \brief the icon shown on the button
663 The icon's default size is defined by the GUI style, but can be
664 adjusted by setting the \l iconSize property.
666 void QAbstractButton::setIcon(const QIcon &icon)
668 Q_D(QAbstractButton);
670 d->sizeHint = QSize();
675 QIcon QAbstractButton::icon() const
677 Q_D(const QAbstractButton);
681 #ifndef QT_NO_SHORTCUT
683 \property QAbstractButton::shortcut
684 \brief the mnemonic associated with the button
687 void QAbstractButton::setShortcut(const QKeySequence &key)
689 Q_D(QAbstractButton);
690 if (d->shortcutId != 0)
691 releaseShortcut(d->shortcutId);
693 d->shortcutId = grabShortcut(key);
696 QKeySequence QAbstractButton::shortcut() const
698 Q_D(const QAbstractButton);
701 #endif // QT_NO_SHORTCUT
704 \property QAbstractButton::checkable
705 \brief whether the button is checkable
707 By default, the button is not checkable.
711 void QAbstractButton::setCheckable(bool checkable)
713 Q_D(QAbstractButton);
714 if (d->checkable == checkable)
717 d->checkable = checkable;
721 bool QAbstractButton::isCheckable() const
723 Q_D(const QAbstractButton);
728 \property QAbstractButton::checked
729 \brief whether the button is checked
731 Only checkable buttons can be checked. By default, the button is unchecked.
735 void QAbstractButton::setChecked(bool checked)
737 Q_D(QAbstractButton);
738 if (!d->checkable || d->checked == checked) {
739 if (!d->blockRefresh)
744 if (!checked && d->queryCheckedButton() == this) {
745 // the checked button of an exclusive or autoexclusive group cannot be unchecked
746 #ifndef QT_NO_BUTTONGROUP
747 if (d->group ? d->group->d_func()->exclusive : d->autoExclusive)
750 d->group->d_func()->detectCheckedButton();
752 if (d->autoExclusive)
757 QPointer<QAbstractButton> guard(this);
759 d->checked = checked;
760 if (!d->blockRefresh)
764 if (guard && checked)
767 emit toggled(checked);
770 bool QAbstractButton::isChecked() const
772 Q_D(const QAbstractButton);
777 \property QAbstractButton::down
778 \brief whether the button is pressed down
780 If this property is true, the button is pressed down. The signals
781 pressed() and clicked() are not emitted if you set this property
782 to true. The default is false.
785 void QAbstractButton::setDown(bool down)
787 Q_D(QAbstractButton);
792 if (d->autoRepeat && d->down)
793 d->repeatTimer.start(d->autoRepeatDelay, this);
795 d->repeatTimer.stop();
798 bool QAbstractButton::isDown() const
800 Q_D(const QAbstractButton);
805 \property QAbstractButton::autoRepeat
806 \brief whether autoRepeat is enabled
808 If autoRepeat is enabled, then the pressed(), released(), and clicked() signals are emitted at
809 regular intervals when the button is down. autoRepeat is off by default.
810 The initial delay and the repetition interval are defined in milliseconds by \l
811 autoRepeatDelay and \l autoRepeatInterval.
813 Note: If a button is pressed down by a shortcut key, then auto-repeat is enabled and timed by the
814 system and not by this class. The pressed(), released(), and clicked() signals will be emitted
815 like in the normal case.
818 void QAbstractButton::setAutoRepeat(bool autoRepeat)
820 Q_D(QAbstractButton);
821 if (d->autoRepeat == autoRepeat)
823 d->autoRepeat = autoRepeat;
824 if (d->autoRepeat && d->down)
825 d->repeatTimer.start(d->autoRepeatDelay, this);
827 d->repeatTimer.stop();
830 bool QAbstractButton::autoRepeat() const
832 Q_D(const QAbstractButton);
833 return d->autoRepeat;
837 \property QAbstractButton::autoRepeatDelay
838 \brief the initial delay of auto-repetition
841 If \l autoRepeat is enabled, then autoRepeatDelay defines the initial
842 delay in milliseconds before auto-repetition kicks in.
844 \sa autoRepeat, autoRepeatInterval
847 void QAbstractButton::setAutoRepeatDelay(int autoRepeatDelay)
849 Q_D(QAbstractButton);
850 d->autoRepeatDelay = autoRepeatDelay;
853 int QAbstractButton::autoRepeatDelay() const
855 Q_D(const QAbstractButton);
856 return d->autoRepeatDelay;
860 \property QAbstractButton::autoRepeatInterval
861 \brief the interval of auto-repetition
864 If \l autoRepeat is enabled, then autoRepeatInterval defines the
865 length of the auto-repetition interval in millisecons.
867 \sa autoRepeat, autoRepeatDelay
870 void QAbstractButton::setAutoRepeatInterval(int autoRepeatInterval)
872 Q_D(QAbstractButton);
873 d->autoRepeatInterval = autoRepeatInterval;
876 int QAbstractButton::autoRepeatInterval() const
878 Q_D(const QAbstractButton);
879 return d->autoRepeatInterval;
885 \property QAbstractButton::autoExclusive
886 \brief whether auto-exclusivity is enabled
888 If auto-exclusivity is enabled, checkable buttons that belong to the
889 same parent widget behave as if they were part of the same
890 exclusive button group. In an exclusive button group, only one button
891 can be checked at any time; checking another button automatically
892 unchecks the previously checked one.
894 The property has no effect on buttons that belong to a button
897 autoExclusive is off by default, except for radio buttons.
901 void QAbstractButton::setAutoExclusive(bool autoExclusive)
903 Q_D(QAbstractButton);
904 d->autoExclusive = autoExclusive;
907 bool QAbstractButton::autoExclusive() const
909 Q_D(const QAbstractButton);
910 return d->autoExclusive;
913 #ifndef QT_NO_BUTTONGROUP
915 Returns the group that this button belongs to.
917 If the button is not a member of any QButtonGroup, this function
922 QButtonGroup *QAbstractButton::group() const
924 Q_D(const QAbstractButton);
927 #endif // QT_NO_BUTTONGROUP
930 Performs an animated click: the button is pressed immediately, and
931 released \a msec milliseconds later (the default is 100 ms).
933 Calling this function again before the button was released will reset
936 All signals associated with a click are emitted as appropriate.
938 This function does nothing if the button is \link setEnabled()
943 void QAbstractButton::animateClick(int msec)
947 Q_D(QAbstractButton);
948 if (d->checkable && focusPolicy() & Qt::ClickFocus)
951 repaint(); //flush paint event before invoking potentially expensive operation
952 QApplication::flush();
953 if (!d->animateTimer.isActive())
955 d->animateTimer.start(msec, this);
961 All the usual signals associated with a click are emitted as
962 appropriate. If the button is checkable, the state of the button is
965 This function does nothing if the button is \link setEnabled()
970 void QAbstractButton::click()
974 Q_D(QAbstractButton);
975 QPointer<QAbstractButton> guard(this);
988 /*! \fn void QAbstractButton::toggle()
990 Toggles the state of a checkable button.
994 void QAbstractButton::toggle()
996 Q_D(QAbstractButton);
997 setChecked(!d->checked);
1001 /*! This virtual handler is called when setChecked() was called,
1002 unless it was called from within nextCheckState(). It allows
1003 subclasses to reset their intermediate button states.
1005 \sa nextCheckState()
1007 void QAbstractButton::checkStateSet()
1011 /*! This virtual handler is called when a button is clicked. The
1012 default implementation calls setChecked(!isChecked()) if the button
1013 isCheckable(). It allows subclasses to implement intermediate button
1018 void QAbstractButton::nextCheckState()
1021 setChecked(!isChecked());
1025 Returns true if \a pos is inside the clickable button rectangle;
1026 otherwise returns false.
1028 By default, the clickable area is the entire widget. Subclasses
1029 may reimplement this function to provide support for clickable
1030 areas of different shapes and sizes.
1032 bool QAbstractButton::hitButton(const QPoint &pos) const
1034 return rect().contains(pos);
1038 bool QAbstractButton::event(QEvent *e)
1040 // as opposed to other widgets, disabled buttons accept mouse
1041 // events. This avoids surprising click-through scenarios
1044 case QEvent::TabletPress:
1045 case QEvent::TabletRelease:
1046 case QEvent::TabletMove:
1047 case QEvent::MouseButtonPress:
1048 case QEvent::MouseButtonRelease:
1049 case QEvent::MouseButtonDblClick:
1050 case QEvent::MouseMove:
1051 case QEvent::HoverMove:
1052 case QEvent::HoverEnter:
1053 case QEvent::HoverLeave:
1054 case QEvent::ContextMenu:
1055 #ifndef QT_NO_WHEELEVENT
1064 #ifndef QT_NO_SHORTCUT
1065 if (e->type() == QEvent::Shortcut) {
1066 Q_D(QAbstractButton);
1067 QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
1068 if (d->shortcutId != se->shortcutId())
1070 if (!se->isAmbiguous()) {
1071 if (!d->animateTimer.isActive())
1074 if (focusPolicy() != Qt::NoFocus)
1075 setFocus(Qt::ShortcutFocusReason);
1076 window()->setAttribute(Qt::WA_KeyboardFocusChange);
1081 return QWidget::event(e);
1085 void QAbstractButton::mousePressEvent(QMouseEvent *e)
1087 Q_D(QAbstractButton);
1088 if (e->button() != Qt::LeftButton) {
1092 if (hitButton(e->pos())) {
1095 repaint(); //flush paint event before invoking potentially expensive operation
1096 QApplication::flush();
1105 void QAbstractButton::mouseReleaseEvent(QMouseEvent *e)
1107 Q_D(QAbstractButton);
1110 if (e->button() != Qt::LeftButton) {
1120 if (hitButton(e->pos())) {
1121 d->repeatTimer.stop();
1131 void QAbstractButton::mouseMoveEvent(QMouseEvent *e)
1133 Q_D(QAbstractButton);
1134 if (!(e->buttons() & Qt::LeftButton) || !d->pressed) {
1139 if (hitButton(e->pos()) != d->down) {
1141 repaint(); //flush paint event before invoking potentially expensive operation
1142 QApplication::flush();
1148 } else if (!hitButton(e->pos())) {
1154 void QAbstractButton::keyPressEvent(QKeyEvent *e)
1156 Q_D(QAbstractButton);
1160 case Qt::Key_Return:
1163 case Qt::Key_Select:
1165 if (!e->isAutoRepeat()) {
1167 repaint(); //flush paint event before invoking potentially expensive operation
1168 QApplication::flush();
1178 #ifdef QT_KEYPAD_NAVIGATION
1179 if ((QApplication::keypadNavigationEnabled()
1180 && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right))
1181 || (!QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional
1182 || (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down))) {
1188 if (d->autoExclusive
1189 #ifndef QT_NO_BUTTONGROUP
1192 #ifndef QT_NO_ITEMVIEWS
1193 || ((pw = parentWidget()) && qobject_cast<QAbstractItemView *>(pw->parentWidget()))
1196 // ### Using qobject_cast to check if the parent is a viewport of
1197 // QAbstractItemView is a crude hack, and should be revisited and
1198 // cleaned up when fixing task 194373. It's here to ensure that we
1199 // keep compatibility outside QAbstractItemView.
1200 d->moveFocus(e->key());
1201 if (hasFocus()) // nothing happend, propagate
1204 focusNextPrevChild(next);
1207 case Qt::Key_Escape:
1210 repaint(); //flush paint event before invoking potentially expensive operation
1211 QApplication::flush();
1222 void QAbstractButton::keyReleaseEvent(QKeyEvent *e)
1224 Q_D(QAbstractButton);
1226 if (!e->isAutoRepeat())
1227 d->repeatTimer.stop();
1230 case Qt::Key_Select:
1232 if (!e->isAutoRepeat() && d->down)
1242 void QAbstractButton::timerEvent(QTimerEvent *e)
1244 Q_D(QAbstractButton);
1245 if (e->timerId() == d->repeatTimer.timerId()) {
1246 d->repeatTimer.start(d->autoRepeatInterval, this);
1248 QPointer<QAbstractButton> guard(this);
1257 } else if (e->timerId() == d->animateTimer.timerId()) {
1258 d->animateTimer.stop();
1264 void QAbstractButton::focusInEvent(QFocusEvent *e)
1266 Q_D(QAbstractButton);
1267 #ifdef QT_KEYPAD_NAVIGATION
1268 if (!QApplication::keypadNavigationEnabled())
1270 d->fixFocusPolicy();
1271 QWidget::focusInEvent(e);
1275 void QAbstractButton::focusOutEvent(QFocusEvent *e)
1277 Q_D(QAbstractButton);
1278 if (e->reason() != Qt::PopupFocusReason)
1280 QWidget::focusOutEvent(e);
1284 void QAbstractButton::changeEvent(QEvent *e)
1286 Q_D(QAbstractButton);
1287 switch (e->type()) {
1288 case QEvent::EnabledChange:
1293 d->sizeHint = QSize();
1296 QWidget::changeEvent(e);
1300 \fn void QAbstractButton::paintEvent(QPaintEvent *e)
1305 \fn void QAbstractButton::pressed()
1307 This signal is emitted when the button is pressed down.
1309 \sa released(), clicked()
1313 \fn void QAbstractButton::released()
1315 This signal is emitted when the button is released.
1317 \sa pressed(), clicked(), toggled()
1321 \fn void QAbstractButton::clicked(bool checked)
1323 This signal is emitted when the button is activated (i.e. pressed down
1324 then released while the mouse cursor is inside the button), when the
1325 shortcut key is typed, or when click() or animateClick() is called.
1326 Notably, this signal is \e not emitted if you call setDown(),
1327 setChecked() or toggle().
1329 If the button is checkable, \a checked is true if the button is
1330 checked, or false if the button is unchecked.
1332 \sa pressed(), released(), toggled()
1336 \fn void QAbstractButton::toggled(bool checked)
1338 This signal is emitted whenever a checkable button changes its state.
1339 \a checked is true if the button is checked, or false if the button is
1342 This may be the result of a user action, click() slot activation,
1343 or because setChecked() was called.
1345 The states of buttons in exclusive button groups are updated before this
1346 signal is emitted. This means that slots can act on either the "off"
1347 signal or the "on" signal emitted by the buttons in the group whose
1348 states have changed.
1350 For example, a slot that reacts to signals emitted by newly checked
1351 buttons but which ignores signals from buttons that have been unchecked
1352 can be implemented using the following pattern:
1354 \snippet doc/src/snippets/code/src_gui_widgets_qabstractbutton.cpp 2
1356 Button groups can be created using the QButtonGroup class, and
1357 updates to the button states monitored with the
1358 \l{QButtonGroup::buttonClicked()} signal.
1360 \sa checked, clicked()
1364 \property QAbstractButton::iconSize
1365 \brief the icon size used for this button.
1367 The default size is defined by the GUI style. This is a maximum
1368 size for the icons. Smaller icons will not be scaled up.
1371 QSize QAbstractButton::iconSize() const
1373 Q_D(const QAbstractButton);
1374 if (d->iconSize.isValid())
1376 int e = style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, this);
1380 void QAbstractButton::setIconSize(const QSize &size)
1382 Q_D(QAbstractButton);
1383 if (d->iconSize == size)
1387 d->sizeHint = QSize();