File indexing completed on 2024-04-14 15:49:41

0001 // SPDX-FileCopyrightText: 2006 Pino Toscano <toscano.pino@tiscali.it>
0002 // SPDX-FileCopyrightText: 2020 Simon Persson <simon.persson@mykolab.com>
0003 //
0004 // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 
0006 #include "kbuttongroup.h"
0007 
0008 #include <QChildEvent>
0009 #include <QHash>
0010 #include <QAbstractButton>
0011 #include <QSignalMapper>
0012 
0013 class KButtonGroup::Private
0014 {
0015 public:
0016     explicit Private(KButtonGroup *q) :
0017         q(q),
0018         currentId(-1),
0019         nextId(0),
0020         wantToBeId(-1)
0021     {
0022         connect(&clickedMapper, SIGNAL(mapped(int)), q, SLOT(slotClicked(int)));
0023         connect(&pressedMapper, SIGNAL(mapped(int)), q, SIGNAL(pressed(int)));
0024         connect(&releasedMapper, SIGNAL(mapped(int)), q, SIGNAL(released(int)));
0025     }
0026 
0027     void slotClicked(int id);
0028 
0029     KButtonGroup *q;
0030     QSignalMapper clickedMapper;
0031     QSignalMapper pressedMapper;
0032     QSignalMapper releasedMapper;
0033 
0034     QHash<QObject *, int> btnMap;
0035     int currentId;
0036     int nextId;
0037     int wantToBeId;
0038 };
0039 
0040 KButtonGroup::KButtonGroup(QWidget *parent) : QGroupBox(parent), d(new Private(this))
0041 {
0042 }
0043 
0044 KButtonGroup::~KButtonGroup()
0045 {
0046     delete d;
0047 }
0048 
0049 void KButtonGroup::setSelected(int id)
0050 {
0051     if (!testAttribute(Qt::WA_WState_Polished)) {
0052         d->wantToBeId = id;
0053         ensurePolished();
0054         return;
0055     }
0056 
0057     QHash<QObject *, int>::Iterator it = d->btnMap.begin();
0058     QHash<QObject *, int>::Iterator itEnd = d->btnMap.end();
0059     QAbstractButton *button = nullptr;
0060 
0061     for (; it != itEnd; ++it) {
0062         if ((it.value() == id) && (button = qobject_cast<QAbstractButton *>(it.key()))) {
0063             button->setChecked(true);
0064             d->currentId = id;
0065             emit changed(id);
0066             d->wantToBeId = -1;
0067             return;
0068         }
0069     }
0070     // button not found, it might still show up though, eg. because of premature polishing above
0071     d->wantToBeId = id;
0072 }
0073 
0074 int KButtonGroup::selected() const
0075 {
0076     return d->currentId;
0077 }
0078 
0079 void KButtonGroup::childEvent(QChildEvent *event)
0080 {
0081     if (event->polished()) {
0082         auto button = qobject_cast<QAbstractButton *>(event->child());
0083         if (!d->btnMap.contains(event->child()) && button) {
0084             connect(button, SIGNAL(clicked()), &d->clickedMapper, SLOT(map()));
0085             d->clickedMapper.setMapping(button, d->nextId);
0086 
0087             connect(button, SIGNAL(pressed()), &d->pressedMapper, SLOT(map()));
0088             d->pressedMapper.setMapping(button, d->nextId);
0089 
0090             connect(button, SIGNAL(released()), &d->releasedMapper, SLOT(map()));
0091             d->releasedMapper.setMapping(button, d->nextId);
0092 
0093             d->btnMap[button] = d->nextId;
0094 
0095             if (d->nextId == d->wantToBeId) {
0096                 d->currentId = d->wantToBeId;
0097                 d->wantToBeId = -1;
0098                 button->setChecked(true);
0099                 emit changed(d->currentId);
0100             }
0101 
0102             ++d->nextId;
0103         }
0104     } else if (event->removed()) {
0105         QObject *obj = event->child();
0106         QHash<QObject *, int>::ConstIterator it = d->btnMap.constFind(obj);
0107 
0108         if (it != d->btnMap.constEnd()) {
0109             d->clickedMapper.removeMappings(obj);
0110             d->pressedMapper.removeMappings(obj);
0111             d->releasedMapper.removeMappings(obj);
0112 
0113             if (it.value() == d->currentId) {
0114                 d->currentId = -1;
0115             }
0116 
0117             d->btnMap.remove(obj);
0118         }
0119     }
0120 
0121     // be transparent
0122     QGroupBox::childEvent(event);
0123 }
0124 
0125 int KButtonGroup::id(QAbstractButton *button) const
0126 {
0127     QHash<QObject *, int>::ConstIterator it = d->btnMap.constFind(button);
0128 
0129     if (it != d->btnMap.constEnd()) {
0130         return it.value();
0131     }
0132 
0133     return -1;
0134 }
0135 
0136 void KButtonGroup::Private::slotClicked(int id)
0137 {
0138     currentId = id;
0139     emit q->clicked(id);
0140     emit q->changed(id);
0141 }
0142 
0143 #include "moc_kbuttongroup.cpp"
0144 
0145