File indexing completed on 2024-04-14 14:20:16

0001 /*
0002     This file is part of the KDE Libraries
0003 
0004     Copyright (C) 2006 Pino Toscano <toscano.pino@tiscali.it>
0005 
0006     This library is free software; you can redistribute it and/or
0007     modify it under the terms of the GNU Library General Public
0008     License as published by the Free Software Foundation; either
0009     version 2 of the License, or (at your option) any later version.
0010 
0011     This library is distributed in the hope that it will be useful,
0012     but WITHOUT ANY WARRANTY; without even the implied warranty of
0013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014     Library General Public License for more details.
0015 
0016     You should have received a copy of the GNU Library General Public License
0017     along with this library; see the file COPYING.LIB. If not, write to
0018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019     Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #include "kbuttongroup.h"
0023 
0024 #include <QChildEvent>
0025 #include <QHash>
0026 #include <QAbstractButton>
0027 #include <QSignalMapper>
0028 
0029 class Q_DECL_HIDDEN KButtonGroup::Private
0030 {
0031 public:
0032     Private(KButtonGroup *q) :
0033         q(q),
0034         clickedMapper(),
0035         pressedMapper(),
0036         releasedMapper(),
0037         currentId(-1),
0038         nextId(0),
0039         wantToBeId(-1)
0040     {
0041         connect(&clickedMapper, SIGNAL(mapped(int)), q, SLOT(slotClicked(int)));
0042         connect(&pressedMapper, SIGNAL(mapped(int)), q, SIGNAL(pressed(int)));
0043         connect(&releasedMapper, SIGNAL(mapped(int)), q, SIGNAL(released(int)));
0044     }
0045 
0046     void slotClicked(int id);
0047 
0048     KButtonGroup *q;
0049     QSignalMapper clickedMapper;
0050     QSignalMapper pressedMapper;
0051     QSignalMapper releasedMapper;
0052 
0053     QHash<QObject *, int> btnMap;
0054     int currentId;
0055     int nextId;
0056     int wantToBeId;
0057 };
0058 
0059 KButtonGroup::KButtonGroup(QWidget *parent) : QGroupBox(parent), d(new Private(this))
0060 {
0061 }
0062 
0063 KButtonGroup::~KButtonGroup()
0064 {
0065     delete d;
0066 }
0067 
0068 void KButtonGroup::setSelected(int id)
0069 {
0070     if (!testAttribute(Qt::WA_WState_Polished)) {
0071         d->wantToBeId = id;
0072         ensurePolished();
0073         return;
0074     }
0075 
0076     QHash<QObject *, int>::Iterator it = d->btnMap.begin();
0077     QHash<QObject *, int>::Iterator itEnd = d->btnMap.end();
0078     QAbstractButton *button = nullptr;
0079 
0080     for (; it != itEnd; ++it) {
0081         if ((it.value() == id) && (button = qobject_cast<QAbstractButton *>(it.key()))) {
0082             button->setChecked(true);
0083             d->currentId = id;
0084             emit changed(id);
0085             d->wantToBeId = -1;
0086             return;
0087         }
0088     }
0089     // button not found, it might still show up though, eg. because of premature polishing above
0090     d->wantToBeId = id;
0091 }
0092 
0093 int KButtonGroup::selected() const
0094 {
0095     return d->currentId;
0096 }
0097 
0098 void KButtonGroup::childEvent(QChildEvent *event)
0099 {
0100     if (event->polished()) {
0101         QAbstractButton *button = qobject_cast<QAbstractButton *>(event->child());
0102         if (!d->btnMap.contains(event->child()) && button) {
0103             connect(button, SIGNAL(clicked()), &d->clickedMapper, SLOT(map()));
0104             d->clickedMapper.setMapping(button, d->nextId);
0105 
0106             connect(button, SIGNAL(pressed()), &d->pressedMapper, SLOT(map()));
0107             d->pressedMapper.setMapping(button, d->nextId);
0108 
0109             connect(button, SIGNAL(released()), &d->releasedMapper, SLOT(map()));
0110             d->releasedMapper.setMapping(button, d->nextId);
0111 
0112             d->btnMap[button] = d->nextId;
0113 
0114             if (d->nextId == d->wantToBeId) {
0115                 d->currentId = d->wantToBeId;
0116                 d->wantToBeId = -1;
0117                 button->setChecked(true);
0118                 emit changed(d->currentId);
0119             }
0120 
0121             ++d->nextId;
0122         }
0123     } else if (event->removed()) {
0124         QObject *obj = event->child();
0125         QHash<QObject *, int>::ConstIterator it = d->btnMap.constFind(obj);
0126 
0127         if (it != d->btnMap.constEnd()) {
0128             d->clickedMapper.removeMappings(obj);
0129             d->pressedMapper.removeMappings(obj);
0130             d->releasedMapper.removeMappings(obj);
0131 
0132             if (it.value() == d->currentId) {
0133                 d->currentId = -1;
0134             }
0135 
0136             d->btnMap.remove(obj);
0137         }
0138     }
0139 
0140     // be transparent
0141     QGroupBox::childEvent(event);
0142 }
0143 
0144 int KButtonGroup::id(QAbstractButton *button) const
0145 {
0146     QHash<QObject *, int>::ConstIterator it = d->btnMap.constFind(button);
0147 
0148     if (it != d->btnMap.constEnd()) {
0149         return it.value();
0150     }
0151 
0152     return -1;
0153 }
0154 
0155 void KButtonGroup::Private::slotClicked(int id)
0156 {
0157     currentId = id;
0158     emit q->clicked(id);
0159     emit q->changed(id);
0160 }
0161 
0162 #include "moc_kbuttongroup.cpp"
0163