Merge branch 'master' into refactor
[profile/ivi/qtbase.git] / src / widgets / widgets / qabstractbutton.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qabstractbutton.h"
43 #include "qabstractitemview.h"
44 #include "qbuttongroup.h"
45 #include "qabstractbutton_p.h"
46 #include "qevent.h"
47 #include "qpainter.h"
48 #include "qapplication.h"
49 #include "qstyle.h"
50 #include "qaction.h"
51 #ifndef QT_NO_ACCESSIBILITY
52 #include "qaccessible.h"
53 #endif
54
55 QT_BEGIN_NAMESPACE
56
57 #define AUTO_REPEAT_DELAY  300
58 #define AUTO_REPEAT_INTERVAL 100
59
60 Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets;
61
62 /*!
63     \class QAbstractButton
64
65     \brief The QAbstractButton class is the abstract base class of
66     button widgets, providing functionality common to buttons.
67
68     \ingroup abstractwidgets
69
70     This class implements an \e abstract button.
71     Subclasses of this class handle user actions, and specify how the button
72     is drawn.
73
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
78     behavior if required.
79
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.
83
84     If the button is a text button with a string containing an
85     ampersand ('&'), QAbstractButton automatically creates a shortcut
86     key. For example:
87
88     \snippet doc/src/snippets/code/src_gui_widgets_qabstractbutton.cpp 0
89
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 '&&').
94
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.
98
99     \snippet doc/src/snippets/code/src_gui_widgets_qabstractbutton.cpp 1
100
101     All of the buttons provided by Qt (QPushButton, QToolButton,
102     QCheckBox, and QRadioButton) can display both \l text and \l{icon}{icons}.
103
104     A button can be made the default button in a dialog are provided by
105     QPushButton::setDefault() and QPushButton::setAutoDefault().
106
107     QAbstractButton provides most of the states used for buttons:
108
109     \list
110
111     \o isDown() indicates whether the button is \e pressed down.
112
113     \o isChecked() indicates whether the button is \e checked.  Only
114     checkable buttons can be checked and unchecked (see below).
115
116     \o isEnabled() indicates whether the button can be pressed by the
117     user.
118
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.
122
123     \o setCheckable() sets whether the button is a toggle button or not.
124
125     \endlist
126
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).
133
134     QAbstractButton provides four signals:
135
136     \list 1
137
138     \o pressed() is emitted when the left mouse button is pressed while
139     the mouse cursor is inside the button.
140
141     \o released() is emitted when the left mouse button is released.
142
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.
146
147     \o toggled() is emitted when the state of a toggle button changes.
148
149     \endlist
150
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
157     nextCheckState().
158
159     \sa QButtonGroup
160 */
161
162 QAbstractButtonPrivate::QAbstractButtonPrivate(QSizePolicy::ControlType type)
163     :
164 #ifndef QT_NO_SHORTCUT
165     shortcutId(0),
166 #endif
167     checkable(false), checked(false), autoRepeat(false), autoExclusive(false),
168     down(false), blockRefresh(false), pressed(false),
169 #ifndef QT_NO_BUTTONGROUP
170     group(0),
171 #endif
172     autoRepeatDelay(AUTO_REPEAT_DELAY),
173     autoRepeatInterval(AUTO_REPEAT_INTERVAL),
174     controlType(type)
175 {}
176
177 #ifndef QT_NO_BUTTONGROUP
178
179 class QButtonGroupPrivate: public QObjectPrivate
180 {
181     Q_DECLARE_PUBLIC(QButtonGroup)
182
183 public:
184     QButtonGroupPrivate():exclusive(true){}
185     QList<QAbstractButton *> buttonList;
186     QPointer<QAbstractButton> checkedButton;
187     void detectCheckedButton();
188     void notifyChecked(QAbstractButton *button);
189     bool exclusive;
190     QMap<QAbstractButton*, int> mapping;
191 };
192
193 QButtonGroup::QButtonGroup(QObject *parent)
194     : QObject(*new QButtonGroupPrivate, parent)
195 {
196 }
197
198 QButtonGroup::~QButtonGroup()
199 {
200     Q_D(QButtonGroup);
201     for (int i = 0; i < d->buttonList.count(); ++i)
202         d->buttonList.at(i)->d_func()->group = 0;
203 }
204
205
206 bool QButtonGroup::exclusive() const
207 {
208     Q_D(const QButtonGroup);
209     return d->exclusive;
210 }
211
212 void QButtonGroup::setExclusive(bool exclusive)
213 {
214     Q_D(QButtonGroup);
215     d->exclusive = exclusive;
216 }
217
218
219 // TODO: Qt 5: Merge with addButton(QAbstractButton *button, int id)
220 void QButtonGroup::addButton(QAbstractButton *button)
221 {
222     addButton(button, -1);
223 }
224
225 void QButtonGroup::addButton(QAbstractButton *button, int id)
226 {
227     Q_D(QButtonGroup);
228     if (QButtonGroup *previous = button->d_func()->group)
229         previous->removeButton(button);
230     button->d_func()->group = this;
231     d->buttonList.append(button);
232     if (id == -1) {
233         QList<int> ids = d->mapping.values();
234         if (ids.isEmpty())
235            d->mapping[button] = -2;
236         else {
237             qSort(ids);
238             d->mapping[button] = ids.first()-1;
239         }
240     } else {
241         d->mapping[button] = id;
242     }
243
244     if (d->exclusive && button->isChecked())
245         button->d_func()->notifyChecked();
246 }
247
248 void QButtonGroup::removeButton(QAbstractButton *button)
249 {
250     Q_D(QButtonGroup);
251     if (d->checkedButton == button) {
252         d->detectCheckedButton();
253     }
254     if (button->d_func()->group == this) {
255         button->d_func()->group = 0;
256         d->buttonList.removeAll(button);
257         d->mapping.remove(button);
258     }
259 }
260
261 QList<QAbstractButton*> QButtonGroup::buttons() const
262 {
263     Q_D(const QButtonGroup);
264     return d->buttonList;
265 }
266
267 QAbstractButton *QButtonGroup::checkedButton() const
268 {
269     Q_D(const QButtonGroup);
270     return d->checkedButton;
271 }
272
273 QAbstractButton *QButtonGroup::button(int id) const
274 {
275     Q_D(const QButtonGroup);
276     return d->mapping.key(id);
277 }
278
279 void QButtonGroup::setId(QAbstractButton *button, int id)
280 {
281     Q_D(QButtonGroup);
282     if (button && id != -1)
283         d->mapping[button] = id;
284 }
285
286 int QButtonGroup::id(QAbstractButton *button) const
287 {
288     Q_D(const QButtonGroup);
289     return d->mapping.value(button, -1);
290 }
291
292 int QButtonGroup::checkedId() const
293 {
294     Q_D(const QButtonGroup);
295     return d->mapping.value(d->checkedButton, -1);
296 }
297
298 // detect a checked button other than the current one
299 void QButtonGroupPrivate::detectCheckedButton()
300 {
301     QAbstractButton *previous = checkedButton;
302     checkedButton = 0;
303     if (exclusive)
304         return;
305     for (int i = 0; i < buttonList.count(); i++) {
306         if (buttonList.at(i) != previous && buttonList.at(i)->isChecked()) {
307             checkedButton = buttonList.at(i);
308             return;
309         }
310     }
311 }
312
313 #endif // QT_NO_BUTTONGROUP
314
315 QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const
316 {
317 #ifndef QT_NO_BUTTONGROUP
318     if (group)
319         return group->d_func()->buttonList;
320 #endif
321
322     QList<QAbstractButton*>candidates = parent->findChildren<QAbstractButton *>();
323     if (autoExclusive) {
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()
329 #endif
330                 )
331                 candidates.removeAt(i);
332         }
333     }
334     return candidates;
335 }
336
337 QAbstractButton *QAbstractButtonPrivate::queryCheckedButton() const
338 {
339 #ifndef QT_NO_BUTTONGROUP
340     if (group)
341         return group->d_func()->checkedButton;
342 #endif
343
344     Q_Q(const QAbstractButton);
345     QList<QAbstractButton *> buttonList = queryButtonList();
346     if (!autoExclusive || buttonList.count() == 1) // no group
347         return 0;
348
349     for (int i = 0; i < buttonList.count(); ++i) {
350         QAbstractButton *b = buttonList.at(i);
351         if (b->d_func()->checked && b != q)
352             return b;
353     }
354     return checked  ? const_cast<QAbstractButton *>(q) : 0;
355 }
356
357 void QAbstractButtonPrivate::notifyChecked()
358 {
359 #ifndef QT_NO_BUTTONGROUP
360     Q_Q(QAbstractButton);
361     if (group) {
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();
366     } else
367 #endif
368     if (autoExclusive) {
369         if (QAbstractButton *b = queryCheckedButton())
370             b->setChecked(false);
371     }
372 }
373
374 void QAbstractButtonPrivate::moveFocus(int key)
375 {
376     QList<QAbstractButton *> buttonList = queryButtonList();;
377 #ifndef QT_NO_BUTTONGROUP
378     bool exclusive = group ? group->d_func()->exclusive : autoExclusive;
379 #else
380     bool exclusive = autoExclusive;
381 #endif
382     QWidget *f = QApplication::focusWidget();
383     QAbstractButton *fb = qobject_cast<QAbstractButton *>(f);
384     if (!fb || !buttonList.contains(fb))
385         return;
386     
387     QAbstractButton *candidate = 0;
388     int bestScore = -1;
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;
392
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();
399
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.
403             int score;
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());
412             } else {
413                 score = (1 << 30) + (p.y() - goal.y()) * (p.y() - goal.y()) + (p.x() - goal.x()) * (p.x() - goal.x());
414             }
415
416             if (score > bestScore && candidate)
417                 continue;
418
419             switch(key) {
420             case Qt::Key_Up:
421                 if (p.y() < goal.y()) {
422                     candidate = button;
423                     bestScore = score;
424                 }
425                 break;
426             case Qt::Key_Down:
427                 if (p.y() > goal.y()) {
428                     candidate = button;
429                     bestScore = score;
430                 }
431                 break;
432             case Qt::Key_Left:
433                 if (p.x() < goal.x()) {
434                     candidate = button;
435                     bestScore = score;
436                 }
437                 break;
438             case Qt::Key_Right:
439                 if (p.x() > goal.x()) {
440                     candidate = button;
441                     bestScore = score;
442                 }
443                 break;
444             }
445         }
446     }
447
448     if (exclusive
449 #ifdef QT_KEYPAD_NAVIGATION
450         && !QApplication::keypadNavigationEnabled()
451 #endif
452         && candidate
453         && fb->d_func()->checked
454         && candidate->d_func()->checkable)
455         candidate->click();
456
457     if (candidate) {
458         if (key == Qt::Key_Up || key == Qt::Key_Left)
459             candidate->setFocus(Qt::BacktabFocusReason);
460         else
461             candidate->setFocus(Qt::TabFocusReason);
462     }
463 }
464
465 void QAbstractButtonPrivate::fixFocusPolicy()
466 {
467     Q_Q(QAbstractButton);
468 #ifndef QT_NO_BUTTONGROUP
469     if (!group && !autoExclusive)
470 #else
471     if (!autoExclusive)
472 #endif
473         return;
474
475     QList<QAbstractButton *> buttonList = queryButtonList();
476     for (int i = 0; i < buttonList.count(); ++i) {
477         QAbstractButton *b = buttonList.at(i);
478         if (!b->isCheckable())
479             continue;
480         b->setFocusPolicy((Qt::FocusPolicy) ((b == q || !q->isCheckable())
481                                          ? (b->focusPolicy() | Qt::TabFocus)
482                                          :  (b->focusPolicy() & ~Qt::TabFocus)));
483     }
484 }
485
486 void QAbstractButtonPrivate::init()
487 {
488     Q_Q(QAbstractButton);
489
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);
495 }
496
497 void QAbstractButtonPrivate::refresh()
498 {
499     Q_Q(QAbstractButton);
500
501     if (blockRefresh)
502         return;
503     q->update();
504 #ifndef QT_NO_ACCESSIBILITY
505     QAccessible::updateAccessibility(q, 0, QAccessible::StateChanged);
506 #endif
507 }
508
509 void QAbstractButtonPrivate::click()
510 {
511     Q_Q(QAbstractButton);
512
513     down = false;
514     blockRefresh = true;
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)
520 #else
521         if (autoExclusive)
522 #endif
523             changeState = false;
524     }
525
526     QPointer<QAbstractButton> guard(q);
527     if (changeState) {
528         q->nextCheckState();
529         if (!guard)
530             return;
531     }
532     blockRefresh = false;
533     refresh();
534     q->repaint(); //flush paint event before invoking potentially expensive operation
535     QApplication::flush();
536     if (guard)
537         emitReleased();
538     if (guard)
539         emitClicked();
540 }
541
542 void QAbstractButtonPrivate::emitClicked()
543 {
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));
550         if (guard && group)
551             emit group->buttonClicked(q);
552     }
553 #endif
554 }
555
556 void QAbstractButtonPrivate::emitPressed()
557 {
558     Q_Q(QAbstractButton);
559     QPointer<QAbstractButton> guard(q);
560     emit q->pressed();
561 #ifndef QT_NO_BUTTONGROUP
562     if (guard && group) {
563         emit group->buttonPressed(group->id(q));
564         if (guard && group)
565             emit group->buttonPressed(q);
566     }
567 #endif
568 }
569
570 void QAbstractButtonPrivate::emitReleased()
571 {
572     Q_Q(QAbstractButton);
573     QPointer<QAbstractButton> guard(q);
574     emit q->released();
575 #ifndef QT_NO_BUTTONGROUP
576     if (guard && group) {
577         emit group->buttonReleased(group->id(q));
578         if (guard && group)
579             emit group->buttonReleased(q);
580     }
581 #endif
582 }
583
584 /*!
585     Constructs an abstract button with a \a parent.
586 */
587 QAbstractButton::QAbstractButton(QWidget *parent)
588     : QWidget(*new QAbstractButtonPrivate, parent, 0)
589 {
590     Q_D(QAbstractButton);
591     d->init();
592 }
593
594 /*!
595     Destroys the button.
596  */
597  QAbstractButton::~QAbstractButton()
598 {
599 #ifndef QT_NO_BUTTONGROUP
600     Q_D(QAbstractButton);
601     if (d->group)
602         d->group->removeButton(this);
603 #endif
604 }
605
606
607 /*! \internal
608  */
609 QAbstractButton::QAbstractButton(QAbstractButtonPrivate &dd, QWidget *parent)
610     : QWidget(dd, parent, 0)
611 {
612     Q_D(QAbstractButton);
613     d->init();
614 }
615
616 /*!
617 \property QAbstractButton::text
618 \brief the text shown on the button
619
620 If the button has no text, the text() function will return a an empty
621 string.
622
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 '&&').
629
630 There is no default text.
631 */
632
633 void QAbstractButton::setText(const QString &text)
634 {
635     Q_D(QAbstractButton);
636     if (d->text == text)
637         return;
638     d->text = text;
639 #ifndef QT_NO_SHORTCUT
640     QKeySequence newMnemonic = QKeySequence::mnemonic(text);
641     setShortcut(newMnemonic);
642 #endif
643     d->sizeHint = QSize();
644     update();
645     updateGeometry();
646 #ifndef QT_NO_ACCESSIBILITY
647     QAccessible::updateAccessibility(this, 0, QAccessible::NameChanged);
648 #endif
649 }
650
651 QString QAbstractButton::text() const
652 {
653     Q_D(const QAbstractButton);
654     return d->text;
655 }
656
657
658 /*!
659   \property QAbstractButton::icon
660   \brief the icon shown on the button
661
662   The icon's default size is defined by the GUI style, but can be
663   adjusted by setting the \l iconSize property.
664 */
665 void QAbstractButton::setIcon(const QIcon &icon)
666 {
667     Q_D(QAbstractButton);
668     d->icon = icon;
669     d->sizeHint = QSize();
670     update();
671     updateGeometry();
672 }
673
674 QIcon QAbstractButton::icon() const
675 {
676     Q_D(const QAbstractButton);
677     return d->icon;
678 }
679
680 #ifndef QT_NO_SHORTCUT
681 /*!
682 \property QAbstractButton::shortcut
683 \brief the mnemonic associated with the button
684 */
685
686 void QAbstractButton::setShortcut(const QKeySequence &key)
687 {
688     Q_D(QAbstractButton);
689     if (d->shortcutId != 0)
690         releaseShortcut(d->shortcutId);
691     d->shortcut = key;
692     d->shortcutId = grabShortcut(key);
693 }
694
695 QKeySequence QAbstractButton::shortcut() const
696 {
697     Q_D(const QAbstractButton);
698     return d->shortcut;
699 }
700 #endif // QT_NO_SHORTCUT
701
702 /*!
703 \property QAbstractButton::checkable
704 \brief whether the button is checkable
705
706 By default, the button is not checkable.
707
708 \sa checked
709 */
710 void QAbstractButton::setCheckable(bool checkable)
711 {
712     Q_D(QAbstractButton);
713     if (d->checkable == checkable)
714         return;
715
716     d->checkable = checkable;
717     d->checked = false;
718 }
719
720 bool QAbstractButton::isCheckable() const
721 {
722     Q_D(const QAbstractButton);
723     return d->checkable;
724 }
725
726 /*!
727 \property QAbstractButton::checked
728 \brief whether the button is checked
729
730 Only checkable buttons can be checked. By default, the button is unchecked.
731
732 \sa checkable
733 */
734 void QAbstractButton::setChecked(bool checked)
735 {
736     Q_D(QAbstractButton);
737     if (!d->checkable || d->checked == checked) {
738         if (!d->blockRefresh)
739             checkStateSet();
740         return;
741     }
742
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)
747             return;
748         if (d->group)
749             d->group->d_func()->detectCheckedButton();
750 #else
751         if (d->autoExclusive)
752             return;
753 #endif
754     }
755
756     QPointer<QAbstractButton> guard(this);
757
758     d->checked = checked;
759     if (!d->blockRefresh)
760         checkStateSet();
761     d->refresh();
762
763     if (guard && checked)
764         d->notifyChecked();
765     if (guard)
766         emit toggled(checked);
767 }
768
769 bool QAbstractButton::isChecked() const
770 {
771     Q_D(const QAbstractButton);
772     return d->checked;
773 }
774
775 /*!
776   \property QAbstractButton::down
777   \brief whether the button is pressed down
778
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.
782 */
783
784 void QAbstractButton::setDown(bool down)
785 {
786     Q_D(QAbstractButton);
787     if (d->down == down)
788         return;
789     d->down = down;
790     d->refresh();
791     if (d->autoRepeat && d->down)
792         d->repeatTimer.start(d->autoRepeatDelay, this);
793     else
794         d->repeatTimer.stop();
795 }
796
797 bool QAbstractButton::isDown() const
798 {
799     Q_D(const QAbstractButton);
800     return d->down;
801 }
802
803 /*!
804 \property QAbstractButton::autoRepeat
805 \brief whether autoRepeat is enabled
806
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.
811
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.
815 */
816
817 void QAbstractButton::setAutoRepeat(bool autoRepeat)
818 {
819     Q_D(QAbstractButton);
820     if (d->autoRepeat == autoRepeat)
821         return;
822     d->autoRepeat = autoRepeat;
823     if (d->autoRepeat && d->down)
824         d->repeatTimer.start(d->autoRepeatDelay, this);
825     else
826         d->repeatTimer.stop();
827 }
828
829 bool QAbstractButton::autoRepeat() const
830 {
831     Q_D(const QAbstractButton);
832     return d->autoRepeat;
833 }
834
835 /*!
836     \property QAbstractButton::autoRepeatDelay
837     \brief the initial delay of auto-repetition
838     \since 4.2
839
840     If \l autoRepeat is enabled, then autoRepeatDelay defines the initial
841     delay in milliseconds before auto-repetition kicks in.
842
843     \sa autoRepeat, autoRepeatInterval
844 */
845
846 void QAbstractButton::setAutoRepeatDelay(int autoRepeatDelay)
847 {
848     Q_D(QAbstractButton);
849     d->autoRepeatDelay = autoRepeatDelay;
850 }
851
852 int QAbstractButton::autoRepeatDelay() const
853 {
854     Q_D(const QAbstractButton);
855     return d->autoRepeatDelay;
856 }
857
858 /*!
859     \property QAbstractButton::autoRepeatInterval
860     \brief the interval of auto-repetition
861     \since 4.2
862
863     If \l autoRepeat is enabled, then autoRepeatInterval defines the
864     length of the auto-repetition interval in millisecons.
865
866     \sa autoRepeat, autoRepeatDelay
867 */
868
869 void QAbstractButton::setAutoRepeatInterval(int autoRepeatInterval)
870 {
871     Q_D(QAbstractButton);
872     d->autoRepeatInterval = autoRepeatInterval;
873 }
874
875 int QAbstractButton::autoRepeatInterval() const
876 {
877     Q_D(const QAbstractButton);
878     return d->autoRepeatInterval;
879 }
880
881
882
883 /*!
884 \property QAbstractButton::autoExclusive
885 \brief whether auto-exclusivity is enabled
886
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.
892
893 The property has no effect on buttons that belong to a button
894 group.
895
896 autoExclusive is off by default, except for radio buttons.
897
898 \sa QRadioButton
899 */
900 void QAbstractButton::setAutoExclusive(bool autoExclusive)
901 {
902     Q_D(QAbstractButton);
903     d->autoExclusive = autoExclusive;
904 }
905
906 bool QAbstractButton::autoExclusive() const
907 {
908     Q_D(const QAbstractButton);
909     return d->autoExclusive;
910 }
911
912 #ifndef QT_NO_BUTTONGROUP
913 /*!
914   Returns the group that this button belongs to.
915
916   If the button is not a member of any QButtonGroup, this function
917   returns 0.
918
919   \sa QButtonGroup
920 */
921 QButtonGroup *QAbstractButton::group() const
922 {
923     Q_D(const QAbstractButton);
924     return d->group;
925 }
926 #endif // QT_NO_BUTTONGROUP
927
928 /*!
929 Performs an animated click: the button is pressed immediately, and
930 released \a msec milliseconds later (the default is 100 ms).
931
932 Calling this function again before the button was released will reset
933 the release timer.
934
935 All signals associated with a click are emitted as appropriate.
936
937 This function does nothing if the button is \link setEnabled()
938 disabled. \endlink
939
940 \sa click()
941 */
942 void QAbstractButton::animateClick(int msec)
943 {
944     if (!isEnabled())
945         return;
946     Q_D(QAbstractButton);
947     if (d->checkable && focusPolicy() & Qt::ClickFocus)
948         setFocus();
949     setDown(true);
950     repaint(); //flush paint event before invoking potentially expensive operation
951     QApplication::flush();
952     if (!d->animateTimer.isActive())
953         d->emitPressed();
954     d->animateTimer.start(msec, this);
955 }
956
957 /*!
958 Performs a click.
959
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
962 toggled.
963
964 This function does nothing if the button is \link setEnabled()
965 disabled. \endlink
966
967 \sa animateClick()
968  */
969 void QAbstractButton::click()
970 {
971     if (!isEnabled())
972         return;
973     Q_D(QAbstractButton);
974     QPointer<QAbstractButton> guard(this);
975     d->down = true;
976     d->emitPressed();
977     if (guard) {
978         d->down = false;
979         nextCheckState();
980         if (guard)
981             d->emitReleased();
982         if (guard)
983             d->emitClicked();
984     }
985 }
986
987 /*! \fn void QAbstractButton::toggle()
988
989     Toggles the state of a checkable button.
990
991      \sa checked
992 */
993 void QAbstractButton::toggle()
994 {
995     Q_D(QAbstractButton);
996     setChecked(!d->checked);
997 }
998
999
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.
1003
1004 \sa nextCheckState()
1005  */
1006 void QAbstractButton::checkStateSet()
1007 {
1008 }
1009
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
1013 states.
1014
1015 \sa checkStateSet()
1016 */
1017 void QAbstractButton::nextCheckState()
1018 {
1019     if (isCheckable())
1020         setChecked(!isChecked());
1021 }
1022
1023 /*!
1024 Returns true if \a pos is inside the clickable button rectangle;
1025 otherwise returns false.
1026
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.
1030 */
1031 bool QAbstractButton::hitButton(const QPoint &pos) const
1032 {
1033     return rect().contains(pos);
1034 }
1035
1036 /*! \reimp */
1037 bool QAbstractButton::event(QEvent *e)
1038 {
1039     // as opposed to other widgets, disabled buttons accept mouse
1040     // events. This avoids surprising click-through scenarios
1041     if (!isEnabled()) {
1042         switch(e->type()) {
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
1055         case QEvent::Wheel:
1056 #endif
1057             return true;
1058         default:
1059             break;
1060         }
1061     }
1062
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())
1068             return false;
1069         if (!se->isAmbiguous()) {
1070             if (!d->animateTimer.isActive())
1071                 animateClick();
1072         } else {
1073             if (focusPolicy() != Qt::NoFocus)
1074                 setFocus(Qt::ShortcutFocusReason);
1075             window()->setAttribute(Qt::WA_KeyboardFocusChange);
1076         }
1077         return true;
1078     }
1079 #endif
1080     return QWidget::event(e);
1081 }
1082
1083 /*! \reimp */
1084 void QAbstractButton::mousePressEvent(QMouseEvent *e)
1085 {
1086     Q_D(QAbstractButton);
1087     if (e->button() != Qt::LeftButton) {
1088         e->ignore();
1089         return;
1090     }
1091     if (hitButton(e->pos())) {
1092         setDown(true);
1093         d->pressed = true;
1094         repaint(); //flush paint event before invoking potentially expensive operation
1095         QApplication::flush();
1096         d->emitPressed();
1097         e->accept();
1098     } else {
1099         e->ignore();
1100     }
1101 }
1102
1103 /*! \reimp */
1104 void QAbstractButton::mouseReleaseEvent(QMouseEvent *e)
1105 {
1106     Q_D(QAbstractButton);
1107     d->pressed = false;
1108
1109     if (e->button() != Qt::LeftButton) {
1110         e->ignore();
1111         return;
1112     }
1113
1114     if (!d->down) {
1115         e->ignore();
1116         return;
1117     }
1118
1119     if (hitButton(e->pos())) {
1120         d->repeatTimer.stop();
1121         d->click();
1122         e->accept();
1123     } else {
1124         setDown(false);
1125         e->ignore();
1126     }
1127 }
1128
1129 /*! \reimp */
1130 void QAbstractButton::mouseMoveEvent(QMouseEvent *e)
1131 {
1132     Q_D(QAbstractButton);
1133     if (!(e->buttons() & Qt::LeftButton) || !d->pressed) {
1134         e->ignore();
1135         return;
1136     }
1137
1138     if (hitButton(e->pos()) != d->down) {
1139         setDown(!d->down);
1140         repaint(); //flush paint event before invoking potentially expensive operation
1141         QApplication::flush();
1142         if (d->down)
1143             d->emitPressed();
1144         else
1145             d->emitReleased();
1146         e->accept();
1147     } else if (!hitButton(e->pos())) {
1148         e->ignore();
1149     }
1150 }
1151
1152 /*! \reimp */
1153 void QAbstractButton::keyPressEvent(QKeyEvent *e)
1154 {
1155     Q_D(QAbstractButton);
1156     bool next = true;
1157     switch (e->key()) {
1158     case Qt::Key_Enter:
1159     case Qt::Key_Return:
1160         e->ignore();
1161         break;
1162     case Qt::Key_Select:
1163     case Qt::Key_Space:
1164         if (!e->isAutoRepeat()) {
1165             setDown(true);
1166             repaint(); //flush paint event before invoking potentially expensive operation
1167             QApplication::flush();
1168             d->emitPressed();
1169         }
1170         break;
1171     case Qt::Key_Up:
1172     case Qt::Key_Left:
1173         next = false;
1174         // fall through
1175     case Qt::Key_Right:
1176     case Qt::Key_Down:
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))) {
1182             e->ignore();
1183             return;
1184         }
1185 #endif
1186         QWidget *pw;
1187         if (d->autoExclusive
1188 #ifndef QT_NO_BUTTONGROUP
1189         || d->group
1190 #endif
1191 #ifndef QT_NO_ITEMVIEWS
1192         || ((pw = parentWidget()) && qobject_cast<QAbstractItemView *>(pw->parentWidget()))
1193 #endif
1194         ) {
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
1201                 e->ignore();
1202         } else {
1203             focusNextPrevChild(next);
1204         }
1205         break;
1206     case Qt::Key_Escape:
1207         if (d->down) {
1208             setDown(false);
1209             repaint(); //flush paint event before invoking potentially expensive operation
1210             QApplication::flush();
1211             d->emitReleased();
1212             break;
1213         }
1214         // fall through
1215     default:
1216         e->ignore();
1217     }
1218 }
1219
1220 /*! \reimp */
1221 void QAbstractButton::keyReleaseEvent(QKeyEvent *e)
1222 {
1223     Q_D(QAbstractButton);
1224
1225     if (!e->isAutoRepeat())
1226         d->repeatTimer.stop();
1227
1228     switch (e->key()) {
1229     case Qt::Key_Select:
1230     case Qt::Key_Space:
1231         if (!e->isAutoRepeat() && d->down)
1232             d->click();
1233         break;
1234     default:
1235         e->ignore();
1236     }
1237 }
1238
1239 /*!\reimp
1240  */
1241 void QAbstractButton::timerEvent(QTimerEvent *e)
1242 {
1243     Q_D(QAbstractButton);
1244     if (e->timerId() == d->repeatTimer.timerId()) {
1245         d->repeatTimer.start(d->autoRepeatInterval, this);
1246         if (d->down) {
1247             QPointer<QAbstractButton> guard(this);
1248             nextCheckState();
1249             if (guard)
1250                 d->emitReleased();
1251             if (guard)
1252                 d->emitClicked();
1253             if (guard)
1254                 d->emitPressed();
1255         }
1256     } else if (e->timerId() == d->animateTimer.timerId()) {
1257         d->animateTimer.stop();
1258         d->click();
1259     }
1260 }
1261
1262 /*! \reimp */
1263 void QAbstractButton::focusInEvent(QFocusEvent *e)
1264 {
1265     Q_D(QAbstractButton);
1266 #ifdef QT_KEYPAD_NAVIGATION
1267     if (!QApplication::keypadNavigationEnabled())
1268 #endif
1269     d->fixFocusPolicy();
1270     QWidget::focusInEvent(e);
1271 }
1272
1273 /*! \reimp */
1274 void QAbstractButton::focusOutEvent(QFocusEvent *e)
1275 {
1276     Q_D(QAbstractButton);
1277     if (e->reason() != Qt::PopupFocusReason)
1278         d->down = false;
1279     QWidget::focusOutEvent(e);
1280 }
1281
1282 /*! \reimp */
1283 void QAbstractButton::changeEvent(QEvent *e)
1284 {
1285     Q_D(QAbstractButton);
1286     switch (e->type()) {
1287     case QEvent::EnabledChange:
1288         if (!isEnabled())
1289             setDown(false);
1290         break;
1291     default:
1292         d->sizeHint = QSize();
1293         break;
1294     }
1295     QWidget::changeEvent(e);
1296 }
1297
1298 /*!
1299     \fn void QAbstractButton::paintEvent(QPaintEvent *e)
1300     \reimp
1301 */
1302
1303 /*!
1304     \fn void QAbstractButton::pressed()
1305
1306     This signal is emitted when the button is pressed down.
1307
1308     \sa released(), clicked()
1309 */
1310
1311 /*!
1312     \fn void QAbstractButton::released()
1313
1314     This signal is emitted when the button is released.
1315
1316     \sa pressed(), clicked(), toggled()
1317 */
1318
1319 /*!
1320 \fn void QAbstractButton::clicked(bool checked)
1321
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().
1327
1328 If the button is checkable, \a checked is true if the button is
1329 checked, or false if the button is unchecked.
1330
1331 \sa pressed(), released(), toggled()
1332 */
1333
1334 /*!
1335 \fn void QAbstractButton::toggled(bool checked)
1336
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
1339 unchecked.
1340
1341 This may be the result of a user action, click() slot activation,
1342 or because setChecked() was called.
1343
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.
1348
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:
1352
1353 \snippet doc/src/snippets/code/src_gui_widgets_qabstractbutton.cpp 2
1354
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.
1358
1359 \sa checked, clicked()
1360 */
1361
1362 /*!
1363     \property QAbstractButton::iconSize
1364     \brief the icon size used for this button.
1365
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.
1368 */
1369
1370 QSize QAbstractButton::iconSize() const
1371 {
1372     Q_D(const QAbstractButton);
1373     if (d->iconSize.isValid())
1374         return d->iconSize;
1375     int e = style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, this);
1376     return QSize(e, e);
1377 }
1378
1379 void QAbstractButton::setIconSize(const QSize &size)
1380 {
1381     Q_D(QAbstractButton);
1382     if (d->iconSize == size)
1383         return;
1384
1385     d->iconSize = size;
1386     d->sizeHint = QSize();
1387     updateGeometry();
1388     if (isVisible()) {
1389         update();
1390     }
1391 }
1392
1393
1394 #ifdef QT3_SUPPORT
1395 /*!
1396     Use icon() instead.
1397 */
1398 QIcon *QAbstractButton::iconSet() const
1399 {
1400     Q_D(const QAbstractButton);
1401     if (!d->icon.isNull())
1402         return const_cast<QIcon *>(&d->icon);
1403     return 0;
1404 }
1405
1406 /*!
1407     Use QAbstractButton(QWidget *) instead.
1408
1409     Call setObjectName() if you want to specify an object name, and
1410     setParent() if you want to set the window flags.
1411 */
1412 QAbstractButton::QAbstractButton(QWidget *parent, const char *name, Qt::WindowFlags f)
1413     : QWidget(*new QAbstractButtonPrivate, parent, f)
1414 {
1415     Q_D(QAbstractButton);
1416     setObjectName(QString::fromAscii(name));
1417     d->init();
1418 }
1419
1420 /*! \fn bool QAbstractButton::isOn() const
1421
1422     Use isChecked() instead.
1423 */
1424
1425 /*!
1426     \fn QPixmap *QAbstractButton::pixmap() const
1427
1428     This compatibility function always returns 0.
1429
1430     Use icon() instead.
1431 */
1432
1433 /*! \fn void QAbstractButton::setPixmap(const QPixmap &p)
1434
1435     Use setIcon() instead.
1436 */
1437
1438 /*! \fn void QAbstractButton::setIconSet(const QIcon &icon)
1439
1440     Use setIcon() instead.
1441 */
1442
1443 /*! \fn void QAbstractButton::setOn(bool b)
1444
1445     Use setChecked() instead.
1446 */
1447
1448 /*! \fn bool QAbstractButton::isToggleButton() const
1449
1450     Use isCheckable() instead.
1451 */
1452
1453 /*!
1454     \fn void QAbstractButton::setToggleButton(bool b)
1455
1456     Use setCheckable() instead.
1457 */
1458
1459 /*! \fn void QAbstractButton::setAccel(const QKeySequence &key)
1460
1461     Use setShortcut() instead.
1462 */
1463
1464 /*! \fn QKeySequence QAbstractButton::accel() const
1465
1466     Use shortcut() instead.
1467 */
1468 #endif
1469
1470 QT_END_NAMESPACE