source: trunk/src/gui/widgets/qcheckbox.cpp@ 858

Last change on this file since 858 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 12.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
53QT_BEGIN_NAMESPACE
54
55class QCheckBoxPrivate : public QAbstractButtonPrivate
56{
57 Q_DECLARE_PUBLIC(QCheckBox)
58public:
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
162void 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*/
178void 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
207QCheckBox::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
220QCheckBox::QCheckBox(const QString &text, QWidget *parent)
221 : QAbstractButton (*new QCheckBoxPrivate, parent)
222{
223 Q_D(QCheckBox);
224 d->init();
225 setText(text);
226}
227
228void QCheckBox::setTristate(bool y)
229{
230 Q_D(QCheckBox);
231 d->tristate = y;
232}
233
234bool 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*/
247Qt::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*/
262void 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*/
285QSize 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(), 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*/
306void 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*/
317void 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*/
338bool 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*/
348void 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*/
362void 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*/
376bool 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*/
393QCheckBox::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*/
405QCheckBox::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
438QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.