File indexing completed on 2024-05-05 05:53:55

0001 /*
0002     SPDX-FileCopyrightText: 2019 Mariusz Glebocki <mglb@arccos-1.net>
0003 
0004     Based on KConfigDialog and KConfigDialogManager from KConfigWidgets
0005 
0006     SPDX-FileCopyrightText: 2003 Benjamin C Meyer (ben+kdelibs at meyerhome dot net)
0007     SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org>
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 
0012 // Own
0013 #include "ConfigDialogButtonGroupManager.h"
0014 
0015 // Qt
0016 #include <QAbstractButton>
0017 #include <QButtonGroup>
0018 #include <QString>
0019 #include <QTimer>
0020 
0021 using namespace Konsole;
0022 
0023 // const QString ConfigDialogButtonGroupManager::ManagedNamePrefix;
0024 const QString ConfigDialogButtonGroupManager::ManagedNamePrefix = QStringLiteral("kcfg_");
0025 
0026 ConfigDialogButtonGroupManager::ConfigDialogButtonGroupManager(QObject *parent, KCoreConfigSkeleton *config)
0027     : QObject(parent)
0028     , _config(config)
0029 {
0030     Q_ASSERT(config);
0031     connect(_config, &KCoreConfigSkeleton::configChanged, this, &ConfigDialogButtonGroupManager::updateWidgets);
0032 }
0033 
0034 void ConfigDialogButtonGroupManager::addChildren(const QObject *parentObj)
0035 {
0036     const auto allButtonGroups = parentObj->findChildren<QButtonGroup *>();
0037     for (const auto *buttonGroup : allButtonGroups) {
0038         if (buttonGroup->objectName().startsWith(ManagedNamePrefix)) {
0039             add(buttonGroup);
0040         }
0041     }
0042 }
0043 
0044 void ConfigDialogButtonGroupManager::add(const QButtonGroup *obj)
0045 {
0046     Q_ASSERT(obj->exclusive());
0047     connect(obj, &QButtonGroup::buttonToggled, this, &ConfigDialogButtonGroupManager::setButtonState, Qt::UniqueConnection);
0048     _groups.append(obj);
0049 }
0050 
0051 bool ConfigDialogButtonGroupManager::hasChanged() const
0052 {
0053     for (const QButtonGroup *group : std::as_const(_groups)) {
0054         if (group->checkedButton() == nullptr) {
0055             continue;
0056         }
0057         int value = buttonToEnumValue(group->checkedButton());
0058         const auto *enumItem = groupToConfigItemEnum(group);
0059 
0060         if (enumItem != nullptr && !enumItem->isEqual(value)) {
0061             return true;
0062         }
0063     }
0064     return false;
0065 }
0066 
0067 bool ConfigDialogButtonGroupManager::isDefault() const
0068 {
0069     bool useDefaults = _config->useDefaults(true);
0070     bool result = !hasChanged();
0071     _config->useDefaults(useDefaults);
0072     return result;
0073 }
0074 
0075 void ConfigDialogButtonGroupManager::updateWidgets()
0076 {
0077     bool prevSignalsBlocked = signalsBlocked();
0078     bool changed = false;
0079     blockSignals(true);
0080     for (const QButtonGroup *group : std::as_const(_groups)) {
0081         auto *enumItem = groupToConfigItemEnum(group);
0082         if (enumItem == nullptr) {
0083             continue;
0084         }
0085 
0086         int value = enumItem->value();
0087         const QString &valueName = enumItem->choices().at(value).name;
0088         QAbstractButton *currentButton = nullptr;
0089         for (auto &button : group->buttons()) {
0090             if (button->objectName() == valueName) {
0091                 currentButton = button;
0092                 break;
0093             }
0094         }
0095         if (currentButton == nullptr) {
0096             return;
0097         }
0098         currentButton->setChecked(true);
0099         changed = true;
0100     }
0101     blockSignals(prevSignalsBlocked);
0102     if (changed) {
0103         QTimer::singleShot(0, this, &ConfigDialogButtonGroupManager::widgetModified);
0104     }
0105 }
0106 
0107 void ConfigDialogButtonGroupManager::updateWidgetsDefault()
0108 {
0109     bool useDefaults = _config->useDefaults(true);
0110     updateWidgets();
0111     _config->useDefaults(useDefaults);
0112 }
0113 
0114 void ConfigDialogButtonGroupManager::updateSettings()
0115 {
0116     bool updateConfig = false;
0117     for (const QButtonGroup *group : std::as_const(_groups)) {
0118         auto *enumItem = groupToConfigItemEnum(group);
0119         if (enumItem == nullptr) {
0120             continue;
0121         }
0122         const auto *currentButton = group->checkedButton();
0123         if (currentButton == nullptr) {
0124             continue;
0125         }
0126         const int value = buttonToEnumValue(currentButton);
0127         if (value < 0) {
0128             continue;
0129         }
0130 
0131         if (!enumItem->isEqual(value)) {
0132             enumItem->setValue(value);
0133             updateConfig = true;
0134         }
0135     }
0136     if (updateConfig) {
0137         _config->save();
0138         Q_EMIT settingsChanged();
0139     }
0140 }
0141 
0142 void ConfigDialogButtonGroupManager::setButtonState(QAbstractButton *button, bool checked)
0143 {
0144     Q_ASSERT(button->group());
0145     if (!checked) {
0146         // Both deselected and selected buttons trigger this slot, ignore the deselected one
0147         return;
0148     }
0149     auto *enumItem = groupToConfigItemEnum(button->group());
0150     if (enumItem == nullptr) {
0151         return;
0152     }
0153 
0154     int value = buttonToEnumValue(button);
0155     if (value < 0) {
0156         return;
0157     }
0158 
0159     Q_EMIT settingsChanged();
0160 }
0161 
0162 // Returns configuration item associated with the group
0163 KCoreConfigSkeleton::ItemEnum *ConfigDialogButtonGroupManager::groupToConfigItemEnum(const QButtonGroup *group) const
0164 {
0165     Q_ASSERT(group);
0166     const QString key = group->objectName().mid(ManagedNamePrefix.length());
0167     auto *item = _config->findItem(key);
0168     if (item == nullptr) {
0169         return nullptr;
0170     }
0171     auto *enumItem = dynamic_cast<KCoreConfigSkeleton::ItemEnum *>(item);
0172     if (enumItem == nullptr) {
0173         return nullptr;
0174     }
0175     return enumItem;
0176 }
0177 
0178 // Returns a value the button represents in its group
0179 int ConfigDialogButtonGroupManager::buttonToEnumValue(const QAbstractButton *button) const
0180 {
0181     Q_ASSERT(button);
0182     Q_ASSERT(button->group());
0183 
0184     if (_buttonValues.contains(button)) {
0185         return _buttonValues[button];
0186     }
0187 
0188     const auto *enumItem = groupToConfigItemEnum(button->group());
0189     if (enumItem == nullptr) {
0190         return -1;
0191     }
0192     const auto &choices = enumItem->choices();
0193 
0194     const QString buttonName = button->objectName();
0195     int value = -1;
0196     for (int i = 0; i < choices.size(); ++i) {
0197         if (buttonName == choices.at(i).name) {
0198             value = i;
0199             break;
0200         }
0201     }
0202     _buttonValues[button] = value;
0203     return value;
0204 }
0205 
0206 #include "moc_ConfigDialogButtonGroupManager.cpp"