diff --git a/kcmkwin/kwincompositing/model.cpp b/kcmkwin/kwincompositing/model.cpp index 1426c472c1..3b2f158e19 100644 --- a/kcmkwin/kwincompositing/model.cpp +++ b/kcmkwin/kwincompositing/model.cpp @@ -80,6 +80,11 @@ static QString translatedCategory(const QString &category) return translatedCategories[index]; } +static EffectStatus effectStatus(bool enabled) +{ + return enabled ? EffectStatus::Enabled : EffectStatus::Disabled; +} + EffectModel::EffectModel(QObject *parent) : QAbstractItemModel(parent) { } @@ -160,7 +165,7 @@ QVariant EffectModel::data(const QModelIndex &index, int role) const case ServiceNameRole: return m_effectsList.at(index.row()).serviceName; case EffectStatusRole: - return m_effectsList.at(index.row()).effectStatus; + return (int)m_effectsList.at(index.row()).effectStatus; case VideoRole: return m_effectsList.at(index.row()).video; case SupportedRole: @@ -188,11 +193,11 @@ bool EffectModel::setData(const QModelIndex& index, const QVariant& value, int r // gets marked as changed and will get saved to the config file. This means the // config file could get polluted EffectData &data = m_effectsList[index.row()]; - data.effectStatus = value.toBool(); + data.effectStatus = EffectStatus(value.toInt()); data.changed = true; emit dataChanged(index, index); - if (data.effectStatus && !data.exclusiveGroup.isEmpty()) { + if (data.effectStatus == EffectStatus::Enabled && !data.exclusiveGroup.isEmpty()) { // need to disable all other exclusive effects in the same category for (int i = 0; i < m_effectsList.size(); ++i) { if (i == index.row()) { @@ -200,7 +205,7 @@ bool EffectModel::setData(const QModelIndex& index, const QVariant& value, int r } EffectData &otherData = m_effectsList[i]; if (otherData.exclusiveGroup == data.exclusiveGroup) { - otherData.effectStatus = false; + otherData.effectStatus = EffectStatus::Disabled; otherData.changed = true; emit dataChanged(this->index(i, 0), this->index(i, 0)); } @@ -234,7 +239,15 @@ void EffectModel::loadEffects() effect.category = translatedCategory(data.category); effect.serviceName = data.name; effect.enabledByDefault = data.enabled; - effect.effectStatus = kwinConfig.readEntry(effect.serviceName + "Enabled", effect.enabledByDefault); + effect.enabledByDefaultFunction = (data.enabledFunction != nullptr); + const QString enabledKey = QStringLiteral("%1Enabled").arg(effect.serviceName); + if (kwinConfig.hasKey(enabledKey)) { + effect.effectStatus = effectStatus(kwinConfig.readEntry(effect.serviceName + "Enabled", effect.enabledByDefault)); + } else if (data.enabledFunction != nullptr) { + effect.effectStatus = EffectStatus::EnabledUndeterminded; + } else { + effect.effectStatus = effectStatus(effect.enabledByDefault); + } effect.video = data.video; effect.supported = true; effect.exclusiveGroup = data.exclusiveCategory; @@ -262,8 +275,9 @@ void EffectModel::loadEffects() effect.version = plugin.version(); effect.category = translatedCategory(plugin.category()); effect.serviceName = plugin.pluginName(); - effect.effectStatus = kwinConfig.readEntry(effect.serviceName + "Enabled", plugin.isPluginEnabledByDefault()); + effect.effectStatus = effectStatus(kwinConfig.readEntry(effect.serviceName + "Enabled", plugin.isPluginEnabledByDefault())); effect.enabledByDefault = plugin.isPluginEnabledByDefault(); + effect.enabledByDefaultFunction = false; effect.video = service->property(QStringLiteral("X-KWin-Video-Url"), QVariant::Url).toUrl(); effect.supported = true; effect.exclusiveGroup = service->property(QStringLiteral("X-KWin-Exclusive-Category"), QVariant::String).toString(); @@ -350,7 +364,7 @@ void EffectModel::syncEffectsToKWin() QDBusConnection::sessionBus()); for (int it = 0; it < m_effectsList.size(); it++) { if (m_effectsList.at(it).effectStatus != m_effectsChanged.at(it).effectStatus) { - if (m_effectsList.at(it).effectStatus) { + if (m_effectsList.at(it).effectStatus != EffectStatus::Disabled) { interface.loadEffect(m_effectsList.at(it).serviceName); } else { interface.unloadEffect(m_effectsList.at(it).serviceName); @@ -361,9 +375,9 @@ void EffectModel::syncEffectsToKWin() m_effectsChanged = m_effectsList; } -void EffectModel::updateEffectStatus(const QModelIndex &rowIndex, bool effectState) +void EffectModel::updateEffectStatus(const QModelIndex &rowIndex, EffectStatus effectState) { - setData(rowIndex, effectState, EffectModel::EffectStatusRole); + setData(rowIndex, (int)effectState, EffectModel::EffectStatusRole); } void EffectModel::syncConfig() @@ -378,11 +392,14 @@ void EffectModel::syncConfig() effect.changed = false; const QString key = effect.serviceName + QStringLiteral("Enabled"); - - if (effect.effectStatus != effect.enabledByDefault) { - kwinConfig.writeEntry(key, effect.effectStatus); - } else { + const bool shouldEnable = (effect.effectStatus != EffectStatus::Disabled); + const bool restoreToDefault = effect.enabledByDefaultFunction + ? effect.effectStatus == EffectStatus::EnabledUndeterminded + : shouldEnable == effect.enabledByDefault; + if (restoreToDefault) { kwinConfig.deleteEntry(key); + } else { + kwinConfig.writeEntry(key, shouldEnable); } } @@ -394,8 +411,10 @@ void EffectModel::defaults() { for (int i = 0; i < m_effectsList.count(); ++i) { const auto &effect = m_effectsList.at(i); - if (effect.effectStatus != effect.enabledByDefault) { - updateEffectStatus(index(i, 0), effect.enabledByDefault); + if (effect.enabledByDefaultFunction && effect.effectStatus != EffectStatus::EnabledUndeterminded) { + updateEffectStatus(index(i, 0), EffectStatus::EnabledUndeterminded); + } else if ((bool)effect.effectStatus != effect.enabledByDefault) { + updateEffectStatus(index(i, 0), effect.enabledByDefault ? EffectStatus::Enabled : EffectStatus::Disabled); } } } @@ -472,11 +491,11 @@ bool EffectFilterModel::filterAcceptsRow(int source_row, const QModelIndex &sour return false; } -void EffectFilterModel::updateEffectStatus(int rowIndex, bool effectState) +void EffectFilterModel::updateEffectStatus(int rowIndex, int effectState) { const QModelIndex sourceIndex = mapToSource(index(rowIndex, 0)); - m_effectModel->updateEffectStatus(sourceIndex, effectState); + m_effectModel->updateEffectStatus(sourceIndex, EffectStatus(effectState)); } void EffectFilterModel::syncConfig() diff --git a/kcmkwin/kwincompositing/model.h b/kcmkwin/kwincompositing/model.h index fc7f7dad25..b863b1b371 100644 --- a/kcmkwin/kwincompositing/model.h +++ b/kcmkwin/kwincompositing/model.h @@ -34,6 +34,12 @@ namespace KWin { namespace Compositing { +enum class EffectStatus { + Disabled = Qt::Unchecked, + EnabledUndeterminded = Qt::PartiallyChecked, + Enabled = Qt::Checked +}; + struct EffectData { QString name; QString description; @@ -43,8 +49,9 @@ struct EffectData { QString version; QString category; QString serviceName; - bool effectStatus; + EffectStatus effectStatus; bool enabledByDefault; + bool enabledByDefaultFunction; QUrl video; bool supported; QString exclusiveGroup; @@ -90,7 +97,7 @@ public: virtual QHash< int, QByteArray > roleNames() const override; - void updateEffectStatus(const QModelIndex &rowIndex, bool effectState); + void updateEffectStatus(const QModelIndex &rowIndex, EffectStatus effectState); void syncEffectsToKWin(); void syncConfig(); void loadEffects(); @@ -153,7 +160,7 @@ public: EffectFilterModel(QObject *parent = 0); const QString &filter() const; - Q_INVOKABLE void updateEffectStatus(int rowIndex, bool effectState); + Q_INVOKABLE void updateEffectStatus(int rowIndex, int effectState); Q_INVOKABLE void syncConfig(); Q_INVOKABLE void load(); diff --git a/kcmkwin/kwincompositing/qml/Effect.qml b/kcmkwin/kwincompositing/qml/Effect.qml index e05ab81cef..0c46ef3b44 100644 --- a/kcmkwin/kwincompositing/qml/Effect.qml +++ b/kcmkwin/kwincompositing/qml/Effect.qml @@ -30,7 +30,7 @@ Rectangle { height: rowEffect.implicitHeight color: item.ListView.isCurrentItem ? effectView.backgroundActiveColor : index % 2 ? effectView.backgroundNormalColor : effectView.backgroundAlternateColor signal changed() - property bool checked: model.EffectStatusRole + property int checkedState: model.EffectStatusRole MouseArea { anchors.fill: parent @@ -61,7 +61,7 @@ Rectangle { return; } actuallyChanged = true; - item.checked = exclusiveGroupButton.checked + item.checkedState = exclusiveGroupButton.checked ? Qt.Checked : Qt.UnChecked item.changed(); } onClicked: { @@ -78,20 +78,20 @@ Rectangle { CheckBox { id: effectStatusCheckBox - checked: model.EffectStatusRole + checkedState: model.EffectStatusRole visible: model.ExclusiveRole == "" - onCheckedChanged: { + onCheckedStateChanged: { if (!visible) { return; } - item.checked = effectStatusCheckBox.checked; + item.checkedState = effectStatusCheckBox.checkedState; item.changed(); } Connections { target: searchModel onDataChanged: { - effectStatusCheckBox.checked = model.EffectStatusRole; + effectStatusCheckBox.checkedState = model.EffectStatusRole; } } } @@ -140,7 +140,7 @@ Rectangle { Button { id: configureButton visible: ConfigurableRole - enabled: effectStatusCheckBox.checked + enabled: item.checkedState != Qt.UnChecked iconName: "configure" onClicked: { effectConfig.openConfig(model.ServiceNameRole, model.ScriptedRole, model.NameRole); diff --git a/kcmkwin/kwincompositing/qml/EffectView.qml b/kcmkwin/kwincompositing/qml/EffectView.qml index 4db0818273..4118b3f96e 100644 --- a/kcmkwin/kwincompositing/qml/EffectView.qml +++ b/kcmkwin/kwincompositing/qml/EffectView.qml @@ -111,11 +111,6 @@ Item { id: searchModel objectName: "filterModel" filter: searchField.text - signal effectState(int rowIndex, bool enabled) - - onEffectState: { - searchModel.updateEffectStatus(rowIndex, enabled); - } } ScrollView { @@ -157,7 +152,9 @@ Item { Connections { id: effectStateConnection target: null - onChanged: searchModel.effectState(index, checked) + onChanged: { + searchModel.updateEffectStatus(index, checkedState); + } } Component.onCompleted: { effectStateConnection.target = effectDelegate @@ -174,6 +171,6 @@ Item { }//End ColumnLayout Connections { target: searchModel - onEffectState: changed() + onDataChanged: changed() } }//End item