Support for mutual exclusive effects
The new X-KWin-Exclusive-Category property is read from the service and provided to QML through the ExclusiveRole. If an effect has such a role the CheckBox is replaced by a RadioButton. The radio buttons of an exclusive group take care that only one effect of the group can be enabled. In addition the radio button acts like a check box. If one clicks the checked radio button it gets unchecked. At the same time this change removes the hard coded functionality for the exclusive group of desktop switching effects. It's all handled dynamically by creating the ExclusiveGroup when needed. For each category there can be one ExclusiveGroup. REVIEW: 116711
This commit is contained in:
parent
503c221733
commit
7d63ab03bc
4 changed files with 78 additions and 52 deletions
|
@ -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
|
||||
|
|
|
@ -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<EffectData> m_effectsList;
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue