source: trunk/src/qt3support/widgets/q3buttongroup.cpp@ 1023

Last change on this file since 1023 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: 15.6 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 Qt3Support 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 "q3buttongroup.h"
43#include "qabstractbutton.h"
44#include "qmap.h"
45#include "qapplication.h"
46#include "qradiobutton.h"
47#include "qevent.h"
48#include "qset.h"
49
50QT_BEGIN_NAMESPACE
51
52/*!
53 \class Q3ButtonGroup
54 \brief The Q3ButtonGroup widget organizes QAbstractButton widgets in a group.
55
56 \compat
57
58 A button group widget makes it easier to deal with groups of
59 buttons. Each button in a button group has a unique identifier.
60 The button group emits a clicked() signal with this identifier
61 when a button in the group is clicked. This makes a button group
62 particularly useful when you have several similar buttons and want
63 to connect all their clicked() signals to a single slot.
64
65 An \link setExclusive() exclusive\endlink button group switches
66 off all toggle buttons except the one that was clicked. A button
67 group is, by default, non-exclusive. Note that all radio buttons
68 that are inserted into a button group are mutually exclusive even
69 if the button group is non-exclusive. (See
70 setRadioButtonExclusive().)
71
72 There are two ways of using a button group:
73 \list
74 \i The button group is the parent widget of a number of buttons,
75 i.e. the button group is the parent argument in the button
76 constructor. The buttons are assigned identifiers 0, 1, 2, etc.,
77 in the order they are created. A Q3ButtonGroup can display a frame
78 and a title because it inherits Q3GroupBox.
79 \i The button group is an invisible widget and the contained
80 buttons have some other parent widget. In this usage, each button
81 must be manually inserted, using insert(), into the button group
82 and given an identifier.
83 \endlist
84
85 A button can be removed from the group with remove(). A pointer to
86 a button with a given id can be obtained using find(). The id of a
87 button is available using id(). A button can be set \e on with
88 setButton(). The number of buttons in the group is returned by
89 count().
90
91 \sa QPushButton, QCheckBox, QRadioButton
92*/
93
94/*!
95 \property Q3ButtonGroup::exclusive
96 \brief whether the button group is exclusive
97
98 If this property is true, then the buttons in the group are
99 toggled, and to untoggle a button you must click on another button
100 in the group. The default value is false.
101*/
102
103/*!
104 \property Q3ButtonGroup::radioButtonExclusive
105 \brief whether the radio buttons in the group are exclusive
106
107 If this property is true (the default), the \link QRadioButton
108 radio buttons\endlink in the group are treated exclusively.
109*/
110
111
112/*!
113 Constructs a button group with no title.
114
115 The \a parent and \a name arguments are passed to the QWidget
116 constructor.
117*/
118
119Q3ButtonGroup::Q3ButtonGroup(QWidget *parent, const char *name)
120 : Q3GroupBox(parent, name)
121{
122 init();
123}
124
125/*!
126 Constructs a button group with the title \a title.
127
128 The \a parent and \a name arguments are passed to the QWidget
129 constructor.
130*/
131
132Q3ButtonGroup::Q3ButtonGroup(const QString &title, QWidget *parent,
133 const char *name)
134 : Q3GroupBox(title, parent, name)
135{
136 init();
137}
138
139/*!
140 Constructs a button group with no title. Child widgets will be
141 arranged in \a strips rows or columns (depending on \a
142 orientation).
143
144 The \a parent and \a name arguments are passed to the QWidget
145 constructor.
146*/
147
148Q3ButtonGroup::Q3ButtonGroup(int strips, Qt::Orientation orientation,
149 QWidget *parent, const char *name)
150 : Q3GroupBox(strips, orientation, parent, name)
151{
152 init();
153}
154
155/*!
156 Constructs a button group with title \a title. Child widgets will
157 be arranged in \a strips rows or columns (depending on \a
158 orientation).
159
160 The \a parent and \a name arguments are passed to the QWidget
161 constructor.
162*/
163
164Q3ButtonGroup::Q3ButtonGroup(int strips, Qt::Orientation orientation,
165 const QString &title, QWidget *parent,
166 const char *name)
167 : Q3GroupBox(strips, orientation, title, parent, name)
168{
169 init();
170}
171
172/*!
173 Initializes the button group.
174*/
175
176void Q3ButtonGroup::init()
177{
178 group.setExclusive(false);
179 radio_excl = true;
180}
181
182/*! Destructor. */
183
184Q3ButtonGroup::~Q3ButtonGroup()
185{
186}
187
188bool Q3ButtonGroup::isExclusive() const
189{
190 return group.exclusive();
191}
192
193void Q3ButtonGroup::setExclusive(bool enable)
194{
195 group.setExclusive(enable);
196}
197
198
199/*!
200 Inserts the \a button with the identifier \a id into the button
201 group. Returns the button identifier.
202
203 Buttons are normally inserted into a button group automatically by
204 passing the button group as the parent when the button is
205 constructed. So it is not necessary to manually insert buttons
206 that have this button group as their parent widget. An exception
207 is when you want custom identifiers instead of the default 0, 1,
208 2, etc., or if you want the buttons to have some other parent.
209
210 The button is assigned the identifier \a id or an automatically
211 generated identifier. It works as follows: If \a id >= 0, this
212 identifier is assigned. If \a id == -1 (default), the identifier
213 is equal to the number of buttons in the group. If \a id is any
214 other negative integer, for instance -2, a unique identifier
215 (negative integer \<= -2) is generated. No button has an id of -1.
216
217 \sa find(), remove(), setExclusive()
218*/
219
220int Q3ButtonGroup::insert(QAbstractButton *button, int id)
221{
222 remove_helper(button);
223 return insert_helper(button, id);
224}
225
226int Q3ButtonGroup::insert_helper(QAbstractButton *button, int id)
227{
228 if (isExclusive() || !qobject_cast<QRadioButton*>(button))
229 group.addButton(button);
230
231 static int seq_no = -2;
232 if (id < -1)
233 id = seq_no--;
234 else if (id == -1)
235 id = buttonIds.count();
236 buttonIds.insert(id, button);
237 connect(button, SIGNAL(pressed()) , SLOT(buttonPressed()));
238 connect(button, SIGNAL(released()), SLOT(buttonReleased()));
239 connect(button, SIGNAL(clicked()) , SLOT(buttonClicked()));
240 connect(button, SIGNAL(destroyed()) , SLOT(buttonDestroyed()));
241 return id;
242}
243
244/*!
245 Returns the number of buttons in the group.
246*/
247int Q3ButtonGroup::count() const
248{
249 fixChildren();
250 return buttonIds.count();
251}
252
253/*!
254 Removes the \a button from the button group.
255
256 \sa insert()
257*/
258
259void Q3ButtonGroup::remove(QAbstractButton *button)
260{
261 fixChildren();
262 remove_helper(button);
263}
264
265void Q3ButtonGroup::remove_helper(QAbstractButton *button)
266{
267 QMap<int, QAbstractButton*>::Iterator it = buttonIds.begin();
268 while (it != buttonIds.end()) {
269 if (it.value() == button) {
270 buttonIds.erase(it);
271 button->disconnect(this);
272 group.removeButton(button);
273 break;
274 }
275 ++it;
276 }
277}
278
279
280/*!
281 Returns the button with the specified identifier \a id, or 0 if
282 the button was not found.
283*/
284
285QAbstractButton *Q3ButtonGroup::find(int id) const
286{
287 fixChildren();
288 return buttonIds.value(id);
289}
290
291
292/*!
293 \fn void Q3ButtonGroup::pressed(int id)
294
295 This signal is emitted when a button in the group is \link
296 QAbstractButton::pressed() pressed\endlink. The \a id argument is the
297 button's identifier.
298
299 \sa insert()
300*/
301
302/*!
303 \fn void Q3ButtonGroup::released(int id)
304
305 This signal is emitted when a button in the group is \link
306 QAbstractButton::released() released\endlink. The \a id argument is the
307 button's identifier.
308
309 \sa insert()
310*/
311
312/*!
313 \fn void Q3ButtonGroup::clicked(int id)
314
315 This signal is emitted when a button in the group is \link
316 QAbstractButton::clicked() clicked\endlink. The \a id argument is the
317 button's identifier.
318
319 \sa insert()
320*/
321
322
323/*!
324 \internal
325 This slot is activated when one of the buttons in the group emits the
326 QAbstractButton::pressed() signal.
327*/
328
329void Q3ButtonGroup::buttonPressed()
330{
331 QAbstractButton *senderButton = qobject_cast<QAbstractButton *>(sender());
332 Q_ASSERT(senderButton);
333 int senderId = id(senderButton);
334 if (senderId != -1)
335 emit pressed(senderId);
336}
337
338/*!
339 \internal
340 This slot is activated when one of the buttons in the group emits the
341 QAbstractButton::released() signal.
342*/
343
344void Q3ButtonGroup::buttonReleased()
345{
346 QAbstractButton *senderButton = qobject_cast<QAbstractButton *>(sender());
347 Q_ASSERT(senderButton);
348 int senderId = id(senderButton);
349 if (senderId != -1)
350 emit released(senderId);
351}
352
353/*!
354 \internal
355 This slot is activated when one of the buttons in the group emits the
356 QAbstractButton::clicked() signal.
357*/
358
359void Q3ButtonGroup::buttonClicked()
360{
361 QAbstractButton *senderButton = qobject_cast<QAbstractButton *>(sender());
362 Q_ASSERT(senderButton);
363 int senderId = id(senderButton);
364 if (senderId != -1)
365 emit clicked(senderId);
366}
367
368/*!
369 \internal
370*/
371void Q3ButtonGroup::buttonDestroyed()
372{
373 int id = buttonIds.key(static_cast<QAbstractButton *>(sender()), -1);
374 if (id != -1)
375 buttonIds.remove(id);
376}
377
378void Q3ButtonGroup::setButton(int id)
379{
380 QAbstractButton *b = find(id);
381 if (b)
382 b->setOn(true);
383}
384
385void Q3ButtonGroup::setRadioButtonExclusive(bool on)
386{
387 radio_excl = on;
388}
389
390
391/*!
392 Returns the selected toggle button if exactly one is selected;
393 otherwise returns 0.
394
395 \sa selectedId()
396*/
397
398QAbstractButton *Q3ButtonGroup::selected() const
399{
400 fixChildren();
401 QAbstractButton *candidate = 0;
402 QMap<int, QAbstractButton*>::ConstIterator it = buttonIds.constBegin();
403 while (it != buttonIds.constEnd()) {
404 if (it.value()->isCheckable() && it.value()->isChecked()) {
405 if (candidate)
406 return 0;
407 candidate = it.value();
408 }
409 ++it;
410 }
411 return candidate;
412}
413
414/*!
415 \property Q3ButtonGroup::selectedId
416 \brief The id of the selected toggle button.
417
418 If no toggle button is selected, id() returns -1.
419
420 If setButton() is called on an exclusive group, the button with
421 the given id will be set to on and all the others will be set to
422 off.
423
424 \sa selected()
425*/
426
427int Q3ButtonGroup::selectedId() const
428{
429 return id(selected());
430}
431
432
433/*!
434 Returns the id of \a button, or -1 if \a button is not a member of
435 this group.
436
437 \sa selectedId()
438*/
439
440int Q3ButtonGroup::id(QAbstractButton *button) const
441{
442 fixChildren();
443 QMap<int, QAbstractButton*>::ConstIterator it = buttonIds.constBegin();
444 while (it != buttonIds.constEnd()) {
445 if (it.value() == button)
446 return it.key();
447 ++it;
448 }
449 return -1;
450}
451
452
453/*!
454 \reimp
455*/
456bool Q3ButtonGroup::event(QEvent * e)
457{
458 if (e->type() == QEvent::ChildInserted) {
459 QChildEvent * ce = (QChildEvent *) e;
460 if (QAbstractButton *button = qobject_cast<QAbstractButton*>(ce->child())) {
461 button->setAutoExclusive(false);
462 if (group.exclusive() || qobject_cast<QRadioButton*>(button)) {
463 button->setAutoExclusive(true);
464 QMap<int, QAbstractButton*>::ConstIterator it = buttonIds.constBegin();
465 while (it != buttonIds.constEnd()) {
466 if (it.value() == button)
467 return Q3GroupBox::event(e);
468 ++it;
469 }
470 }
471 insert(button, id(button));
472 }
473 }
474 return Q3GroupBox::event(e);
475}
476
477void Q3ButtonGroup::fixChildren() const
478{
479 if (children().count() == buttonIds.count())
480 return; // small optimization, all our children have ids.
481
482 QSet<QAbstractButton*> set;
483 for (QMap<int, QAbstractButton*>::ConstIterator it = buttonIds.constBegin();
484 it != buttonIds.constEnd(); ++it)
485 set.insert(*it);
486 // Use children() instead of qFindChildren<QAbstractButton*> because the search
487 // should not be recursive.We match with the behavior of Qt3
488 const QObjectList childList = children();
489 Q_FOREACH(QObject* obj, childList) {
490 QAbstractButton *button = qobject_cast<QAbstractButton*>(obj);
491 if ( button && !set.contains(button))
492 const_cast<Q3ButtonGroup*>(this)->insert_helper(button);
493 }
494}
495
496
497/*!
498 \class Q3HButtonGroup
499 \brief The Q3HButtonGroup widget organizes button widgets in a
500 group with one horizontal row.
501
502 \compat
503
504 Q3HButtonGroup is a convenience class that offers a thin layer on
505 top of Q3ButtonGroup. From a layout point of view it is effectively
506 a Q3HBoxWidget that offers a frame with a title and is specifically
507 designed for buttons. From a functionality point of view it is a
508 Q3ButtonGroup.
509
510 \sa Q3VButtonGroup
511*/
512
513/*!
514 \fn Q3HButtonGroup::Q3HButtonGroup(QWidget *parent, const char *name)
515
516 Constructs a horizontal button group with no title.
517
518 The \a parent and \a name arguments are passed to the QWidget
519 constructor.
520*/
521
522/*!
523 \fn Q3HButtonGroup::Q3HButtonGroup(const QString &title, QWidget *parent,
524 const char *name)
525
526 Constructs a horizontal button group with the title \a title.
527
528 The \a parent and \a name arguments are passed to the QWidget
529 constructor.
530*/
531
532/*!
533 \class Q3VButtonGroup
534 \brief The Q3VButtonGroup widget organizes button widgets in a
535 vertical column.
536
537 \compat
538
539 Q3VButtonGroup is a convenience class that offers a thin layer on top
540 of Q3ButtonGroup. Think of it as a QVBoxWidget that offers a frame with a
541 title and is specifically designed for buttons.
542
543 \sa Q3HButtonGroup
544*/
545
546/*!
547 \fn Q3VButtonGroup::Q3VButtonGroup(QWidget *parent, const char *name)
548
549 Constructs a vertical button group with no title.
550
551 The \a parent and \a name arguments are passed on to the QWidget
552 constructor.
553*/
554
555/*!
556 \fn Q3VButtonGroup::Q3VButtonGroup(const QString &title, QWidget *parent,
557 const char *name)
558
559 Constructs a vertical button group with the title \a title.
560
561 The \a parent and \a name arguments are passed on to the QWidget
562 constructor.
563*/
564
565QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.