src/qt3support/widgets/q3buttongroup.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 Qt3Support 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 "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 
       
    50 QT_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 
       
   119 Q3ButtonGroup::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 
       
   132 Q3ButtonGroup::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 
       
   148 Q3ButtonGroup::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 
       
   164 Q3ButtonGroup::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 
       
   176 void Q3ButtonGroup::init()
       
   177 {
       
   178     group.setExclusive(false);
       
   179     radio_excl = true;
       
   180 }
       
   181 
       
   182 /*! Destructor. */
       
   183 
       
   184 Q3ButtonGroup::~Q3ButtonGroup()
       
   185 {
       
   186 }
       
   187 
       
   188 bool Q3ButtonGroup::isExclusive() const
       
   189 {
       
   190     return group.exclusive();
       
   191 }
       
   192 
       
   193 void 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 
       
   220 int Q3ButtonGroup::insert(QAbstractButton *button, int id)
       
   221 {
       
   222     remove_helper(button);
       
   223     return insert_helper(button, id);
       
   224 }
       
   225 
       
   226 int 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 */
       
   247 int 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 
       
   259 void Q3ButtonGroup::remove(QAbstractButton *button)
       
   260 {
       
   261     fixChildren();
       
   262     remove_helper(button);
       
   263 }
       
   264 
       
   265 void 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 
       
   285 QAbstractButton *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 
       
   329 void 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 
       
   344 void 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 
       
   359 void 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 */
       
   371 void Q3ButtonGroup::buttonDestroyed()
       
   372 {
       
   373     int id = buttonIds.key(static_cast<QAbstractButton *>(sender()), -1);
       
   374     if (id != -1)
       
   375         buttonIds.remove(id);
       
   376 }
       
   377 
       
   378 void Q3ButtonGroup::setButton(int id)
       
   379 {
       
   380     QAbstractButton *b = find(id);
       
   381     if (b)
       
   382         b->setOn(true);
       
   383 }
       
   384 
       
   385 void 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 
       
   398 QAbstractButton *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 
       
   427 int 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 
       
   440 int 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 */
       
   456 bool 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 
       
   477 void 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 
       
   565 QT_END_NAMESPACE