util/src/gui/widgets/qabstractbutton.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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), 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 = 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         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