src/gui/widgets/qabstractbutton.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    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 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),
       
   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 = qFindChildren<QAbstractButton *>(parent);
       
   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         repaint(); //flush paint event before invoking potentially expensive operation
       
  1094         QApplication::flush();
       
  1095         d->emitPressed();
       
  1096         e->accept();
       
  1097     } else {
       
  1098         e->ignore();
       
  1099     }
       
  1100 }
       
  1101 
       
  1102 /*! \reimp */
       
  1103 void QAbstractButton::mouseReleaseEvent(QMouseEvent *e)
       
  1104 {
       
  1105     Q_D(QAbstractButton);
       
  1106     if (e->button() != Qt::LeftButton) {
       
  1107         e->ignore();
       
  1108         return;
       
  1109     }
       
  1110 
       
  1111     if (!d->down) {
       
  1112         e->ignore();
       
  1113         return;
       
  1114     }
       
  1115 
       
  1116     if (hitButton(e->pos())) {
       
  1117         d->repeatTimer.stop();
       
  1118         d->click();
       
  1119         e->accept();
       
  1120     } else {
       
  1121         setDown(false);
       
  1122         e->ignore();
       
  1123     }
       
  1124 }
       
  1125 
       
  1126 /*! \reimp */
       
  1127 void QAbstractButton::mouseMoveEvent(QMouseEvent *e)
       
  1128 {
       
  1129     Q_D(QAbstractButton);
       
  1130     if (!(e->buttons() & Qt::LeftButton)) {
       
  1131         e->ignore();
       
  1132         return;
       
  1133     }
       
  1134 
       
  1135     if (hitButton(e->pos()) != d->down) {
       
  1136         setDown(!d->down);
       
  1137         repaint(); //flush paint event before invoking potentially expensive operation
       
  1138         QApplication::flush();
       
  1139         if (d->down)
       
  1140             d->emitPressed();
       
  1141         else
       
  1142             d->emitReleased();
       
  1143         e->accept();
       
  1144     } else if (!hitButton(e->pos())) {
       
  1145         e->ignore();
       
  1146     }
       
  1147 }
       
  1148 
       
  1149 /*! \reimp */
       
  1150 void QAbstractButton::keyPressEvent(QKeyEvent *e)
       
  1151 {
       
  1152     Q_D(QAbstractButton);
       
  1153     bool next = true;
       
  1154     switch (e->key()) {
       
  1155     case Qt::Key_Enter:
       
  1156     case Qt::Key_Return:
       
  1157         e->ignore();
       
  1158         break;
       
  1159     case Qt::Key_Select:
       
  1160     case Qt::Key_Space:
       
  1161         if (!e->isAutoRepeat()) {
       
  1162             setDown(true);
       
  1163             repaint(); //flush paint event before invoking potentially expensive operation
       
  1164             QApplication::flush();
       
  1165             d->emitPressed();
       
  1166         }
       
  1167         break;
       
  1168     case Qt::Key_Up:
       
  1169     case Qt::Key_Left:
       
  1170         next = false;
       
  1171         // fall through
       
  1172     case Qt::Key_Right:
       
  1173     case Qt::Key_Down:
       
  1174 #ifdef QT_KEYPAD_NAVIGATION
       
  1175         if ((QApplication::keypadNavigationEnabled()
       
  1176                 && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right))
       
  1177                 || (!QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional
       
  1178                 || (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down))) {
       
  1179             e->ignore();
       
  1180             return;
       
  1181         }
       
  1182 #endif
       
  1183         QWidget *pw;
       
  1184         if (d->autoExclusive
       
  1185 #ifndef QT_NO_BUTTONGROUP
       
  1186         || d->group
       
  1187 #endif
       
  1188 #ifndef QT_NO_ITEMVIEWS
       
  1189         || ((pw = parentWidget()) && qobject_cast<QAbstractItemView *>(pw->parentWidget()))
       
  1190 #endif
       
  1191         ) {
       
  1192             // ### Using qobject_cast to check if the parent is a viewport of
       
  1193             // QAbstractItemView is a crude hack, and should be revisited and
       
  1194             // cleaned up when fixing task 194373. It's here to ensure that we
       
  1195             // keep compatibility outside QAbstractItemView.
       
  1196             d->moveFocus(e->key());
       
  1197             if (hasFocus()) // nothing happend, propagate
       
  1198                 e->ignore();
       
  1199         } else {
       
  1200             focusNextPrevChild(next);
       
  1201         }
       
  1202         break;
       
  1203     case Qt::Key_Escape:
       
  1204         if (d->down) {
       
  1205             setDown(false);
       
  1206             repaint(); //flush paint event before invoking potentially expensive operation
       
  1207             QApplication::flush();
       
  1208             d->emitReleased();
       
  1209             break;
       
  1210         }
       
  1211         // fall through
       
  1212     default:
       
  1213         e->ignore();
       
  1214     }
       
  1215 }
       
  1216 
       
  1217 /*! \reimp */
       
  1218 void QAbstractButton::keyReleaseEvent(QKeyEvent *e)
       
  1219 {
       
  1220     Q_D(QAbstractButton);
       
  1221 
       
  1222     if (!e->isAutoRepeat())
       
  1223         d->repeatTimer.stop();
       
  1224 
       
  1225     switch (e->key()) {
       
  1226     case Qt::Key_Select:
       
  1227     case Qt::Key_Space:
       
  1228         if (!e->isAutoRepeat() && d->down)
       
  1229             d->click();
       
  1230         break;
       
  1231     default:
       
  1232         e->ignore();
       
  1233     }
       
  1234 }
       
  1235 
       
  1236 /*!\reimp
       
  1237  */
       
  1238 void QAbstractButton::timerEvent(QTimerEvent *e)
       
  1239 {
       
  1240     Q_D(QAbstractButton);
       
  1241     if (e->timerId() == d->repeatTimer.timerId()) {
       
  1242         d->repeatTimer.start(d->autoRepeatInterval, this);
       
  1243         if (d->down) {
       
  1244             QPointer<QAbstractButton> guard(this);
       
  1245             nextCheckState();
       
  1246             if (guard)
       
  1247                 d->emitReleased();
       
  1248             if (guard)
       
  1249                 d->emitClicked();
       
  1250             if (guard)
       
  1251                 d->emitPressed();
       
  1252         }
       
  1253     } else if (e->timerId() == d->animateTimer.timerId()) {
       
  1254         d->animateTimer.stop();
       
  1255         d->click();
       
  1256     }
       
  1257 }
       
  1258 
       
  1259 /*! \reimp */
       
  1260 void QAbstractButton::focusInEvent(QFocusEvent *e)
       
  1261 {
       
  1262     Q_D(QAbstractButton);
       
  1263 #ifdef QT_KEYPAD_NAVIGATION
       
  1264     if (!QApplication::keypadNavigationEnabled())
       
  1265 #endif
       
  1266     d->fixFocusPolicy();
       
  1267     QWidget::focusInEvent(e);
       
  1268 }
       
  1269 
       
  1270 /*! \reimp */
       
  1271 void QAbstractButton::focusOutEvent(QFocusEvent *e)
       
  1272 {
       
  1273     Q_D(QAbstractButton);
       
  1274     if (e->reason() != Qt::PopupFocusReason)
       
  1275         d->down = false;
       
  1276     QWidget::focusOutEvent(e);
       
  1277 }
       
  1278 
       
  1279 /*! \reimp */
       
  1280 void QAbstractButton::changeEvent(QEvent *e)
       
  1281 {
       
  1282     Q_D(QAbstractButton);
       
  1283     switch (e->type()) {
       
  1284     case QEvent::EnabledChange:
       
  1285         if (!isEnabled())
       
  1286             setDown(false);
       
  1287         break;
       
  1288     default:
       
  1289         d->sizeHint = QSize();
       
  1290         break;
       
  1291     }
       
  1292     QWidget::changeEvent(e);
       
  1293 }
       
  1294 
       
  1295 /*!
       
  1296     \fn void QAbstractButton::paintEvent(QPaintEvent *e)
       
  1297     \reimp
       
  1298 */
       
  1299 
       
  1300 /*!
       
  1301     \fn void QAbstractButton::pressed()
       
  1302 
       
  1303     This signal is emitted when the button is pressed down.
       
  1304 
       
  1305     \sa released(), clicked()
       
  1306 */
       
  1307 
       
  1308 /*!
       
  1309     \fn void QAbstractButton::released()
       
  1310 
       
  1311     This signal is emitted when the button is released.
       
  1312 
       
  1313     \sa pressed(), clicked(), toggled()
       
  1314 */
       
  1315 
       
  1316 /*!
       
  1317 \fn void QAbstractButton::clicked(bool checked)
       
  1318 
       
  1319 This signal is emitted when the button is activated (i.e. pressed down
       
  1320 then released while the mouse cursor is inside the button), when the
       
  1321 shortcut key is typed, or when click() or animateClick() is called.
       
  1322 Notably, this signal is \e not emitted if you call setDown(),
       
  1323 setChecked() or toggle().
       
  1324 
       
  1325 If the button is checkable, \a checked is true if the button is
       
  1326 checked, or false if the button is unchecked.
       
  1327 
       
  1328 \sa pressed(), released(), toggled()
       
  1329 */
       
  1330 
       
  1331 /*!
       
  1332 \fn void QAbstractButton::toggled(bool checked)
       
  1333 
       
  1334 This signal is emitted whenever a checkable button changes its state.
       
  1335 \a checked is true if the button is checked, or false if the button is
       
  1336 unchecked.
       
  1337 
       
  1338 This may be the result of a user action, click() slot activation,
       
  1339 or because setChecked() was called.
       
  1340 
       
  1341 The states of buttons in exclusive button groups are updated before this
       
  1342 signal is emitted. This means that slots can act on either the "off"
       
  1343 signal or the "on" signal emitted by the buttons in the group whose
       
  1344 states have changed.
       
  1345 
       
  1346 For example, a slot that reacts to signals emitted by newly checked
       
  1347 buttons but which ignores signals from buttons that have been unchecked
       
  1348 can be implemented using the following pattern:
       
  1349 
       
  1350 \snippet doc/src/snippets/code/src_gui_widgets_qabstractbutton.cpp 2
       
  1351 
       
  1352 Button groups can be created using the QButtonGroup class, and
       
  1353 updates to the button states monitored with the
       
  1354 \l{QButtonGroup::buttonClicked()} signal.
       
  1355 
       
  1356 \sa checked, clicked()
       
  1357 */
       
  1358 
       
  1359 /*!
       
  1360     \property QAbstractButton::iconSize
       
  1361     \brief the icon size used for this button.
       
  1362 
       
  1363     The default size is defined by the GUI style. This is a maximum
       
  1364     size for the icons. Smaller icons will not be scaled up.
       
  1365 */
       
  1366 
       
  1367 QSize QAbstractButton::iconSize() const
       
  1368 {
       
  1369     Q_D(const QAbstractButton);
       
  1370     if (d->iconSize.isValid())
       
  1371         return d->iconSize;
       
  1372     int e = style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, this);
       
  1373     return QSize(e, e);
       
  1374 }
       
  1375 
       
  1376 void QAbstractButton::setIconSize(const QSize &size)
       
  1377 {
       
  1378     Q_D(QAbstractButton);
       
  1379     if (d->iconSize == size)
       
  1380         return;
       
  1381 
       
  1382     d->iconSize = size;
       
  1383     d->sizeHint = QSize();
       
  1384     updateGeometry();
       
  1385     if (isVisible()) {
       
  1386         update();
       
  1387     }
       
  1388 }
       
  1389 
       
  1390 
       
  1391 #ifdef QT3_SUPPORT
       
  1392 /*!
       
  1393     Use icon() instead.
       
  1394 */
       
  1395 QIcon *QAbstractButton::iconSet() const
       
  1396 {
       
  1397     Q_D(const QAbstractButton);
       
  1398     if (!d->icon.isNull())
       
  1399         return const_cast<QIcon *>(&d->icon);
       
  1400     return 0;
       
  1401 }
       
  1402 
       
  1403 /*!
       
  1404     Use QAbstractButton(QWidget *) instead.
       
  1405 
       
  1406     Call setObjectName() if you want to specify an object name, and
       
  1407     setParent() if you want to set the window flags.
       
  1408 */
       
  1409 QAbstractButton::QAbstractButton(QWidget *parent, const char *name, Qt::WindowFlags f)
       
  1410     : QWidget(*new QAbstractButtonPrivate, parent, f)
       
  1411 {
       
  1412     Q_D(QAbstractButton);
       
  1413     setObjectName(QString::fromAscii(name));
       
  1414     d->init();
       
  1415 }
       
  1416 
       
  1417 /*! \fn bool QAbstractButton::isOn() const
       
  1418 
       
  1419     Use isChecked() instead.
       
  1420 */
       
  1421 
       
  1422 /*!
       
  1423     \fn QPixmap *QAbstractButton::pixmap() const
       
  1424 
       
  1425     This compatibility function always returns 0.
       
  1426 
       
  1427     Use icon() instead.
       
  1428 */
       
  1429 
       
  1430 /*! \fn void QAbstractButton::setPixmap(const QPixmap &p)
       
  1431 
       
  1432     Use setIcon() instead.
       
  1433 */
       
  1434 
       
  1435 /*! \fn void QAbstractButton::setIconSet(const QIcon &icon)
       
  1436 
       
  1437     Use setIcon() instead.
       
  1438 */
       
  1439 
       
  1440 /*! \fn void QAbstractButton::setOn(bool b)
       
  1441 
       
  1442     Use setChecked() instead.
       
  1443 */
       
  1444 
       
  1445 /*! \fn bool QAbstractButton::isToggleButton() const
       
  1446 
       
  1447     Use isCheckable() instead.
       
  1448 */
       
  1449 
       
  1450 /*!
       
  1451     \fn void QAbstractButton::setToggleButton(bool b)
       
  1452 
       
  1453     Use setCheckable() instead.
       
  1454 */
       
  1455 
       
  1456 /*! \fn void QAbstractButton::setAccel(const QKeySequence &key)
       
  1457 
       
  1458     Use setShortcut() instead.
       
  1459 */
       
  1460 
       
  1461 /*! \fn QKeySequence QAbstractButton::accel() const
       
  1462 
       
  1463     Use shortcut() instead.
       
  1464 */
       
  1465 #endif
       
  1466 
       
  1467 QT_END_NAMESPACE