diff --git a/kcms/kded/kcmkded.cpp b/kcms/kded/kcmkded.cpp --- a/kcms/kded/kcmkded.cpp +++ b/kcms/kded/kcmkded.cpp @@ -75,8 +75,9 @@ m_filteredModel->setSourceModel(m_model); - connect(m_model, &ModulesModel::autoloadedModulesChanged, this, [this] { - setNeedsSave(true); + connect(m_model, &ModulesModel::autoloadedModulesChanged, this, [this](const bool changed) { + setNeedsSave(changed); + 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() @@ -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 autoloadEnableSaved; }; 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,8 +68,10 @@ QStringList runningModules() const; void setRunningModules(const QStringList &runningModules); + bool representsDefault() const; + signals: - void autoloadedModulesChanged(); + void autoloadedModulesChanged(bool changed); private: QVector m_data; diff --git a/kcms/kded/modulesmodel.cpp b/kcms/kded/modulesmodel.cpp --- a/kcms/kded/modulesmodel.cpp +++ b/kcms/kded/modulesmodel.cpp @@ -75,17 +75,33 @@ 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 < rowCount(); ++i) { + const QModelIndex idx = index(i, 0); + const auto type = static_cast(idx.data(ModulesModel::TypeRole).toInt()); + const bool immutable = idx.data(ModulesModel::ImmutableRole).toBool(); + if (type != KDEDConfig::AutostartType || immutable) { + continue; + } + isDefault &= idx.data(ModulesModel::AutoloadEnabledRole).toBool(); + } + return isDefault; +} + bool ModulesModel::setData(const QModelIndex &index, const QVariant &value, int role) { - bool dirty = false; + bool dirtyModel = false; + bool dirtyConfig = false; if (!checkIndex(index)) { - return dirty; + return dirtyModel; } auto &item = m_data[index.row()]; @@ -96,18 +112,20 @@ if (item.type == KDEDConfig::AutostartType && item.autoloadEnabled != autoloadEnabled) { item.autoloadEnabled = value.toBool(); - dirty = true; - - emit autoloadedModulesChanged(); + dirtyModel = true; + if (item.autoloadEnableSaved != value.toBool()) { + dirtyConfig = true; + } + emit autoloadedModulesChanged(dirtyConfig); } break; } - if (dirty) { + if (dirtyModel) { emit dataChanged(index, index, {role}); } - return dirty; + return dirtyConfig; } QHash ModulesModel::roleNames() const @@ -119,6 +137,7 @@ {AutoloadEnabledRole, QByteArrayLiteral("autoloadEnabled")}, {StatusRole, QByteArrayLiteral("status")}, {ModuleNameRole, QByteArrayLiteral("moduleName")}, + {ImmutableRole, QByteArrayLiteral("immutable")}, }; } @@ -177,6 +196,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 +210,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. @@ -227,6 +250,7 @@ m_data << autostartModules << onDemandModules; endResetModel(); + emit autoloadedModulesChanged(false); } bool ModulesModel::runningModulesKnown() const 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