1/*
2    SPDX-FileCopyrightText: 2020 Ismael Asensio <isma.af@gmail.com>
3
4    SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
5*/
6
7import QtQuick 2.14
8import QtQuick.Layouts 1.14
9import QtQuick.Controls 2.14 as QQC2
10
11import org.kde.kirigami 2.10 as Kirigami
12import org.kde.kquickcontrols 2.0 as KQC
13import org.kde.kcms.kwinrules 1.0
14
15
16Loader {
17    id: valueEditor
18    focus: true
19
20    property var ruleValue
21    property var ruleOptions
22    property int controlType
23
24    signal valueEdited(var value)
25
26    sourceComponent: {
27        switch (controlType) {
28            case RuleItem.Boolean: return booleanEditor
29            case RuleItem.String: return stringEditor
30            case RuleItem.Integer: return integerEditor
31            case RuleItem.Option: return optionEditor
32            case RuleItem.NetTypes: return netTypesEditor
33            case RuleItem.Percentage: return percentageEditor
34            case RuleItem.Point: return coordinateEditor
35            case RuleItem.Size: return coordinateEditor
36            case RuleItem.Shortcut: return shortcutEditor
37            case RuleItem.OptionList: return optionListEditor
38            default: return emptyEditor
39        }
40    }
41
42    Component {
43        id: emptyEditor
44        Item {}
45    }
46
47    Component {
48        id: booleanEditor
49        RowLayout {
50            Item {
51                Layout.fillWidth: true
52            }
53            QQC2.RadioButton {
54                text: i18n("Yes")
55                checked: ruleValue
56                Layout.margins: Kirigami.Units.smallSpacing
57                onToggled: valueEditor.valueEdited(checked)
58            }
59            QQC2.RadioButton {
60                text: i18n("No")
61                checked: !ruleValue
62                Layout.margins: Kirigami.Units.smallSpacing
63                onToggled: valueEditor.valueEdited(!checked)
64            }
65        }
66    }
67
68    Component {
69        id: stringEditor
70        QQC2.TextField {
71            id: stringTextField
72            property bool isTextEdited: false
73            horizontalAlignment: Text.AlignLeft
74            onTextEdited: { valueEditor.valueEdited(text); }
75            Connections {
76                target: valueEditor
77                function onRuleValueChanged() {
78                    if (!stringTextField.activeFocus) {  // Protects from self-updating when editing
79                        stringTextField.text = valueEditor.ruleValue
80                    }
81                }
82            }
83            Component.onCompleted: { this.text = valueEditor.ruleValue }
84        }
85    }
86
87    Component {
88        id: integerEditor
89        QQC2.SpinBox {
90            editable: true
91            value: ruleValue
92            onValueModified: valueEditor.valueEdited(value)
93        }
94    }
95
96    Component {
97        id: optionEditor
98        OptionsComboBox {
99            flat: true
100            model: ruleOptions
101            onActivated: (index) => {
102                valueEditor.valueEdited(currentValue);
103            }
104        }
105    }
106
107    Component {
108        id: netTypesEditor
109        OptionsComboBox {
110            flat: true
111            model: ruleOptions
112            multipleChoice: true
113            useFlagsValue: true
114            // Filter the provided value with the options mask
115            selectionMask: ruleValue & optionsMask
116            onActivated: {
117                valueEditor.valueEdited(selectionMask);
118            }
119        }
120    }
121
122    Component {
123        id: optionListEditor
124        OptionsComboBox {
125            id: optionListCombo
126            flat: true
127            model: ruleOptions
128            multipleChoice: true
129
130            onActivated: {
131                let selectionList = []
132                for (let i = 0; i < count; i++) {
133                    if (selectionMask & (1 << i)) {
134                        selectionList.push(model.data(model.index(i,0), Qt.UserRole))
135                    }
136                }
137                valueEditor.valueEdited(selectionList);
138            }
139
140            function updateSelectionMask() {
141                selectionMask = 0
142                for (let i = 0; i < count; i++) {
143                    if (ruleValue.includes(model.data(model.index(i,0), Qt.UserRole))) {
144                        selectionMask += 1 << i
145                    }
146                }
147            }
148
149            onModelChanged: updateSelectionMask()
150            Component.onCompleted: updateSelectionMask()
151            Connections {
152                target: valueEditor
153                function onRuleValueChanged() {
154                    optionListCombo.updateSelectionMask()
155                }
156            }
157        }
158    }
159
160    Component {
161        id: percentageEditor
162        RowLayout {
163            QQC2.Slider {
164                id: slider
165                Layout.fillWidth: true
166                from: 0
167                to: 100
168                value: ruleValue
169                onMoved: valueEditor.valueEdited(Math.round(slider.value))
170            }
171            QQC2.Label {
172                text: i18n("%1 %", Math.round(slider.value))
173                horizontalAlignment: Qt.AlignRight
174                Layout.minimumWidth: maxPercentage.width + Kirigami.Units.smallSpacing
175                Layout.margins: Kirigami.Units.smallSpacing
176            }
177            TextMetrics {
178                id: maxPercentage
179                text: i18n("%1 %", 100)
180            }
181        }
182    }
183
184    Component {
185        id: coordinateEditor
186        RowLayout {
187            id: coordItem
188            spacing: Kirigami.Units.smallSpacing
189
190            readonly property bool isSize: controlType == RuleItem.Size
191            readonly property var coord: (isSize) ? Qt.size(coordX.value, coordY.value)
192                                                  : Qt.point(coordX.value, coordY.value)
193
194            QQC2.SpinBox {
195                id: coordX
196                editable: true
197                Layout.preferredWidth: 50   // 50%
198                Layout.fillWidth: true
199                from: (isSize) ? 0 : -32767
200                to: 32767
201                value: (isSize) ? ruleValue.width : ruleValue.x
202                onValueModified: valueEditor.valueEdited(coord)
203            }
204            QQC2.Label {
205                id: coordSeparator
206                Layout.preferredWidth: implicitWidth
207                text: i18nc("(x, y) coordinates separator in size/position","x")
208                horizontalAlignment: Text.AlignHCenter
209            }
210            QQC2.SpinBox {
211                id: coordY
212                editable: true
213                from: coordX.from
214                to: coordX.to
215                Layout.preferredWidth: 50   // 50%
216                Layout.fillWidth: true
217                value: (isSize) ? ruleValue.height : ruleValue.y
218                onValueModified: valueEditor.valueEdited(coord)
219            }
220        }
221    }
222
223    Component {
224        id: shortcutEditor
225        RowLayout {
226            Item {
227                Layout.fillWidth: true
228            }
229            KQC.KeySequenceItem {
230                keySequence: ruleValue
231                onCaptureFinished: valueEditor.valueEdited(keySequence)
232            }
233        }
234    }
235}
236