1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
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.
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.
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.
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.
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
118 user. \note As opposed to other widgets, buttons derived from
119 QAbstractButton accepts mouse and context menu events
122 \o setAutoRepeat() sets whether the button will auto-repeat if the
123 user holds it down. \l autoRepeatDelay and \l autoRepeatInterval
124 define how auto-repetition is done.
126 \o setCheckable() sets whether the button is a toggle button or not.
130 The difference between isDown() and isChecked() is as follows.
131 When the user clicks a toggle button to check it, the button is first
132 \e pressed then released into the \e checked state. When the user
133 clicks it again (to uncheck it), the button moves first to the
134 \e pressed state, then to the \e unchecked state (isChecked() and
135 isDown() are both false).
137 QAbstractButton provides four signals:
141 \o pressed() is emitted when the left mouse button is pressed while
142 the mouse cursor is inside the button.
144 \o released() is emitted when the left mouse button is released.
146 \o clicked() is emitted when the button is first pressed and then
147 released, when the shortcut key is typed, or when click() or
148 animateClick() is called.
150 \o toggled() is emitted when the state of a toggle button changes.
154 To subclass QAbstractButton, you must reimplement at least
155 paintEvent() to draw the button's outline and its text or pixmap. It
156 is generally advisable to reimplement sizeHint() as well, and
157 sometimes hitButton() (to determine whether a button press is within
158 the button). For buttons with more than two states (like tri-state
159 buttons), you will also have to reimplement checkStateSet() and
165 QAbstractButtonPrivate::QAbstractButtonPrivate(QSizePolicy::ControlType type)
167 #ifndef QT_NO_SHORTCUT
170 checkable(false), checked(false), autoRepeat(false), autoExclusive(false),
171 down(false), blockRefresh(false), pressed(false),
172 #ifndef QT_NO_BUTTONGROUP
175 autoRepeatDelay(AUTO_REPEAT_DELAY),
176 autoRepeatInterval(AUTO_REPEAT_INTERVAL),
180 #ifndef QT_NO_BUTTONGROUP
182 class QButtonGroupPrivate: public QObjectPrivate
184 Q_DECLARE_PUBLIC(QButtonGroup)
187 QButtonGroupPrivate():exclusive(true){}
188 QList<QAbstractButton *> buttonList;
189 QPointer<QAbstractButton> checkedButton;
190 void detectCheckedButton();
191 void notifyChecked(QAbstractButton *button);
193 QMap<QAbstractButton*, int> mapping;
196 QButtonGroup::QButtonGroup(QObject *parent)
197 : QObject(*new QButtonGroupPrivate, parent)
201 QButtonGroup::~QButtonGroup()
204 for (int i = 0; i < d->buttonList.count(); ++i)
205 d->buttonList.at(i)->d_func()->group = 0;
209 bool QButtonGroup::exclusive() const
211 Q_D(const QButtonGroup);
215 void QButtonGroup::setExclusive(bool exclusive)
218 d->exclusive = exclusive;
222 // TODO: Qt 5: Merge with addButton(QAbstractButton *button, int id)
223 void QButtonGroup::addButton(QAbstractButton *button)
225 addButton(button, -1);
228 void QButtonGroup::addButton(QAbstractButton *button, int id)
231 if (QButtonGroup *previous = button->d_func()->group)
232 previous->removeButton(button);
233 button->d_func()->group = this;
234 d->buttonList.append(button);
236 QList<int> ids = d->mapping.values();
238 d->mapping[button] = -2;
241 d->mapping[button] = ids.first()-1;
244 d->mapping[button] = id;
247 if (d->exclusive && button->isChecked())
248 button->d_func()->notifyChecked();
251 void QButtonGroup::removeButton(QAbstractButton *button)
254 if (d->checkedButton == button) {
255 d->detectCheckedButton();
257 if (button->d_func()->group == this) {
258 button->d_func()->group = 0;
259 d->buttonList.removeAll(button);
260 d->mapping.remove(button);
264 QList<QAbstractButton*> QButtonGroup::buttons() const
266 Q_D(const QButtonGroup);
267 return d->buttonList;
270 QAbstractButton *QButtonGroup::checkedButton() const
272 Q_D(const QButtonGroup);
273 return d->checkedButton;
276 QAbstractButton *QButtonGroup::button(int id) const
278 Q_D(const QButtonGroup);
279 return d->mapping.key(id);
282 void QButtonGroup::setId(QAbstractButton *button, int id)
285 if (button && id != -1)
286 d->mapping[button] = id;
289 int QButtonGroup::id(QAbstractButton *button) const
291 Q_D(const QButtonGroup);
292 return d->mapping.value(button, -1);
295 int QButtonGroup::checkedId() const
297 Q_D(const QButtonGroup);
298 return d->mapping.value(d->checkedButton, -1);
301 // detect a checked button other than the current one
302 void QButtonGroupPrivate::detectCheckedButton()
304 QAbstractButton *previous = checkedButton;
308 for (int i = 0; i < buttonList.count(); i++) {
309 if (buttonList.at(i) != previous && buttonList.at(i)->isChecked()) {
310 checkedButton = buttonList.at(i);
316 #endif // QT_NO_BUTTONGROUP
318 QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const
320 #ifndef QT_NO_BUTTONGROUP
322 return group->d_func()->buttonList;
325 QList<QAbstractButton*>candidates = parent->findChildren<QAbstractButton *>();
327 for (int i = candidates.count() - 1; i >= 0; --i) {
328 QAbstractButton *candidate = candidates.at(i);
329 if (!candidate->autoExclusive()
330 #ifndef QT_NO_BUTTONGROUP
331 || candidate->group()
334 candidates.removeAt(i);
340 QAbstractButton *QAbstractButtonPrivate::queryCheckedButton() const
342 #ifndef QT_NO_BUTTONGROUP
344 return group->d_func()->checkedButton;
347 Q_Q(const QAbstractButton);
348 QList<QAbstractButton *> buttonList = queryButtonList();
349 if (!autoExclusive || buttonList.count() == 1) // no group
352 for (int i = 0; i < buttonList.count(); ++i) {
353 QAbstractButton *b = buttonList.at(i);
354 if (b->d_func()->checked && b != q)
357 return checked ? const_cast<QAbstractButton *>(q) : 0;
360 void QAbstractButtonPrivate::notifyChecked()
362 #ifndef QT_NO_BUTTONGROUP
363 Q_Q(QAbstractButton);
365 QAbstractButton *previous = group->d_func()->checkedButton;
366 group->d_func()->checkedButton = q;
367 if (group->d_func()->exclusive && previous && previous != q)
368 previous->nextCheckState();
372 if (QAbstractButton *b = queryCheckedButton())
373 b->setChecked(false);
377 void QAbstractButtonPrivate::moveFocus(int key)
379 QList<QAbstractButton *> buttonList = queryButtonList();;
380 #ifndef QT_NO_BUTTONGROUP
381 bool exclusive = group ? group->d_func()->exclusive : autoExclusive;
383 bool exclusive = autoExclusive;
385 QWidget *f = QApplication::focusWidget();
386 QAbstractButton *fb = qobject_cast<QAbstractButton *>(f);
387 if (!fb || !buttonList.contains(fb))
390 QAbstractButton *candidate = 0;
392 QRect target = f->rect().translated(f->mapToGlobal(QPoint(0,0)));
393 QPoint goal = target.center();
394 uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
396 for (int i = 0; i < buttonList.count(); ++i) {
397 QAbstractButton *button = buttonList.at(i);
398 if (button != f && button->window() == f->window() && button->isEnabled() && !button->isHidden() &&
399 (autoExclusive || (button->focusPolicy() & focus_flag) == focus_flag)) {
400 QRect buttonRect = button->rect().translated(button->mapToGlobal(QPoint(0,0)));
401 QPoint p = buttonRect.center();
403 //Priority to widgets that overlap on the same coordinate.
404 //In that case, the distance in the direction will be used as significant score,
405 //take also in account orthogonal distance in case two widget are in the same distance.
407 if ((buttonRect.x() < target.right() && target.x() < buttonRect.right())
408 && (key == Qt::Key_Up || key == Qt::Key_Down)) {
409 //one item's is at the vertical of the other
410 score = (qAbs(p.y() - goal.y()) << 16) + qAbs(p.x() - goal.x());
411 } else if ((buttonRect.y() < target.bottom() && target.y() < buttonRect.bottom())
412 && (key == Qt::Key_Left || key == Qt::Key_Right) ) {
413 //one item's is at the horizontal of the other
414 score = (qAbs(p.x() - goal.x()) << 16) + qAbs(p.y() - goal.y());
416 score = (1 << 30) + (p.y() - goal.y()) * (p.y() - goal.y()) + (p.x() - goal.x()) * (p.x() - goal.x());
419 if (score > bestScore && candidate)
424 if (p.y() < goal.y()) {
430 if (p.y() > goal.y()) {
436 if (p.x() < goal.x()) {
442 if (p.x() > goal.x()) {
452 #ifdef QT_KEYPAD_NAVIGATION
453 && !QApplication::keypadNavigationEnabled()
456 && fb->d_func()->checked
457 && candidate->d_func()->checkable)
461 if (key == Qt::Key_Up || key == Qt::Key_Left)
462 candidate->setFocus(Qt::BacktabFocusReason);
464 candidate->setFocus(Qt::TabFocusReason);
468 void QAbstractButtonPrivate::fixFocusPolicy()
470 Q_Q(QAbstractButton);
471 #ifndef QT_NO_BUTTONGROUP
472 if (!group && !autoExclusive)
478 QList<QAbstractButton *> buttonList = queryButtonList();
479 for (int i = 0; i < buttonList.count(); ++i) {
480 QAbstractButton *b = buttonList.at(i);
481 if (!b->isCheckable())
483 b->setFocusPolicy((Qt::FocusPolicy) ((b == q || !q->isCheckable())
484 ? (b->focusPolicy() | Qt::TabFocus)
485 : (b->focusPolicy() & ~Qt::TabFocus)));
489 void QAbstractButtonPrivate::init()
491 Q_Q(QAbstractButton);
493 q->setFocusPolicy(Qt::FocusPolicy(q->style()->styleHint(QStyle::SH_Button_FocusPolicy)));
494 q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, controlType));
495 q->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
496 q->setForegroundRole(QPalette::ButtonText);
497 q->setBackgroundRole(QPalette::Button);
500 void QAbstractButtonPrivate::refresh()
502 Q_Q(QAbstractButton);
507 #ifndef QT_NO_ACCESSIBILITY
508 QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::StateChanged, q, 0));
512 void QAbstractButtonPrivate::click()
514 Q_Q(QAbstractButton);
518 bool changeState = true;
519 if (checked && queryCheckedButton() == q) {
520 // the checked button of an exclusive or autoexclusive group cannot be unchecked
521 #ifndef QT_NO_BUTTONGROUP
522 if (group ? group->d_func()->exclusive : autoExclusive)
529 QPointer<QAbstractButton> guard(q);
535 blockRefresh = false;
537 q->repaint(); //flush paint event before invoking potentially expensive operation
538 QApplication::flush();
545 void QAbstractButtonPrivate::emitClicked()
547 Q_Q(QAbstractButton);
548 QPointer<QAbstractButton> guard(q);
549 emit q->clicked(checked);
550 #ifndef QT_NO_BUTTONGROUP
551 if (guard && group) {
552 emit group->buttonClicked(group->id(q));
554 emit group->buttonClicked(q);
559 void QAbstractButtonPrivate::emitPressed()
561 Q_Q(QAbstractButton);
562 QPointer<QAbstractButton> guard(q);
564 #ifndef QT_NO_BUTTONGROUP
565 if (guard && group) {
566 emit group->buttonPressed(group->id(q));
568 emit group->buttonPressed(q);
573 void QAbstractButtonPrivate::emitReleased()
575 Q_Q(QAbstractButton);
576 QPointer<QAbstractButton> guard(q);
578 #ifndef QT_NO_BUTTONGROUP
579 if (guard && group) {
580 emit group->buttonReleased(group->id(q));
582 emit group->buttonReleased(q);
588 Constructs an abstract button with a \a parent.
590 QAbstractButton::QAbstractButton(QWidget *parent)
591 : QWidget(*new QAbstractButtonPrivate, parent, 0)
593 Q_D(QAbstractButton);
600 QAbstractButton::~QAbstractButton()
602 #ifndef QT_NO_BUTTONGROUP
603 Q_D(QAbstractButton);
605 d->group->removeButton(this);
612 QAbstractButton::QAbstractButton(QAbstractButtonPrivate &dd, QWidget *parent)
613 : QWidget(dd, parent, 0)
615 Q_D(QAbstractButton);
620 \property QAbstractButton::text
621 \brief the text shown on the button
623 If the button has no text, the text() function will return a an empty
626 If the text contains an ampersand character ('&'), a shortcut is
627 automatically created for it. The character that follows the '&' will
628 be used as the shortcut key. Any previous shortcut will be
629 overwritten, or cleared if no shortcut is defined by the text. See the
630 \l {QShortcut#mnemonic}{QShortcut} documentation for details (to
631 display an actual ampersand, use '&&').
633 There is no default text.
636 void QAbstractButton::setText(const QString &text)
638 Q_D(QAbstractButton);
642 #ifndef QT_NO_SHORTCUT
643 QKeySequence newMnemonic = QKeySequence::mnemonic(text);
644 setShortcut(newMnemonic);
646 d->sizeHint = QSize();
649 #ifndef QT_NO_ACCESSIBILITY
650 QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, this, 0));
654 QString QAbstractButton::text() const
656 Q_D(const QAbstractButton);
662 \property QAbstractButton::icon
663 \brief the icon shown on the button
665 The icon's default size is defined by the GUI style, but can be
666 adjusted by setting the \l iconSize property.
668 void QAbstractButton::setIcon(const QIcon &icon)
670 Q_D(QAbstractButton);
672 d->sizeHint = QSize();
677 QIcon QAbstractButton::icon() const
679 Q_D(const QAbstractButton);
683 #ifndef QT_NO_SHORTCUT
685 \property QAbstractButton::shortcut
686 \brief the mnemonic associated with the button
689 void QAbstractButton::setShortcut(const QKeySequence &key)
691 Q_D(QAbstractButton);
692 if (d->shortcutId != 0)
693 releaseShortcut(d->shortcutId);
695 d->shortcutId = grabShortcut(key);
698 QKeySequence QAbstractButton::shortcut() const
700 Q_D(const QAbstractButton);
703 #endif // QT_NO_SHORTCUT
706 \property QAbstractButton::checkable
707 \brief whether the button is checkable
709 By default, the button is not checkable.
713 void QAbstractButton::setCheckable(bool checkable)
715 Q_D(QAbstractButton);
716 if (d->checkable == checkable)
719 d->checkable = checkable;
723 bool QAbstractButton::isCheckable() const
725 Q_D(const QAbstractButton);
730 \property QAbstractButton::checked
731 \brief whether the button is checked
733 Only checkable buttons can be checked. By default, the button is unchecked.
737 void QAbstractButton::setChecked(bool checked)
739 Q_D(QAbstractButton);
740 if (!d->checkable || d->checked == checked) {
741 if (!d->blockRefresh)
746 if (!checked && d->queryCheckedButton() == this) {
747 // the checked button of an exclusive or autoexclusive group cannot be unchecked
748 #ifndef QT_NO_BUTTONGROUP
749 if (d->group ? d->group->d_func()->exclusive : d->autoExclusive)
752 d->group->d_func()->detectCheckedButton();
754 if (d->autoExclusive)
759 QPointer<QAbstractButton> guard(this);
761 d->checked = checked;
762 if (!d->blockRefresh)
766 if (guard && checked)
769 emit toggled(checked);
772 bool QAbstractButton::isChecked() const
774 Q_D(const QAbstractButton);
779 \property QAbstractButton::down
780 \brief whether the button is pressed down
782 If this property is true, the button is pressed down. The signals
783 pressed() and clicked() are not emitted if you set this property
784 to true. The default is false.
787 void QAbstractButton::setDown(bool down)
789 Q_D(QAbstractButton);
794 if (d->autoRepeat && d->down)
795 d->repeatTimer.start(d->autoRepeatDelay, this);
797 d->repeatTimer.stop();
800 bool QAbstractButton::isDown() const
802 Q_D(const QAbstractButton);
807 \property QAbstractButton::autoRepeat
808 \brief whether autoRepeat is enabled
810 If autoRepeat is enabled, then the pressed(), released(), and clicked() signals are emitted at
811 regular intervals when the button is down. autoRepeat is off by default.
812 The initial delay and the repetition interval are defined in milliseconds by \l
813 autoRepeatDelay and \l autoRepeatInterval.
815 Note: If a button is pressed down by a shortcut key, then auto-repeat is enabled and timed by the
816 system and not by this class. The pressed(), released(), and clicked() signals will be emitted
817 like in the normal case.
820 void QAbstractButton::setAutoRepeat(bool autoRepeat)
822 Q_D(QAbstractButton);
823 if (d->autoRepeat == autoRepeat)
825 d->autoRepeat = autoRepeat;
826 if (d->autoRepeat && d->down)
827 d->repeatTimer.start(d->autoRepeatDelay, this);
829 d->repeatTimer.stop();
832 bool QAbstractButton::autoRepeat() const
834 Q_D(const QAbstractButton);
835 return d->autoRepeat;
839 \property QAbstractButton::autoRepeatDelay
840 \brief the initial delay of auto-repetition
843 If \l autoRepeat is enabled, then autoRepeatDelay defines the initial
844 delay in milliseconds before auto-repetition kicks in.
846 \sa autoRepeat, autoRepeatInterval
849 void QAbstractButton::setAutoRepeatDelay(int autoRepeatDelay)
851 Q_D(QAbstractButton);
852 d->autoRepeatDelay = autoRepeatDelay;
855 int QAbstractButton::autoRepeatDelay() const
857 Q_D(const QAbstractButton);
858 return d->autoRepeatDelay;
862 \property QAbstractButton::autoRepeatInterval
863 \brief the interval of auto-repetition
866 If \l autoRepeat is enabled, then autoRepeatInterval defines the
867 length of the auto-repetition interval in millisecons.
869 \sa autoRepeat, autoRepeatDelay
872 void QAbstractButton::setAutoRepeatInterval(int autoRepeatInterval)
874 Q_D(QAbstractButton);
875 d->autoRepeatInterval = autoRepeatInterval;
878 int QAbstractButton::autoRepeatInterval() const
880 Q_D(const QAbstractButton);
881 return d->autoRepeatInterval;
887 \property QAbstractButton::autoExclusive
888 \brief whether auto-exclusivity is enabled
890 If auto-exclusivity is enabled, checkable buttons that belong to the
891 same parent widget behave as if they were part of the same
892 exclusive button group. In an exclusive button group, only one button
893 can be checked at any time; checking another button automatically
894 unchecks the previously checked one.
896 The property has no effect on buttons that belong to a button
899 autoExclusive is off by default, except for radio buttons.
903 void QAbstractButton::setAutoExclusive(bool autoExclusive)
905 Q_D(QAbstractButton);
906 d->autoExclusive = autoExclusive;
909 bool QAbstractButton::autoExclusive() const
911 Q_D(const QAbstractButton);
912 return d->autoExclusive;
915 #ifndef QT_NO_BUTTONGROUP
917 Returns the group that this button belongs to.
919 If the button is not a member of any QButtonGroup, this function
924 QButtonGroup *QAbstractButton::group() const
926 Q_D(const QAbstractButton);
929 #endif // QT_NO_BUTTONGROUP
932 Performs an animated click: the button is pressed immediately, and
933 released \a msec milliseconds later (the default is 100 ms).
935 Calling this function again before the button was released will reset
938 All signals associated with a click are emitted as appropriate.
940 This function does nothing if the button is \link setEnabled()
945 void QAbstractButton::animateClick(int msec)
949 Q_D(QAbstractButton);
950 if (d->checkable && focusPolicy() & Qt::ClickFocus)
953 repaint(); //flush paint event before invoking potentially expensive operation
954 QApplication::flush();
955 if (!d->animateTimer.isActive())
957 d->animateTimer.start(msec, this);
963 All the usual signals associated with a click are emitted as
964 appropriate. If the button is checkable, the state of the button is
967 This function does nothing if the button is \link setEnabled()
972 void QAbstractButton::click()
976 Q_D(QAbstractButton);
977 QPointer<QAbstractButton> guard(this);
990 /*! \fn void QAbstractButton::toggle()
992 Toggles the state of a checkable button.
996 void QAbstractButton::toggle()
998 Q_D(QAbstractButton);
999 setChecked(!d->checked);
1003 /*! This virtual handler is called when setChecked() was called,
1004 unless it was called from within nextCheckState(). It allows
1005 subclasses to reset their intermediate button states.
1007 \sa nextCheckState()
1009 void QAbstractButton::checkStateSet()
1013 /*! This virtual handler is called when a button is clicked. The
1014 default implementation calls setChecked(!isChecked()) if the button
1015 isCheckable(). It allows subclasses to implement intermediate button
1020 void QAbstractButton::nextCheckState()
1023 setChecked(!isChecked());
1027 Returns true if \a pos is inside the clickable button rectangle;
1028 otherwise returns false.
1030 By default, the clickable area is the entire widget. Subclasses
1031 may reimplement this function to provide support for clickable
1032 areas of different shapes and sizes.
1034 bool QAbstractButton::hitButton(const QPoint &pos) const
1036 return rect().contains(pos);
1040 bool QAbstractButton::event(QEvent *e)
1042 // as opposed to other widgets, disabled buttons accept mouse
1043 // events. This avoids surprising click-through scenarios
1046 case QEvent::TabletPress:
1047 case QEvent::TabletRelease:
1048 case QEvent::TabletMove:
1049 case QEvent::MouseButtonPress:
1050 case QEvent::MouseButtonRelease:
1051 case QEvent::MouseButtonDblClick:
1052 case QEvent::MouseMove:
1053 case QEvent::HoverMove:
1054 case QEvent::HoverEnter:
1055 case QEvent::HoverLeave:
1056 case QEvent::ContextMenu:
1057 #ifndef QT_NO_WHEELEVENT
1066 #ifndef QT_NO_SHORTCUT
1067 if (e->type() == QEvent::Shortcut) {
1068 Q_D(QAbstractButton);
1069 QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
1070 if (d->shortcutId != se->shortcutId())
1072 if (!se->isAmbiguous()) {
1073 if (!d->animateTimer.isActive())
1076 if (focusPolicy() != Qt::NoFocus)
1077 setFocus(Qt::ShortcutFocusReason);
1078 window()->setAttribute(Qt::WA_KeyboardFocusChange);
1083 return QWidget::event(e);
1087 void QAbstractButton::mousePressEvent(QMouseEvent *e)
1089 Q_D(QAbstractButton);
1090 if (e->button() != Qt::LeftButton) {
1094 if (hitButton(e->pos())) {
1097 repaint(); //flush paint event before invoking potentially expensive operation
1098 QApplication::flush();
1107 void QAbstractButton::mouseReleaseEvent(QMouseEvent *e)
1109 Q_D(QAbstractButton);
1112 if (e->button() != Qt::LeftButton) {
1122 if (hitButton(e->pos())) {
1123 d->repeatTimer.stop();
1133 void QAbstractButton::mouseMoveEvent(QMouseEvent *e)
1135 Q_D(QAbstractButton);
1136 if (!(e->buttons() & Qt::LeftButton) || !d->pressed) {
1141 if (hitButton(e->pos()) != d->down) {
1143 repaint(); //flush paint event before invoking potentially expensive operation
1144 QApplication::flush();
1150 } else if (!hitButton(e->pos())) {
1156 void QAbstractButton::keyPressEvent(QKeyEvent *e)
1158 Q_D(QAbstractButton);
1162 case Qt::Key_Return:
1165 case Qt::Key_Select:
1167 if (!e->isAutoRepeat()) {
1169 repaint(); //flush paint event before invoking potentially expensive operation
1170 QApplication::flush();
1180 #ifdef QT_KEYPAD_NAVIGATION
1181 if ((QApplication::keypadNavigationEnabled()
1182 && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right))
1183 || (!QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional
1184 || (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down))) {
1190 if (d->autoExclusive
1191 #ifndef QT_NO_BUTTONGROUP
1194 #ifndef QT_NO_ITEMVIEWS
1195 || ((pw = parentWidget()) && qobject_cast<QAbstractItemView *>(pw->parentWidget()))
1198 // ### Using qobject_cast to check if the parent is a viewport of
1199 // QAbstractItemView is a crude hack, and should be revisited and
1200 // cleaned up when fixing task 194373. It's here to ensure that we
1201 // keep compatibility outside QAbstractItemView.
1202 d->moveFocus(e->key());
1203 if (hasFocus()) // nothing happend, propagate
1206 focusNextPrevChild(next);
1209 case Qt::Key_Escape:
1212 repaint(); //flush paint event before invoking potentially expensive operation
1213 QApplication::flush();
1224 void QAbstractButton::keyReleaseEvent(QKeyEvent *e)
1226 Q_D(QAbstractButton);
1228 if (!e->isAutoRepeat())
1229 d->repeatTimer.stop();
1232 case Qt::Key_Select:
1234 if (!e->isAutoRepeat() && d->down)
1244 void QAbstractButton::timerEvent(QTimerEvent *e)
1246 Q_D(QAbstractButton);
1247 if (e->timerId() == d->repeatTimer.timerId()) {
1248 d->repeatTimer.start(d->autoRepeatInterval, this);
1250 QPointer<QAbstractButton> guard(this);
1259 } else if (e->timerId() == d->animateTimer.timerId()) {
1260 d->animateTimer.stop();
1266 void QAbstractButton::focusInEvent(QFocusEvent *e)
1268 Q_D(QAbstractButton);
1269 #ifdef QT_KEYPAD_NAVIGATION
1270 if (!QApplication::keypadNavigationEnabled())
1272 d->fixFocusPolicy();
1273 QWidget::focusInEvent(e);
1277 void QAbstractButton::focusOutEvent(QFocusEvent *e)
1279 Q_D(QAbstractButton);
1280 if (e->reason() != Qt::PopupFocusReason)
1282 QWidget::focusOutEvent(e);
1286 void QAbstractButton::changeEvent(QEvent *e)
1288 Q_D(QAbstractButton);
1289 switch (e->type()) {
1290 case QEvent::EnabledChange:
1295 d->sizeHint = QSize();
1298 QWidget::changeEvent(e);
1302 \fn void QAbstractButton::paintEvent(QPaintEvent *e)
1307 \fn void QAbstractButton::pressed()
1309 This signal is emitted when the button is pressed down.
1311 \sa released(), clicked()
1315 \fn void QAbstractButton::released()
1317 This signal is emitted when the button is released.
1319 \sa pressed(), clicked(), toggled()
1323 \fn void QAbstractButton::clicked(bool checked)
1325 This signal is emitted when the button is activated (i.e. pressed down
1326 then released while the mouse cursor is inside the button), when the
1327 shortcut key is typed, or when click() or animateClick() is called.
1328 Notably, this signal is \e not emitted if you call setDown(),
1329 setChecked() or toggle().
1331 If the button is checkable, \a checked is true if the button is
1332 checked, or false if the button is unchecked.
1334 \sa pressed(), released(), toggled()
1338 \fn void QAbstractButton::toggled(bool checked)
1340 This signal is emitted whenever a checkable button changes its state.
1341 \a checked is true if the button is checked, or false if the button is
1344 This may be the result of a user action, click() slot activation,
1345 or because setChecked() was called.
1347 The states of buttons in exclusive button groups are updated before this
1348 signal is emitted. This means that slots can act on either the "off"
1349 signal or the "on" signal emitted by the buttons in the group whose
1350 states have changed.
1352 For example, a slot that reacts to signals emitted by newly checked
1353 buttons but which ignores signals from buttons that have been unchecked
1354 can be implemented using the following pattern:
1356 \snippet doc/src/snippets/code/src_gui_widgets_qabstractbutton.cpp 2
1358 Button groups can be created using the QButtonGroup class, and
1359 updates to the button states monitored with the
1360 \l{QButtonGroup::buttonClicked()} signal.
1362 \sa checked, clicked()
1366 \property QAbstractButton::iconSize
1367 \brief the icon size used for this button.
1369 The default size is defined by the GUI style. This is a maximum
1370 size for the icons. Smaller icons will not be scaled up.
1373 QSize QAbstractButton::iconSize() const
1375 Q_D(const QAbstractButton);
1376 if (d->iconSize.isValid())
1378 int e = style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, this);
1382 void QAbstractButton::setIconSize(const QSize &size)
1384 Q_D(QAbstractButton);
1385 if (d->iconSize == size)
1389 d->sizeHint = QSize();