diff --git a/kcmkwin/kwincompositing/model.cpp b/kcmkwin/kwincompositing/model.cpp index 777a5abfc6..20dd0c095b 100644 --- a/kcmkwin/kwincompositing/model.cpp +++ b/kcmkwin/kwincompositing/model.cpp @@ -66,6 +66,7 @@ QHash< int, QByteArray > EffectModel::roleNames() const roleNames[EffectStatusRole] = "EffectStatusRole"; roleNames[VideoRole] = "VideoRole"; roleNames[SupportedRole] = "SupportedRole"; + roleNames[ExclusiveRole] = "ExclusiveRole"; return roleNames; } @@ -130,6 +131,8 @@ QVariant EffectModel::data(const QModelIndex &index, int role) const return m_effectsList.at(index.row()).video; case SupportedRole: return m_effectsList.at(index.row()).supported; + case ExclusiveRole: + return m_effectsList.at(index.row()).exclusiveGroup; default: return QVariant(); } @@ -141,17 +144,24 @@ bool EffectModel::setData(const QModelIndex& index, const QVariant& value, int r return QAbstractItemModel::setData(index, value, role); if (role == EffectModel::EffectStatusRole) { - m_effectsList[index.row()].effectStatus = value.toBool(); - - const QString effectServiceName = m_effectsList[index.row()].serviceName; - if (effectServiceName == "kwin4_effect_slide") { - handleDesktopSwitching(index.row()); - } else if (effectServiceName == "kwin4_effect_fadedesktop") { - handleDesktopSwitching(index.row()); - } else if (effectServiceName == "kwin4_effect_cubeslide") { - handleDesktopSwitching(index.row()); - } + EffectData &data = m_effectsList[index.row()]; + data.effectStatus = value.toBool(); emit dataChanged(index, index); + + if (data.effectStatus && !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()) { + continue; + } + EffectData &otherData = m_effectsList[i]; + if (otherData.exclusiveGroup == data.exclusiveGroup) { + otherData.effectStatus = false; + emit dataChanged(this->index(i, 0), this->index(i, 0)); + } + } + } + return true; } else if (role == EffectModel::WindowManagementRole) { bool enabled = value.toBool(); @@ -188,6 +198,7 @@ void EffectModel::loadEffects() effect.enabledByDefault = plugin.isPluginEnabledByDefault(); 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(); m_effectsList << effect; } @@ -239,27 +250,6 @@ void EffectModel::loadEffects() endResetModel(); } -void EffectModel::handleDesktopSwitching(int row) -{ - //Q: Why do we need the handleDesktopSwitching? - //A: Because of the setData, when we enable the effect - //and then we scroll, our model is being updated, - //so the setData is being called again, and as a result - //of that we have multiple effects enabled for the desktop switching. - const QString currentEffect = m_effectsList[row].serviceName; - for (int it = 0; it < m_effectsList.size(); it++) { - EffectData effect = m_effectsList.at(it); - - if (effect.serviceName == "kwin4_effect_slide" && currentEffect != effect.serviceName && effect.effectStatus) { - m_effectsList[it].effectStatus = !m_effectsList[it].effectStatus; - } else if (effect.serviceName == "kwin4_effect_cubeslide" && currentEffect != effect.serviceName && effect.effectStatus) { - m_effectsList[it].effectStatus = !m_effectsList[it].effectStatus; - } else if (effect.serviceName == "kwin4_effect_fadedesktop" && currentEffect != effect.serviceName && effect.effectStatus) { - m_effectsList[it].effectStatus = !m_effectsList[it].effectStatus; - } - } -} - void EffectModel::handleWindowManagement(int row, bool enabled) { //Make sure that our row is valid diff --git a/kcmkwin/kwincompositing/model.h b/kcmkwin/kwincompositing/model.h index b03a184b59..04f3e7550d 100644 --- a/kcmkwin/kwincompositing/model.h +++ b/kcmkwin/kwincompositing/model.h @@ -47,6 +47,7 @@ struct EffectData { bool enabledByDefault; QUrl video; bool supported; + QString exclusiveGroup; }; class EffectModel : public QAbstractItemModel @@ -67,7 +68,8 @@ public: EffectStatusRole, WindowManagementRole, VideoRole, - SupportedRole + SupportedRole, + ExclusiveRole }; explicit EffectModel(QObject *parent = 0); @@ -90,7 +92,6 @@ public: void defaults(); private: - void handleDesktopSwitching(int row); void handleWindowManagement(int row, bool enabled); int findRowByServiceName(const QString &serviceName); QList m_effectsList; diff --git a/kcmkwin/kwincompositing/qml/Effect.qml b/kcmkwin/kwincompositing/qml/Effect.qml index 75c20512b7..d26464345c 100644 --- a/kcmkwin/kwincompositing/qml/Effect.qml +++ b/kcmkwin/kwincompositing/qml/Effect.qml @@ -30,7 +30,7 @@ Rectangle { height: childrenRect.height color: item.ListView.isCurrentItem ? effectView.backgroundActiveColor : index % 2 ? effectView.backgroundNormalColor : effectView.backgroundAlternateColor signal changed() - property alias checked: effectStatusCheckBox.checked + property bool checked: model.EffectStatusRole MouseArea { anchors.fill: parent @@ -43,18 +43,36 @@ Rectangle { id: rowEffect width: parent.width - 2 * spacing x: spacing - CheckBox { - function isDesktopSwitching() { - if (model.ServiceNameRole == "kwin4_effect_slide") { - return true; - } else if (model.ServiceNameRole == "kwin4_effect_fadedesktop") { - return true; - } else if (model.ServiceNameRole == "kwin4_effect_cubeslide") { - return true; - } else { - return false; + + RadioButton { + id: exclusiveGroupButton + property bool exclusive: model.ExclusiveRole != "" + visible: exclusive + checked: model.EffectStatusRole + property bool actuallyChanged: true + property bool initiallyChecked: false + exclusiveGroup: exclusive ? effectView.exclusiveGroupForCategory(model.ExclusiveRole) : null + onCheckedChanged: { + if (!visible) { + return; } + actuallyChanged = true; + item.checked = exclusiveGroupButton.checked + item.changed(); } + onClicked: { + if (!actuallyChanged || initiallyChecked) { + checked = false; + } + actuallyChanged = false; + initiallyChecked = false; + } + Component.onCompleted: { + exclusiveGroupButton.initiallyChecked = model.EffectStatusRole; + } + } + + CheckBox { function isWindowManagementEnabled() { if (model.ServiceNameRole == "kwin4_effect_dialogparent") { windowManagementEnabled = effectStatusCheckBox.checked; @@ -72,9 +90,15 @@ Rectangle { id: effectStatusCheckBox property bool windowManagementEnabled; checked: model.EffectStatusRole - exclusiveGroup: isDesktopSwitching() ? desktopSwitching : null + visible: model.ExclusiveRole == "" - onCheckedChanged: item.changed() + onCheckedChanged: { + if (!visible) { + return; + } + item.checked = effectStatusCheckBox.checked; + item.changed(); + } Connections { target: searchModel onDataChanged: { diff --git a/kcmkwin/kwincompositing/qml/EffectView.qml b/kcmkwin/kwincompositing/qml/EffectView.qml index 3e1bf5f75f..03a4ef8100 100644 --- a/kcmkwin/kwincompositing/qml/EffectView.qml +++ b/kcmkwin/kwincompositing/qml/EffectView.qml @@ -116,7 +116,24 @@ Item { Layout.fillWidth: true Layout.fillHeight: true ListView { + function exclusiveGroupForCategory(category) { + for (var i = 0; i < effectView.exclusiveGroups.length; ++i) { + var item = effectView.exclusiveGroups[i]; + if (item.category == category) { + return item.group; + } + } + var newGroup = Qt.createQmlObject('import QtQuick 2.1; import QtQuick.Controls 1.1; ExclusiveGroup {}', + effectView, + "dynamicExclusiveGroup" + effectView.exclusiveGroups.length); + effectView.exclusiveGroups[effectView.exclusiveGroups.length] = { + 'category': category, + 'group': newGroup + }; + return newGroup; + } id: effectView + property var exclusiveGroups: [] property color backgroundActiveColor: searchModel.backgroundActiveColor property color backgroundNormalColor: searchModel.backgroundNormalColor property color backgroundAlternateColor: searchModel.backgroundAlternateColor @@ -139,12 +156,6 @@ Item { } } - ExclusiveGroup { - id: desktopSwitching - //Our ExclusiveGroup must me outside of the - //ListView, otherwise it will not work - } - }//End ColumnLayout Connections { target: searchModel