diff --git a/src/settings/ConfigurationDialog.cpp b/src/settings/ConfigurationDialog.cpp index c28fecbe..eee7dcf4 100644 --- a/src/settings/ConfigurationDialog.cpp +++ b/src/settings/ConfigurationDialog.cpp @@ -1,165 +1,164 @@ /* Copyright 2019 by Mariusz Glebocki Based on KConfigDialog from KConfigWidgets Copyright (C) 2003 Benjamin C Meyer (ben+kdelibs at meyerhome dot net) Copyright (C) 2003 Waldo Bastian This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // Own #include "ConfigurationDialog.h" // Qt #include #include // KDE #include #include -#include using namespace Konsole; const QString ConfigDialogButtonGroupManager::ManagedNamePrefix = QStringLiteral("kcfg_"); ConfigurationDialog::ConfigurationDialog(QWidget *parent, KCoreConfigSkeleton *config) : KPageDialog(parent) { setWindowTitle(i18nc("@title:window", "Configure")); // Setting this after modifying buttonBox results in initial focus set to buttonBox. setFaceType(KPageDialog::List); buttonBox()->setStandardButtons(QDialogButtonBox::RestoreDefaults | QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel); connect(buttonBox()->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, this, &ConfigurationDialog::updateButtons); connect(buttonBox()->button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked, this, &ConfigurationDialog::updateButtons); _manager = new KConfigDialogManager(this, config); connect(_manager, SIGNAL(settingsChanged()), this, SLOT(settingsChangedSlot())); connect(_manager, SIGNAL(widgetModified()), this, SLOT(updateButtons())); connect(buttonBox()->button(QDialogButtonBox::Ok), &QAbstractButton::clicked, _manager, &KConfigDialogManager::updateSettings); connect(buttonBox()->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, _manager, &KConfigDialogManager::updateSettings); connect(buttonBox()->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked, _manager, &KConfigDialogManager::updateWidgets); connect(buttonBox()->button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked, _manager, &KConfigDialogManager::updateWidgetsDefault); _groupManager = new ConfigDialogButtonGroupManager(this, config); connect(_groupManager, SIGNAL(settingsChanged()), this, SLOT(settingsChangedSlot())); connect(_groupManager, SIGNAL(widgetModified()), this, SLOT(updateButtons())); connect(buttonBox()->button(QDialogButtonBox::Ok), &QAbstractButton::clicked, _groupManager, &ConfigDialogButtonGroupManager::updateSettings); connect(buttonBox()->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, _groupManager, &ConfigDialogButtonGroupManager::updateSettings); connect(buttonBox()->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked, _groupManager, &ConfigDialogButtonGroupManager::updateWidgets); connect(buttonBox()->button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked, _groupManager, &ConfigDialogButtonGroupManager::updateWidgetsDefault); setApplyButtonEnabled(false); } void ConfigurationDialog::addPage(KPageWidgetItem *item, bool manage) { Q_ASSERT(item); Q_ASSERT(item->widget()); KPageDialog::addPage(item); if (manage) { _manager->addWidget(item->widget()); _groupManager->addChildren(item->widget()); } if (_shown && manage) { QPushButton *defaultButton = buttonBox()->button(QDialogButtonBox::RestoreDefaults); if (defaultButton != nullptr) { bool isDefault = defaultButton->isEnabled() && _manager->isDefault(); defaultButton->setEnabled(!isDefault); } } } void ConfigurationDialog::updateButtons() { static bool onlyOnce = false; if (onlyOnce) { return; } onlyOnce = true; bool has_changed = _manager->hasChanged() || _groupManager->hasChanged(); setApplyButtonEnabled(has_changed); bool is_default = _manager->isDefault() && _groupManager->isDefault(); setRestoreDefaultsButtonEnabled(!is_default); emit widgetModified(); onlyOnce = false; } void ConfigurationDialog::settingsChangedSlot() { updateButtons(); emit settingsChanged(); } void ConfigurationDialog::setApplyButtonEnabled(bool enabled) { QPushButton *applyButton = buttonBox()->button(QDialogButtonBox::Apply); if (applyButton != nullptr) { applyButton->setEnabled(enabled); } } void ConfigurationDialog::setRestoreDefaultsButtonEnabled(bool enabled) { QPushButton *restoreDefaultsButton = buttonBox()->button(QDialogButtonBox::RestoreDefaults); if (restoreDefaultsButton != nullptr) { restoreDefaultsButton->setEnabled(enabled); } } void Konsole::ConfigurationDialog::showEvent(QShowEvent *event) { if (!_shown) { _manager->updateWidgets(); _groupManager->updateWidgets(); bool hasChanged = _manager->hasChanged() || _groupManager->hasChanged(); setApplyButtonEnabled(hasChanged); bool isDefault = _manager->isDefault() || _groupManager->isDefault(); setRestoreDefaultsButtonEnabled(!isDefault); _shown = true; } KPageDialog::showEvent(event); } diff --git a/src/settings/ConfigurationDialog.h b/src/settings/ConfigurationDialog.h index 7b5848ed..123c3fed 100644 --- a/src/settings/ConfigurationDialog.h +++ b/src/settings/ConfigurationDialog.h @@ -1,284 +1,282 @@ /* Copyright 2019 by Mariusz Glebocki Based on KConfigDialog and KConfigDialogManager from KConfigWidgets Copyright (C) 2003 Benjamin C Meyer (ben+kdelibs at meyerhome dot net) Copyright (C) 2003 Waldo Bastian This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef CONFIGURATIONDIALOG_H #define CONFIGURATIONDIALOG_H // Qt -#include #include #include #include #include // KDE #include #include // Konsole #include "konsoleprivate_export.h" -class KConfig; -class KCoreConfigSkeleton; +class QWidget; class KConfigDialogManager; namespace Konsole { class ConfigDialogButtonGroupManager; // KConfigDialog-like class, as the original KConfigDialog wraps // all pages in QScrollArea. KConfigDialog, when fixed, should // be source compatible with this class, so simple class replace // should suffice. class KONSOLEPRIVATE_EXPORT ConfigurationDialog: public KPageDialog { Q_OBJECT Q_SIGNALS: void widgetModified(); void settingsChanged(); public: explicit ConfigurationDialog(QWidget *parent, KCoreConfigSkeleton *config); ~ConfigurationDialog() override = default; void addPage(KPageWidgetItem *item, bool manage); protected Q_SLOTS: void updateButtons(); void settingsChangedSlot(); protected: void setApplyButtonEnabled(bool enabled); void setRestoreDefaultsButtonEnabled(bool enabled); void showEvent(QShowEvent *event) override; private: Q_DISABLE_COPY(ConfigurationDialog) KConfigDialogManager *_manager = nullptr; ConfigDialogButtonGroupManager *_groupManager = nullptr; bool _shown = false; }; // KConfigDialogManager-like class for managing QButtonGroups, // which are not supported by KConfigDialogManager yet. When // support will be available in minimum KF5 used by Konsole, // just remove this class and all expressions which refer to it. class ConfigDialogButtonGroupManager: public QObject { Q_OBJECT public: ConfigDialogButtonGroupManager(QObject *parent, KCoreConfigSkeleton *config) : QObject(parent) , _config(config) { Q_ASSERT(config); connect(_config, &KCoreConfigSkeleton::configChanged, this, &ConfigDialogButtonGroupManager::updateWidgets); } void addChildren(const QObject *parentObj) { const auto allButtonGroups = parentObj->findChildren(); for (const auto *buttonGroup: allButtonGroups) { if (buttonGroup->objectName().startsWith(ManagedNamePrefix)) { add(buttonGroup); } } } void add(const QButtonGroup *obj) { Q_ASSERT(obj->exclusive()); connect(obj, QOverload::of(&QButtonGroup::buttonToggled), this, &ConfigDialogButtonGroupManager::setButtonState, Qt::UniqueConnection); _groups.append(obj); } bool hasChanged() const { for(const QButtonGroup *group: qAsConst(_groups)) { int value = buttonToEnumValue(group->checkedButton()); const auto enumItem = groupToConfigItemEnum(group); if(!enumItem->isEqual(value)) { return true; } } return false; } bool isDefault() const { bool useDefaults = _config->useDefaults(true); bool result = !hasChanged(); _config->useDefaults(useDefaults); return result; } Q_SIGNALS: void settingsChanged(); void widgetModified(); public Q_SLOTS: void updateWidgets() { bool prevSignalsBlocked = signalsBlocked(); bool changed = false; blockSignals(true); for(const QButtonGroup *group: qAsConst(_groups)) { auto *enumItem = groupToConfigItemEnum(group); if(enumItem == nullptr) { continue; } int value = enumItem->value(); const QString &valueName = enumItem->choices().at(value).name; QAbstractButton *currentButton = nullptr; for(auto &button: group->buttons()) { if(button->objectName() == valueName) { currentButton = button; break; } } if(currentButton == nullptr) { return; } currentButton->setChecked(true); changed = true; } blockSignals(prevSignalsBlocked); if(changed) { QTimer::singleShot(0, this, &ConfigDialogButtonGroupManager::widgetModified); } } void updateWidgetsDefault() { bool useDefaults = _config->useDefaults(true); updateWidgets(); _config->useDefaults(useDefaults); } void updateSettings() { bool updateConfig = false; for(const QButtonGroup *group: qAsConst(_groups)) { auto *enumItem = groupToConfigItemEnum(group); if(enumItem == nullptr) { continue; } const auto *currentButton = group->checkedButton(); if(currentButton == nullptr) { continue; } const int value = buttonToEnumValue(currentButton); if(value < 0) { continue; } if(!enumItem->isEqual(value)) { enumItem->setValue(value); updateConfig = true; } } if(updateConfig) { _config->save(); emit settingsChanged(); } } protected Q_SLOTS: void setButtonState(QAbstractButton *button, bool checked) { Q_ASSERT(button); Q_ASSERT(button->group()); if(!checked) { // Both deselected and selected buttons trigger this slot, ignore the deselected one return; } auto *enumItem = groupToConfigItemEnum(button->group()); if(enumItem == nullptr) { return; } int value = buttonToEnumValue(button); if(value < 0) { return; } emit settingsChanged(); } private: // Returns configuration item associated with the group KCoreConfigSkeleton::ItemEnum * groupToConfigItemEnum(const QButtonGroup *group) const { Q_ASSERT(group); const QString key = group->objectName().mid(ManagedNamePrefix.length()); auto *item = _config->findItem(key); if(item == nullptr) { return nullptr; } auto *enumItem = dynamic_cast(item); if(enumItem == nullptr) { return nullptr; } return enumItem; } // Returns a value the button represents in its group int buttonToEnumValue(const QAbstractButton *button) const { Q_ASSERT(button); Q_ASSERT(button->group()); if(_buttonValues.contains(button)) { return _buttonValues[button]; } const auto *enumItem = groupToConfigItemEnum(button->group()); if(enumItem == nullptr) { return -1; } const auto &choices = enumItem->choices(); const QString buttonName = button->objectName(); int value = -1; for(int i = 0; i < choices.size(); ++i) { if(buttonName == choices.at(i).name) { value = i; break; } } _buttonValues[button] = value; return value; } static const QString ManagedNamePrefix; mutable QMap _buttonValues; KCoreConfigSkeleton *_config = nullptr; QList _groups; }; } #endif // CONFIGURATIONDIALOG_H