1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "private/qbuttongroup_p.h"
41
42#include "private/qabstractbutton_p.h"
43
44QT_BEGIN_NAMESPACE
45
46// detect a checked button other than the current one
47void QButtonGroupPrivate::detectCheckedButton()
48{
49 QAbstractButton *previous = checkedButton;
50 checkedButton = nullptr;
51 if (exclusive)
52 return;
53 for (int i = 0; i < buttonList.count(); i++) {
54 if (buttonList.at(i) != previous && buttonList.at(i)->isChecked()) {
55 checkedButton = buttonList.at(i);
56 return;
57 }
58 }
59}
60
61/*!
62 \class QButtonGroup
63 \brief The QButtonGroup class provides a container to organize groups of
64 button widgets.
65
66 \ingroup organizers
67 \ingroup geomanagement
68 \inmodule QtWidgets
69
70 QButtonGroup provides an abstract container into which button widgets can
71 be placed. It does not provide a visual representation of this container
72 (see QGroupBox for a container widget), but instead manages the states of
73 each of the buttons in the group.
74
75 An \l {QButtonGroup::exclusive} {exclusive} button group switches
76 off all checkable (toggle) buttons except the one that has been
77 clicked. By default, a button group is exclusive. The buttons in a
78 button group are usually checkable \l{QPushButton}s, \l{QCheckBox}es
79 (normally for non-exclusive button groups), or \l{QRadioButton}s.
80 If you create an exclusive button group, you should ensure that
81 one of the buttons in the group is initially checked; otherwise,
82 the group will initially be in a state where no buttons are
83 checked.
84
85 A button can be added to the group with addButton() and removed
86 with removeButton(). If the group is exclusive, the
87 currently checked button is available with checkedButton(). If a
88 button is clicked, the buttonClicked() signal is emitted; for a
89 checkable button in an exclusive group this means that the button
90 has been checked. The list of buttons in the group is returned by
91 buttons().
92
93 In addition, QButtonGroup can map between integers and buttons.
94 You can assign an integer id to a button with setId(), and
95 retrieve it with id(). The id of the currently checked button is
96 available with checkedId(), and there is an overloaded signal
97 buttonClicked() which emits the id of the button. The id \c {-1}
98 is reserved by QButtonGroup to mean "no such button". The purpose
99 of the mapping mechanism is to simplify the representation of enum
100 values in a user interface.
101
102 \sa QGroupBox, QPushButton, QCheckBox, QRadioButton
103*/
104
105/*!
106 Constructs a new, empty button group with the given \a parent.
107
108 \sa addButton(), setExclusive()
109*/
110QButtonGroup::QButtonGroup(QObject *parent)
111 : QObject(*new QButtonGroupPrivate, parent)
112{
113}
114
115/*!
116 Destroys the button group.
117*/
118QButtonGroup::~QButtonGroup()
119{
120 Q_D(QButtonGroup);
121 for (int i = 0; i < d->buttonList.count(); ++i)
122 d->buttonList.at(i)->d_func()->group = nullptr;
123}
124
125/*!
126 \property QButtonGroup::exclusive
127 \brief whether the button group is exclusive
128
129 If this property is \c true, then only one button in the group can be checked
130 at any given time. The user can click on any button to check it, and that
131 button will replace the existing one as the checked button in the group.
132
133 In an exclusive group, the user cannot uncheck the currently checked button
134 by clicking on it; instead, another button in the group must be clicked
135 to set the new checked button for that group.
136
137 By default, this property is \c true.
138*/
139bool QButtonGroup::exclusive() const
140{
141 Q_D(const QButtonGroup);
142 return d->exclusive;
143}
144
145void QButtonGroup::setExclusive(bool exclusive)
146{
147 Q_D(QButtonGroup);
148 d->exclusive = exclusive;
149}
150
151
152
153/*!
154 \fn void QButtonGroup::buttonClicked(QAbstractButton *button)
155
156 This signal is emitted when the given \a button is clicked. A
157 button is clicked when it is first pressed and then released, when
158 its shortcut key is typed, or when QAbstractButton::click()
159 or QAbstractButton::animateClick() is programmatically called.
160
161
162 \sa checkedButton(), QAbstractButton::clicked()
163*/
164
165/*!
166 \fn void QButtonGroup::buttonClicked(int id)
167 \obsolete
168
169 This signal is emitted when a button with the given \a id is
170 clicked.
171
172 \sa checkedButton(), QAbstractButton::clicked()
173*/
174
175/*!
176 \fn void QButtonGroup::idClicked(int id)
177 \since 5.15
178
179 This signal is emitted when a button with the given \a id is
180 clicked.
181
182 \sa checkedButton(), QAbstractButton::clicked()
183*/
184
185/*!
186 \fn void QButtonGroup::buttonPressed(QAbstractButton *button)
187 \since 4.2
188
189 This signal is emitted when the given \a button is pressed down.
190
191 \sa QAbstractButton::pressed()
192*/
193
194/*!
195 \fn void QButtonGroup::buttonPressed(int id)
196 \since 4.2
197 \obsolete
198
199 This signal is emitted when a button with the given \a id is
200 pressed down.
201
202 \sa QAbstractButton::pressed()
203*/
204
205/*!
206 \fn void QButtonGroup::idPressed(int id)
207 \since 5.15
208
209 This signal is emitted when a button with the given \a id is
210 pressed down.
211
212 \sa QAbstractButton::pressed()
213*/
214
215/*!
216 \fn void QButtonGroup::buttonReleased(QAbstractButton *button)
217 \since 4.2
218
219 This signal is emitted when the given \a button is released.
220
221 \sa QAbstractButton::released()
222*/
223
224/*!
225 \fn void QButtonGroup::buttonReleased(int id)
226 \since 4.2
227 \obsolete
228
229 This signal is emitted when a button with the given \a id is
230 released.
231
232 \sa QAbstractButton::released()
233*/
234
235/*!
236 \fn void QButtonGroup::idReleased(int id)
237 \since 5.15
238
239 This signal is emitted when a button with the given \a id is
240 released.
241
242 \sa QAbstractButton::released()
243*/
244
245/*!
246 \fn void QButtonGroup::buttonToggled(QAbstractButton *button, bool checked)
247 \since 5.2
248
249 This signal is emitted when the given \a button is toggled.
250 \a checked is true if the button is checked, or false if the button is unchecked.
251
252 \sa QAbstractButton::toggled()
253*/
254
255/*!
256 \fn void QButtonGroup::buttonToggled(int id, bool checked)
257 \since 5.2
258 \obsolete
259
260 This signal is emitted when a button with the given \a id is toggled.
261 \a checked is true if the button is checked, or false if the button is unchecked.
262
263 \sa QAbstractButton::toggled()
264*/
265
266/*!
267 \fn void QButtonGroup::idToggled(int id, bool checked)
268 \since 5.15
269
270 This signal is emitted when a button with the given \a id is toggled.
271 \a checked is true if the button is checked, or false if the button is unchecked.
272
273 \sa QAbstractButton::toggled()
274*/
275
276/*!
277 Adds the given \a button to the button group. If \a id is -1,
278 an id will be assigned to the button.
279 Automatically assigned ids are guaranteed to be negative,
280 starting with -2. If you are assigning your own ids, use
281 positive values to avoid conflicts.
282
283 \sa removeButton(), buttons()
284*/
285void QButtonGroup::addButton(QAbstractButton *button, int id)
286{
287 Q_D(QButtonGroup);
288 if (QButtonGroup *previous = button->d_func()->group)
289 previous->removeButton(button);
290 button->d_func()->group = this;
291 d->buttonList.append(t: button);
292 if (id == -1) {
293 const QHash<QAbstractButton*, int>::const_iterator it
294 = std::min_element(first: d->mapping.cbegin(), last: d->mapping.cend());
295 if (it == d->mapping.cend())
296 d->mapping[button] = -2;
297 else
298 d->mapping[button] = *it - 1;
299 } else {
300 d->mapping[button] = id;
301 }
302
303 if (d->exclusive && button->isChecked())
304 button->d_func()->notifyChecked();
305}
306
307/*!
308 Removes the given \a button from the button group.
309
310 \sa addButton(), buttons()
311*/
312void QButtonGroup::removeButton(QAbstractButton *button)
313{
314 Q_D(QButtonGroup);
315 if (d->checkedButton == button) {
316 d->detectCheckedButton();
317 }
318 if (button->d_func()->group == this) {
319 button->d_func()->group = nullptr;
320 d->buttonList.removeAll(t: button);
321 d->mapping.remove(akey: button);
322 }
323}
324
325/*!
326 Returns the button group's list of buttons. This may be empty.
327
328 \sa addButton(), removeButton()
329*/
330QList<QAbstractButton*> QButtonGroup::buttons() const
331{
332 Q_D(const QButtonGroup);
333 return d->buttonList;
334}
335
336/*!
337 Returns the button group's checked button, or \nullptr if no
338 buttons are checked.
339
340 \sa buttonClicked()
341*/
342QAbstractButton *QButtonGroup::checkedButton() const
343{
344 Q_D(const QButtonGroup);
345 return d->checkedButton;
346}
347
348/*!
349 \since 4.1
350
351 Returns the button with the specified \a id, or \nullptr if no
352 such button exists.
353*/
354QAbstractButton *QButtonGroup::button(int id) const
355{
356 Q_D(const QButtonGroup);
357 return d->mapping.key(avalue: id);
358}
359
360/*!
361 \since 4.1
362
363 Sets the \a id for the specified \a button. Note that \a id cannot
364 be -1.
365
366 \sa id()
367*/
368void QButtonGroup::setId(QAbstractButton *button, int id)
369{
370 Q_D(QButtonGroup);
371 if (button && id != -1)
372 d->mapping[button] = id;
373}
374
375/*!
376 \since 4.1
377
378 Returns the id for the specified \a button, or -1 if no such button
379 exists.
380
381
382 \sa setId()
383*/
384int QButtonGroup::id(QAbstractButton *button) const
385{
386 Q_D(const QButtonGroup);
387 return d->mapping.value(akey: button, adefaultValue: -1);
388}
389
390/*!
391 \since 4.1
392
393 Returns the id of the checkedButton(), or -1 if no button is checked.
394
395 \sa setId()
396*/
397int QButtonGroup::checkedId() const
398{
399 Q_D(const QButtonGroup);
400 return d->mapping.value(akey: d->checkedButton, adefaultValue: -1);
401}
402
403QT_END_NAMESPACE
404
405#include "moc_qbuttongroup.cpp"
406

source code of qtbase/src/widgets/widgets/qbuttongroup.cpp