diff --git a/kcms/kded/kcmkded.cpp b/kcms/kded/kcmkded.cpp --- a/kcms/kded/kcmkded.cpp +++ b/kcms/kded/kcmkded.cpp @@ -76,7 +76,8 @@ m_filteredModel->setSourceModel(m_model); connect(m_model, &ModulesModel::autoloadedModulesChanged, this, [this] { - setNeedsSave(true); + setNeedsSave(m_model->needsSave()); + setRepresentsDefaults(m_model->representsDefault()); }); connect(m_kdedWatcher, &QDBusServiceWatcher::serviceOwnerChanged, this, @@ -212,6 +213,7 @@ m_model->load(); setNeedsSave(false); + setRepresentsDefaults(m_model->representsDefault()); } void KDEDConfig::save() @@ -234,7 +236,7 @@ } kdedrc.sync(); - + m_model->refreshAutoloadEnabledSavedState(); setNeedsSave(false); m_runningModulesBeforeReconfigure = m_model->runningModules(); @@ -262,8 +264,8 @@ { for (int i = 0; i < m_model->rowCount(); ++i) { const QModelIndex idx = m_model->index(i, 0); - if (m_model->setData(idx, true, ModulesModel::AutoloadEnabledRole)) { - setNeedsSave(true); + if (!idx.data(ModulesModel::ImmutableRole).toBool()) { + m_model->setData(idx, true, ModulesModel::AutoloadEnabledRole); } } } diff --git a/kcms/kded/modulesmodel.h b/kcms/kded/modulesmodel.h --- a/kcms/kded/modulesmodel.h +++ b/kcms/kded/modulesmodel.h @@ -33,6 +33,8 @@ KDEDConfig::ModuleType type; bool autoloadEnabled; QString moduleName; + bool immutable; + bool autoloadEnabledSaved; }; Q_DECLARE_TYPEINFO(ModulesModelData, Q_MOVABLE_TYPE); @@ -49,7 +51,8 @@ TypeRole, AutoloadEnabledRole, StatusRole, - ModuleNameRole + ModuleNameRole, + ImmutableRole, }; int rowCount(const QModelIndex &parent = QModelIndex()) const override; @@ -65,6 +68,10 @@ QStringList runningModules() const; void setRunningModules(const QStringList &runningModules); + bool representsDefault() const; + bool needsSave() const; + void refreshAutoloadEnabledSavedState(); + signals: void autoloadedModulesChanged(); diff --git a/kcms/kded/modulesmodel.cpp b/kcms/kded/modulesmodel.cpp --- a/kcms/kded/modulesmodel.cpp +++ b/kcms/kded/modulesmodel.cpp @@ -75,11 +75,38 @@ return KDEDConfig::NotRunning; } case ModuleNameRole: return item.moduleName; + case ImmutableRole: return item.immutable; } return QVariant(); } +bool ModulesModel::representsDefault() const +{ + bool isDefault = true; + for (int i = 0; i < m_data.count(); ++i) { + auto &item = m_data[i]; + if (item.type != KDEDConfig::AutostartType || item.immutable) { + continue; + } + isDefault &= item.autoloadEnabled; + } + return isDefault; +} + +bool ModulesModel::needsSave() const +{ + bool save = false; + for (int i = 0; i < m_data.count(); ++i) { + auto &item = m_data[i]; + if (item.type != KDEDConfig::AutostartType || item.immutable) { + continue; + } + save |= item.autoloadEnabled != item.autoloadEnabledSaved; + } + return save; +} + bool ModulesModel::setData(const QModelIndex &index, const QVariant &value, int role) { bool dirty = false; @@ -90,18 +117,21 @@ auto &item = m_data[index.row()]; + if (item.type != KDEDConfig::AutostartType || item.immutable) { + return dirty; + } + switch (role) { - case AutoloadEnabledRole: + case AutoloadEnabledRole: { const bool autoloadEnabled = value.toBool(); - if (item.type == KDEDConfig::AutostartType - && item.autoloadEnabled != autoloadEnabled) { - item.autoloadEnabled = value.toBool(); + if (item.autoloadEnabled != autoloadEnabled) { + item.autoloadEnabled = autoloadEnabled; dirty = true; - - emit autoloadedModulesChanged(); } + emit autoloadedModulesChanged(); break; } + } if (dirty) { emit dataChanged(index, index, {role}); @@ -119,6 +149,7 @@ {AutoloadEnabledRole, QByteArrayLiteral("autoloadEnabled")}, {StatusRole, QByteArrayLiteral("status")}, {ModuleNameRole, QByteArrayLiteral("moduleName")}, + {ImmutableRole, QByteArrayLiteral("immutable")}, }; } @@ -177,6 +208,7 @@ // autoload defaults to false if it is not found const bool autoload = module.rawData().value(QStringLiteral("X-KDE-Kded-autoload")).toVariant().toBool(); + // keep estimating dbusModuleName in sync with KDEDModule (kdbusaddons) and kded (kded) // currently (KF5) the module name in the D-Bus object path is set by the pluginId const QString dbusModuleName = module.pluginId(); @@ -190,13 +222,16 @@ KConfigGroup cg(&kdedrc, QStringLiteral("Module-%1").arg(dbusModuleName)); const bool autoloadEnabled = cg.readEntry("autoload", true); + const bool immutable = cg.isEntryImmutable("autoload"); ModulesModelData data{ module.name(), module.description(), KDEDConfig::UnknownType, autoloadEnabled, - dbusModuleName + dbusModuleName, + immutable, + autoloadEnabled }; // The logic has to be identical to Kded::initModules. @@ -258,3 +293,11 @@ emit dataChanged(index(0, 0), index(m_data.count() - 1, 0), {StatusRole}); } } + +void ModulesModel::refreshAutoloadEnabledSavedState() +{ + for (int i = 0; i < m_data.count(); ++i) { + auto &item = m_data[i]; + item.autoloadEnabledSaved = item.autoloadEnabled; + } +} diff --git a/kcms/kded/package/contents/ui/main.qml b/kcms/kded/package/contents/ui/main.qml --- a/kcms/kded/package/contents/ui/main.qml +++ b/kcms/kded/package/contents/ui/main.qml @@ -36,8 +36,6 @@

Use this with care: some services are vital for Plasma; do not deactivate services if you do not know what you are doing.

") - // TODO immutable somehow? - Binding { target: kcm.filteredModel property: "query" @@ -164,6 +162,7 @@ id: delegate // FIXME why does the padding logic to dodge the ScrollBars not work here? text: model.display + enabled: !model.immutable checkable: model.type !== Private.KCM.OnDemandType checked: model.autoloadEnabled === true hoverEnabled: checkable