src/gui/widgets/qcheckbox.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
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 "qcheckbox.h"
       
    43 #include "qapplication.h"
       
    44 #include "qbitmap.h"
       
    45 #include "qicon.h"
       
    46 #include "qstylepainter.h"
       
    47 #include "qstyle.h"
       
    48 #include "qstyleoption.h"
       
    49 #include "qevent.h"
       
    50 
       
    51 #include "private/qabstractbutton_p.h"
       
    52 
       
    53 QT_BEGIN_NAMESPACE
       
    54 
       
    55 class QCheckBoxPrivate : public QAbstractButtonPrivate
       
    56 {
       
    57     Q_DECLARE_PUBLIC(QCheckBox)
       
    58 public:
       
    59     QCheckBoxPrivate()
       
    60         : QAbstractButtonPrivate(QSizePolicy::CheckBox), tristate(false), noChange(false),
       
    61           hovering(true), publishedState(Qt::Unchecked) {}
       
    62 
       
    63     uint tristate : 1;
       
    64     uint noChange : 1;
       
    65     uint hovering : 1;
       
    66     uint publishedState : 2;
       
    67 
       
    68     void init();
       
    69 };
       
    70 
       
    71 /*!
       
    72     \class QCheckBox
       
    73     \brief The QCheckBox widget provides a checkbox with a text label.
       
    74 
       
    75     \ingroup basicwidgets
       
    76 
       
    77 
       
    78     A QCheckBox is an option button that can be switched on (checked) or off
       
    79     (unchecked). Checkboxes are typically used to represent features in an
       
    80     application that can be enabled or disabled without affecting others, but
       
    81     different types of behavior can be implemented. For example, a
       
    82     QButtonGroup can be used to group check buttons logically, allowing
       
    83     exclusive checkboxes. However, QButtonGroup does not provide any visual
       
    84     representation.
       
    85 
       
    86     The image below further illustrates the differences between exclusive and
       
    87     non-exclusive checkboxes.
       
    88 
       
    89     \table
       
    90     \row \o \inlineimage checkboxes-exclusive.png
       
    91          \o \inlineimage checkboxes-non-exclusive.png
       
    92     \endtable
       
    93 
       
    94     Whenever a checkbox is checked or cleared it emits the signal
       
    95     stateChanged(). Connect to this signal if you want to trigger an action
       
    96     each time the checkbox changes state. You can use isChecked() to query
       
    97     whether or not a checkbox is checked.
       
    98 
       
    99     In addition to the usual checked and unchecked states, QCheckBox optionally
       
   100     provides a third state to indicate "no change". This is useful whenever you
       
   101     need to give the user the option of neither checking nor unchecking a
       
   102     checkbox. If you need this third state, enable it with setTristate(), and
       
   103     use checkState() to query the current toggle state.
       
   104 
       
   105     Just like QPushButton, a checkbox displays text, and optionally a small
       
   106     icon. The icon is set with setIcon(). The text can be set in the
       
   107     constructor or with setText(). A shortcut key can be specified by preceding
       
   108     the preferred character with an ampersand. For example:
       
   109 
       
   110     \snippet doc/src/snippets/code/src_gui_widgets_qcheckbox.cpp 0
       
   111 
       
   112     In this example the shortcut is \e{Alt+A}. See the \l{QShortcut#mnemonic}
       
   113     {QShortcut} documentation for details (to display an actual ampersand,
       
   114     use '&&').
       
   115 
       
   116     Important inherited functions: text(), setText(), text(), pixmap(),
       
   117     setPixmap(), accel(), setAccel(), isToggleButton(), setDown(), isDown(),
       
   118     isOn(), checkState(), autoRepeat(), isExclusiveToggle(), group(),
       
   119     setAutoRepeat(), toggle(), pressed(), released(), clicked(), toggled(),
       
   120     checkState(), and stateChanged().
       
   121 
       
   122     \table 100%
       
   123     \row
       
   124         \o \inlineimage macintosh-checkbox.png Screenshot of a Macintosh style checkbox
       
   125         \o A checkbox shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
       
   126     \row
       
   127         \o \inlineimage windows-checkbox.png Screenshot of a Windows XP style checkbox
       
   128         \o A checkbox shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
       
   129     \row
       
   130         \o \inlineimage plastique-checkbox.png Screenshot of a Plastique style checkbox
       
   131         \o A checkbox shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
       
   132     \endtable
       
   133 
       
   134     \sa QAbstractButton, QRadioButton, {fowler}{GUI Design Handbook: Check Box}
       
   135 */
       
   136 
       
   137 /*!
       
   138     \enum QCheckBox::ToggleState
       
   139     \compat
       
   140 
       
   141     \value Off  Use Qt::Unchecked instead.
       
   142     \value NoChange  Use Qt::PartiallyChecked instead.
       
   143     \value On  Use Qt::Checked instead.
       
   144 */
       
   145 
       
   146 /*!
       
   147     \fn void QCheckBox::stateChanged(int state)
       
   148 
       
   149     This signal is emitted whenever the check box's state changes, i.e.
       
   150     whenever the user checks or unchecks it.
       
   151 
       
   152     \a state contains the check box's new Qt::CheckState.
       
   153 */
       
   154 
       
   155 /*!
       
   156     \property QCheckBox::tristate
       
   157     \brief whether the checkbox is a tri-state checkbox
       
   158 
       
   159     The default is false; i.e. the checkbox has only two states.
       
   160 */
       
   161 
       
   162 void QCheckBoxPrivate::init()
       
   163 {
       
   164     Q_Q(QCheckBox);
       
   165     q->setCheckable(true);
       
   166     q->setMouseTracking(true);
       
   167     q->setForegroundRole(QPalette::WindowText);
       
   168     setLayoutItemMargins(QStyle::SE_CheckBoxLayoutItem);
       
   169 }
       
   170 
       
   171 /*!
       
   172     Initializes \a option with the values from this QCheckBox. This method is
       
   173     useful for subclasses that require a QStyleOptionButton, but do not want
       
   174     to fill in all the information themselves.
       
   175 
       
   176     \sa QStyleOption::initFrom()
       
   177 */
       
   178 void QCheckBox::initStyleOption(QStyleOptionButton *option) const
       
   179 {
       
   180     if (!option)
       
   181         return;
       
   182     Q_D(const QCheckBox);
       
   183     option->initFrom(this);
       
   184     if (d->down)
       
   185         option->state |= QStyle::State_Sunken;
       
   186     if (d->tristate && d->noChange)
       
   187         option->state |= QStyle::State_NoChange;
       
   188     else
       
   189         option->state |= d->checked ? QStyle::State_On : QStyle::State_Off;
       
   190     if (testAttribute(Qt::WA_Hover) && underMouse()) {
       
   191         if (d->hovering)
       
   192             option->state |= QStyle::State_MouseOver;
       
   193         else
       
   194             option->state &= ~QStyle::State_MouseOver;
       
   195     }
       
   196     option->text = d->text;
       
   197     option->icon = d->icon;
       
   198     option->iconSize = iconSize();
       
   199 }
       
   200 
       
   201 /*!
       
   202     Constructs a checkbox with the given \a parent, but with no text.
       
   203 
       
   204     \a parent is passed on to the QAbstractButton constructor.
       
   205 */
       
   206 
       
   207 QCheckBox::QCheckBox(QWidget *parent)
       
   208     : QAbstractButton (*new QCheckBoxPrivate, parent)
       
   209 {
       
   210     Q_D(QCheckBox);
       
   211     d->init();
       
   212 }
       
   213 
       
   214 /*!
       
   215     Constructs a checkbox with the given \a parent and \a text.
       
   216 
       
   217     \a parent is passed on to the QAbstractButton constructor.
       
   218 */
       
   219 
       
   220 QCheckBox::QCheckBox(const QString &text, QWidget *parent)
       
   221     : QAbstractButton (*new QCheckBoxPrivate, parent)
       
   222 {
       
   223     Q_D(QCheckBox);
       
   224     d->init();
       
   225     setText(text);
       
   226 }
       
   227 
       
   228 void QCheckBox::setTristate(bool y)
       
   229 {
       
   230     Q_D(QCheckBox);
       
   231     d->tristate = y;
       
   232 }
       
   233 
       
   234 bool QCheckBox::isTristate() const
       
   235 {
       
   236     Q_D(const QCheckBox);
       
   237     return d->tristate;
       
   238 }
       
   239 
       
   240 
       
   241 /*!
       
   242     Returns the check box's check state. If you do not need tristate support,
       
   243     you can also  use \l QAbstractButton::isChecked() which returns a boolean.
       
   244 
       
   245     \sa setCheckState() Qt::CheckState
       
   246 */
       
   247 Qt::CheckState QCheckBox::checkState() const
       
   248 {
       
   249     Q_D(const QCheckBox);
       
   250     if (d->tristate &&  d->noChange)
       
   251         return Qt::PartiallyChecked;
       
   252     return d->checked ? Qt::Checked : Qt::Unchecked;
       
   253 }
       
   254 
       
   255 /*!
       
   256     Sets the check box's check state to \a state. If you do not need tristate
       
   257     support, you can also use \l QAbstractButton::setChecked() which takes a
       
   258     boolean.
       
   259 
       
   260     \sa checkState() Qt::CheckState
       
   261 */
       
   262 void QCheckBox::setCheckState(Qt::CheckState state)
       
   263 {
       
   264     Q_D(QCheckBox);
       
   265     if (state == Qt::PartiallyChecked) {
       
   266         d->tristate = true;
       
   267         d->noChange = true;
       
   268     } else {
       
   269         d->noChange = false;
       
   270     }
       
   271     d->blockRefresh = true;
       
   272     setChecked(state != Qt::Unchecked);
       
   273     d->blockRefresh = false;
       
   274     d->refresh();
       
   275     if ((uint)state != d->publishedState) {
       
   276         d->publishedState = state;
       
   277         emit stateChanged(state);
       
   278     }
       
   279 }
       
   280 
       
   281 
       
   282 /*!
       
   283     \reimp
       
   284 */
       
   285 QSize QCheckBox::sizeHint() const
       
   286 {
       
   287     Q_D(const QCheckBox);
       
   288     if (d->sizeHint.isValid())
       
   289         return d->sizeHint;
       
   290     ensurePolished();
       
   291     QFontMetrics fm = fontMetrics();
       
   292     QStyleOptionButton opt;
       
   293     initStyleOption(&opt);
       
   294     QSize sz = style()->itemTextRect(fm, QRect(0, 0, 1, 1), Qt::TextShowMnemonic, false,
       
   295                                      text()).size();
       
   296     if (!opt.icon.isNull())
       
   297         sz = QSize(sz.width() + opt.iconSize.width() + 4, qMax(sz.height(), opt.iconSize.height()));
       
   298     d->sizeHint = (style()->sizeFromContents(QStyle::CT_CheckBox, &opt, sz, this)
       
   299                   .expandedTo(QApplication::globalStrut()));
       
   300     return d->sizeHint;
       
   301 }
       
   302 
       
   303 /*!
       
   304     \reimp
       
   305 */
       
   306 void QCheckBox::paintEvent(QPaintEvent *)
       
   307 {
       
   308     QStylePainter p(this);
       
   309     QStyleOptionButton opt;
       
   310     initStyleOption(&opt);
       
   311     p.drawControl(QStyle::CE_CheckBox, opt);
       
   312 }
       
   313 
       
   314 /*!
       
   315     \reimp
       
   316 */
       
   317 void QCheckBox::mouseMoveEvent(QMouseEvent *e)
       
   318 {
       
   319     Q_D(QCheckBox);
       
   320     if (testAttribute(Qt::WA_Hover)) {
       
   321         bool hit = false;
       
   322         if (underMouse())
       
   323             hit = hitButton(e->pos());
       
   324 
       
   325         if (hit != d->hovering) {
       
   326             update(rect());
       
   327             d->hovering = hit;
       
   328         }
       
   329     }
       
   330 
       
   331     QAbstractButton::mouseMoveEvent(e);
       
   332 }
       
   333 
       
   334 
       
   335 /*!
       
   336     \reimp
       
   337 */
       
   338 bool QCheckBox::hitButton(const QPoint &pos) const
       
   339 {
       
   340     QStyleOptionButton opt;
       
   341     initStyleOption(&opt);
       
   342     return style()->subElementRect(QStyle::SE_CheckBoxClickRect, &opt, this).contains(pos);
       
   343 }
       
   344 
       
   345 /*!
       
   346     \reimp
       
   347 */
       
   348 void QCheckBox::checkStateSet()
       
   349 {
       
   350     Q_D(QCheckBox);
       
   351     d->noChange = false;
       
   352     Qt::CheckState state = checkState();
       
   353     if ((uint)state != d->publishedState) {
       
   354         d->publishedState = state;
       
   355         emit stateChanged(state);
       
   356     }
       
   357 }
       
   358 
       
   359 /*!
       
   360     \reimp
       
   361 */
       
   362 void QCheckBox::nextCheckState()
       
   363 {
       
   364     Q_D(QCheckBox);
       
   365     if (d->tristate)
       
   366         setCheckState((Qt::CheckState)((checkState() + 1) % 3));
       
   367     else {
       
   368         QAbstractButton::nextCheckState();
       
   369         QCheckBox::checkStateSet();
       
   370     }
       
   371 }
       
   372 
       
   373 /*!
       
   374     \reimp
       
   375 */
       
   376 bool QCheckBox::event(QEvent *e)
       
   377 {
       
   378     Q_D(QCheckBox);
       
   379     if (e->type() == QEvent::StyleChange
       
   380 #ifdef Q_WS_MAC
       
   381             || e->type() == QEvent::MacSizeChange
       
   382 #endif
       
   383             )
       
   384         d->setLayoutItemMargins(QStyle::SE_CheckBoxLayoutItem);
       
   385     return QAbstractButton::event(e);
       
   386 }
       
   387 
       
   388 #ifdef QT3_SUPPORT
       
   389 /*!
       
   390     Use one of the constructors that doesn't take the \a name
       
   391     argument and then use setObjectName() instead.
       
   392 */
       
   393 QCheckBox::QCheckBox(QWidget *parent, const char* name)
       
   394     : QAbstractButton (*new QCheckBoxPrivate, parent)
       
   395 {
       
   396     Q_D(QCheckBox);
       
   397     setObjectName(QString::fromAscii(name));
       
   398     d->init();
       
   399 }
       
   400 
       
   401 /*!
       
   402     Use one of the constructors that doesn't take the \a name
       
   403     argument and then use setObjectName() instead.
       
   404 */
       
   405 QCheckBox::QCheckBox(const QString &text, QWidget *parent, const char* name)
       
   406     : QAbstractButton (*new QCheckBoxPrivate, parent)
       
   407 {
       
   408     Q_D(QCheckBox);
       
   409     setObjectName(QString::fromAscii(name));
       
   410     d->init();
       
   411     setText(text);
       
   412 }
       
   413 
       
   414 #endif
       
   415 
       
   416 
       
   417 /*!
       
   418     \fn void QCheckBox::setNoChange()
       
   419     \compat
       
   420 
       
   421     Use setCheckState() instead.
       
   422 */
       
   423 
       
   424 /*!
       
   425     \fn void QCheckBox::setState(ToggleState state)
       
   426     \compat
       
   427 
       
   428     Use setCheckState() instead.
       
   429 */
       
   430 
       
   431 /*!
       
   432     \fn QCheckBox::ToggleState QCheckBox::state() const
       
   433     \compat
       
   434 
       
   435     Use checkState() instead.
       
   436 */
       
   437 
       
   438 QT_END_NAMESPACE