File indexing completed on 2024-04-21 11:26:53

0001 /*
0002     This file is part of the KDE libraries
0003 
0004     SPDX-FileCopyrightText: 2001 Michael Goffioul <kdeprint@swing.be>
0005     SPDX-FileCopyrightText: 2004 Frans Englich <frans.englich@telia.com>
0006     SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
0007 
0008     SPDX-License-Identifier: LGPL-2.0-or-later
0009 */
0010 
0011 #include "kcmodule.h"
0012 #include "kconfigwidgets_debug.h"
0013 
0014 #include <KAboutData>
0015 #include <KConfigSkeleton>
0016 #include <KLocalizedString>
0017 #include <kconfigdialogmanager.h>
0018 #if KCONFIGWIDGETS_WITH_KAUTH
0019 #include <KAuth/ExecuteJob>
0020 #endif
0021 
0022 class KCModulePrivate
0023 {
0024 public:
0025     KCModulePrivate()
0026         : _buttons(KCModule::Help | KCModule::Default | KCModule::Apply)
0027         , _about(nullptr)
0028         , _useRootOnlyMessage(false)
0029         , _firstshow(true)
0030         , _needsAuthorization(false)
0031         , _unmanagedWidgetChangeState(false)
0032         , _unmanagedWidgetDefaultState(false)
0033         , _unmanagedWidgetDefaultStateCalled(false)
0034         , _defaultsIndicatorsVisible(false)
0035     {
0036     }
0037 
0038     void authStatusChanged(int status);
0039 
0040     KCModule::Buttons _buttons;
0041     const KAboutData *_about;
0042     QString _rootOnlyMessage;
0043     QList<KConfigDialogManager *> managers;
0044     QString _quickHelp;
0045 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 0)
0046     QString m_ExportText;
0047 #endif
0048     bool _useRootOnlyMessage : 1;
0049     bool _firstshow : 1;
0050 
0051     bool _needsAuthorization : 1;
0052 #if KCONFIGWIDGETS_WITH_KAUTH
0053     KAuth::Action _authAction;
0054 #endif
0055 
0056     // this member is used to record the state on non-automatically
0057     // managed widgets, allowing for mixed KConfigXT-drive and manual
0058     // widgets to coexist peacefully and do the correct thing with
0059     // the changed(bool) signal
0060     bool _unmanagedWidgetChangeState : 1;
0061     bool _unmanagedWidgetDefaultState : 1;
0062     bool _unmanagedWidgetDefaultStateCalled : 1;
0063 
0064     bool _defaultsIndicatorsVisible : 1;
0065 };
0066 
0067 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 85)
0068 KCModule::KCModule(const KAboutData *aboutData, QWidget *parent, const QVariantList &)
0069     : QWidget(parent)
0070     , d(new KCModulePrivate)
0071 {
0072     setAboutData(aboutData);
0073 }
0074 #endif
0075 
0076 KCModule::KCModule(QWidget *parent, const QVariantList &)
0077     : QWidget(parent)
0078     , d(new KCModulePrivate)
0079 {
0080 }
0081 
0082 void KCModule::showEvent(QShowEvent *ev)
0083 {
0084     if (d->_firstshow) {
0085         d->_firstshow = false;
0086         QMetaObject::invokeMethod(this, &KCModule::load, Qt::QueuedConnection);
0087         auto changedFunc = [this]() {
0088             changed(false);
0089         };
0090         QMetaObject::invokeMethod(this, changedFunc, Qt::QueuedConnection);
0091     }
0092 
0093     QWidget::showEvent(ev);
0094 }
0095 
0096 KCModule::Buttons KCModule::buttons() const
0097 {
0098     return d->_buttons;
0099 }
0100 
0101 void KCModule::setButtons(Buttons buttons)
0102 {
0103     d->_buttons = buttons;
0104 }
0105 
0106 KConfigDialogManager *KCModule::addConfig(KCoreConfigSkeleton *config, QWidget *widget)
0107 {
0108     KConfigDialogManager *manager = new KConfigDialogManager(widget, config);
0109     manager->setObjectName(objectName());
0110     connect(manager, &KConfigDialogManager::widgetModified, this, &KCModule::widgetChanged);
0111     connect(manager, &QObject::destroyed, this, [this, manager]() {
0112         d->managers.removeOne(manager);
0113     });
0114     d->managers.append(manager);
0115     return manager;
0116 }
0117 
0118 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 84)
0119 KConfigDialogManager *KCModule::addConfig(KConfigSkeleton *config, QWidget *widget)
0120 {
0121     KConfigDialogManager *manager = new KConfigDialogManager(widget, config);
0122     manager->setObjectName(objectName());
0123     connect(manager, &KConfigDialogManager::widgetModified, this, &KCModule::widgetChanged);
0124     connect(manager, &QObject::destroyed, this, [this, manager]() {
0125         d->managers.removeOne(manager);
0126     });
0127     d->managers.append(manager);
0128     return manager;
0129 }
0130 #endif
0131 
0132 void KCModule::setNeedsAuthorization(bool needsAuth)
0133 {
0134     d->_needsAuthorization = needsAuth;
0135 #if KCONFIGWIDGETS_WITH_KAUTH
0136     if (needsAuth && d->_about) {
0137         d->_authAction = KAuth::Action(QLatin1String("org.kde.kcontrol.") + d->_about->componentName() + QLatin1String(".save"));
0138         d->_needsAuthorization = d->_authAction.isValid();
0139         d->_authAction.setHelperId(QStringLiteral("org.kde.kcontrol.") + d->_about->componentName());
0140         d->_authAction.setParentWidget(this);
0141         authStatusChanged(d->_authAction.status());
0142     } else {
0143         d->_authAction = KAuth::Action();
0144     }
0145 #endif
0146 }
0147 
0148 bool KCModule::needsAuthorization() const
0149 {
0150     return d->_needsAuthorization;
0151 }
0152 
0153 void KCModule::setDefaultsIndicatorsVisible(bool show)
0154 {
0155     if (d->_defaultsIndicatorsVisible == show) {
0156         return;
0157     }
0158 
0159     d->_defaultsIndicatorsVisible = show;
0160     for (KConfigDialogManager *manager : std::as_const(d->managers)) {
0161         manager->setDefaultsIndicatorsVisible(show);
0162     }
0163     Q_EMIT defaultsIndicatorsVisibleChanged(show);
0164 }
0165 
0166 bool KCModule::defaultsIndicatorsVisible() const
0167 {
0168     return d->_defaultsIndicatorsVisible;
0169 }
0170 
0171 #if KCONFIGWIDGETS_WITH_KAUTH
0172 void KCModule::setAuthAction(const KAuth::Action &action)
0173 {
0174     if (!action.isValid()) {
0175         qCWarning(KCONFIG_WIDGETS_LOG) << "Auth action" << action.name() << "is invalid";
0176         d->_needsAuthorization = false;
0177         return;
0178     }
0179     d->_authAction = action;
0180     d->_needsAuthorization = true;
0181     d->_authAction.setParentWidget(this);
0182     authStatusChanged(d->_authAction.status());
0183 }
0184 
0185 KAuth::Action KCModule::authAction() const
0186 {
0187     return d->_authAction;
0188 }
0189 
0190 void KCModule::authStatusChanged(KAuth::Action::AuthStatus status)
0191 {
0192     switch (status) {
0193     case KAuth::Action::AuthorizedStatus:
0194         setUseRootOnlyMessage(false);
0195         break;
0196     case KAuth::Action::AuthRequiredStatus:
0197         setUseRootOnlyMessage(true);
0198         setRootOnlyMessage(i18n("You will be asked to authenticate before saving"));
0199         break;
0200     default:
0201         setUseRootOnlyMessage(true);
0202         setRootOnlyMessage(i18n("You are not allowed to save the configuration"));
0203         break;
0204     }
0205 
0206     qCDebug(KCONFIG_WIDGETS_LOG) << useRootOnlyMessage();
0207 }
0208 #endif
0209 
0210 KCModule::~KCModule()
0211 {
0212     qDeleteAll(d->managers);
0213     d->managers.clear();
0214     delete d->_about;
0215 }
0216 
0217 void KCModule::load()
0218 {
0219     for (KConfigDialogManager *manager : std::as_const(d->managers)) {
0220         manager->updateWidgets();
0221     }
0222     widgetChanged();
0223 }
0224 
0225 void KCModule::save()
0226 {
0227     for (KConfigDialogManager *manager : std::as_const(d->managers)) {
0228         manager->updateSettings();
0229     }
0230     Q_EMIT changed(false);
0231 }
0232 
0233 void KCModule::defaults()
0234 {
0235     for (KConfigDialogManager *manager : std::as_const(d->managers)) {
0236         manager->updateWidgetsDefault();
0237     }
0238 }
0239 
0240 void KCModule::widgetChanged()
0241 {
0242     Q_EMIT changed(d->_unmanagedWidgetChangeState || managedWidgetChangeState());
0243     if (d->_unmanagedWidgetDefaultStateCalled) {
0244         Q_EMIT defaulted(d->_unmanagedWidgetDefaultState && managedWidgetDefaultState());
0245     } else {
0246         Q_EMIT defaulted(!d->managers.isEmpty() && managedWidgetDefaultState());
0247     }
0248 }
0249 
0250 bool KCModule::managedWidgetChangeState() const
0251 {
0252     for (KConfigDialogManager *manager : std::as_const(d->managers)) {
0253         if (manager->hasChanged()) {
0254             return true;
0255         }
0256     }
0257 
0258     return false;
0259 }
0260 
0261 bool KCModule::managedWidgetDefaultState() const
0262 {
0263     for (KConfigDialogManager *manager : std::as_const(d->managers)) {
0264         if (!manager->isDefault()) {
0265             return false;
0266         }
0267     }
0268 
0269     return true;
0270 }
0271 
0272 void KCModule::unmanagedWidgetChangeState(bool changed)
0273 {
0274     d->_unmanagedWidgetChangeState = changed;
0275     widgetChanged();
0276 }
0277 
0278 void KCModule::unmanagedWidgetDefaultState(bool defaulted)
0279 {
0280     d->_unmanagedWidgetDefaultStateCalled = true;
0281     d->_unmanagedWidgetDefaultState = defaulted;
0282     widgetChanged();
0283 }
0284 
0285 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 90)
0286 const KAboutData *KCModule::aboutData() const
0287 {
0288     return d->_about;
0289 }
0290 #endif
0291 
0292 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 106)
0293 void KCModule::setAboutData(const KAboutData *about)
0294 {
0295     if (about != d->_about) {
0296         delete d->_about;
0297         d->_about = about;
0298     }
0299 }
0300 #endif
0301 
0302 void KCModule::setRootOnlyMessage(const QString &message)
0303 {
0304     d->_rootOnlyMessage = message;
0305     Q_EMIT rootOnlyMessageChanged(d->_useRootOnlyMessage, d->_rootOnlyMessage);
0306 }
0307 
0308 QString KCModule::rootOnlyMessage() const
0309 {
0310     return d->_rootOnlyMessage;
0311 }
0312 
0313 void KCModule::setUseRootOnlyMessage(bool on)
0314 {
0315     d->_useRootOnlyMessage = on;
0316     Q_EMIT rootOnlyMessageChanged(d->_useRootOnlyMessage, d->_rootOnlyMessage);
0317 }
0318 
0319 bool KCModule::useRootOnlyMessage() const
0320 {
0321     return d->_useRootOnlyMessage;
0322 }
0323 
0324 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 64)
0325 void KCModule::changed()
0326 {
0327     markAsChanged();
0328 }
0329 #endif
0330 
0331 void KCModule::markAsChanged()
0332 {
0333     Q_EMIT changed(true);
0334 }
0335 
0336 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 90)
0337 KAboutData KCModule::componentData() const
0338 {
0339     return *d->_about;
0340 }
0341 #endif
0342 
0343 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 0)
0344 QString KCModule::exportText() const
0345 {
0346     return d->m_ExportText;
0347 }
0348 #endif
0349 
0350 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 0)
0351 void KCModule::setExportText(const QString &text)
0352 {
0353     d->m_ExportText = text;
0354 }
0355 #endif
0356 
0357 void KCModule::setQuickHelp(const QString &help)
0358 {
0359     d->_quickHelp = help;
0360     Q_EMIT quickHelpChanged();
0361 }
0362 
0363 QString KCModule::quickHelp() const
0364 {
0365     return d->_quickHelp;
0366 }
0367 
0368 QList<KConfigDialogManager *> KCModule::configs() const
0369 {
0370     return d->managers;
0371 }
0372 
0373 #include "moc_kcmodule.cpp"