1/*
2 * Copyright (c) 2015-2021 Meltytech, LLC
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18import QtQuick 2.12
19import QtQuick.Controls 2.12
20import QtQuick.Layouts 1.12
21import Shotcut.Controls 1.0 as Shotcut
22
23Item {
24    property string keyColorParam: '0'
25    property string keyColorDefault: '#19cc19'
26    property string targetColorParam: '1'
27    property string targetColorDefault: '#c67f66'
28    property string maskTypeParam: '2'
29    property string maskTypeDefault: '0'
30    property string toleranceParam: '3'
31    property double toleranceDefault: 0.24
32    property string slopeParam: '4'
33    property double slopeDefault: 0.4
34    property string hueGateParam: '5'
35    property double hueGateDefault: 0.25
36    property string saturationParam: '6'
37    property double saturationDefault: 0.15
38    property string operation1Param: '7'
39    property string operation1Default: '1'
40    property string amount1Param: '8'
41    property double amount1Default: 0.5
42    property string operation2Param: '9'
43    property string operation2Default: '0'
44    property string amount2Param: '10'
45    property double amount2Default: 0.5
46    property string showMaskParam: '11'
47    property bool showMaskDefault: false
48    property string maskAlphaParam: '12'
49    property bool maskAlphaDefault: false
50    property var defaultParameters: [keyColorParam, targetColorParam, maskTypeParam,
51        toleranceParam, slopeParam, hueGateParam, saturationParam, operation1Param,
52        amount1Param, operation2Param, amount2Param]
53
54    width: 200
55    height: 380
56    Component.onCompleted: {
57        filter.set('threads', 0)
58        if (filter.isNew) {
59            filter.set(keyColorParam, keyColorDefault)
60            filter.set(targetColorParam, targetColorDefault)
61            filter.set(maskTypeParam, maskTypeDefault)
62            filter.set(toleranceParam, toleranceDefault)
63            filter.set(slopeParam, slopeDefault)
64            filter.set(hueGateParam, hueGateDefault)
65            filter.set(saturationParam, saturationDefault)
66            filter.set(operation1Param, operation1Default)
67            filter.set(amount1Param, amount1Default)
68            filter.set(operation2Param, operation2Default)
69            filter.set(amount2Param, amount2Default)
70            filter.set(showMaskParam, showMaskDefault)
71            filter.set(maskAlphaParam, maskAlphaDefault)
72            filter.savePreset(defaultParameters)
73        }
74        setControls()
75    }
76
77    function setControls() {
78        keyColorPicker.value = filter.get(keyColorParam)
79        targetColorPicker.value = filter.get(targetColorParam)
80        maskTypeCombo.currentIndex = filter.get(maskTypeParam)
81        toleranceSlider.value = filter.getDouble(toleranceParam) * 100
82        slopeSlider.value = filter.getDouble(slopeParam) * 100
83        hueGateSlider.value = filter.getDouble(hueGateParam) * 100
84        saturationSlider.value = filter.getDouble(saturationParam) * 100
85        operation1Combo.currentIndex = filter.get(operation1Param)
86        amount1Slider.value = filter.getDouble(amount1Param) * 100
87        operation2Combo.currentIndex = filter.get(operation2Param)
88        amount2Slider.value = filter.getDouble(amount2Param) * 100
89        showMaskCheckbox.checked = parseInt(filter.get(showMaskParam))
90        maskAlphaCheckbox.checked = parseInt(filter.get(maskAlphaParam))
91    }
92
93    GridLayout {
94        columns: 3
95        anchors.fill: parent
96        anchors.margins: 8
97
98        Label {
99            text: qsTr('Preset')
100            Layout.alignment: Qt.AlignRight
101        }
102        Shotcut.Preset {
103            id: presetItem
104            Layout.columnSpan: 2
105            parameters: defaultParameters
106            onPresetSelected: setControls()
107        }
108
109        Label {
110            text: qsTr('Key color')
111            Layout.alignment: Qt.AlignRight
112        }
113        Shotcut.ColorPicker {
114            id: keyColorPicker
115            property bool isReady: false
116            Component.onCompleted: isReady = true
117            onValueChanged: {
118                if (isReady) {
119                    filter.set(keyColorParam, value)
120                    filter.set("disable", 0);
121                }
122            }
123            onPickStarted: {
124                filter.set("disable", 1);
125            }
126            onPickCancelled: filter.set('disable', 0)
127        }
128        Shotcut.UndoButton {
129            onClicked: keyColorPicker.value = keyColorDefault
130        }
131
132        Label {
133            text: qsTr('Target color')
134            Layout.alignment: Qt.AlignRight
135        }
136        Shotcut.ColorPicker {
137            id: targetColorPicker
138            property bool isReady: false
139            Component.onCompleted: isReady = true
140            onValueChanged: {
141                if (isReady) {
142                    filter.set(targetColorParam, value)
143                    filter.set("disable", 0);
144                }
145            }
146            onPickStarted: {
147                filter.set("disable", 1);
148            }
149            onPickCancelled: filter.set('disable', 0)
150        }
151        Shotcut.UndoButton {
152            onClicked: targetColorPicker.value = targetColorDefault
153        }
154
155        Label {
156            text: qsTr('Mask type')
157            Layout.alignment: Qt.AlignRight
158        }
159        Shotcut.ComboBox {
160            id: maskTypeCombo
161            implicitWidth: 180
162            model: [qsTr('Color Distance'), qsTr('Transparency'), qsTr('Edge Inwards'), qsTr('Edge Outwards')]
163            onActivated: filter.set(maskTypeParam, currentIndex)
164        }
165        Shotcut.UndoButton {
166            onClicked: {
167                filter.set(maskTypeParam, maskTypeDefault)
168                maskTypeCombo.currentIndex = maskTypeDefault
169            }
170        }
171
172        Label {
173            text: qsTr('Tolerance')
174            Layout.alignment: Qt.AlignRight
175        }
176        Shotcut.SliderSpinner {
177            id: toleranceSlider
178            minimumValue: 0
179            maximumValue: 100
180            decimals: 1
181            suffix: ' %'
182            value: filter.getDouble(toleranceParam) * 100
183            onValueChanged: filter.set(toleranceParam, value / 100)
184        }
185        Shotcut.UndoButton {
186            onClicked: toleranceSlider.value = toleranceDefault * 100
187        }
188
189        Label {
190            text: qsTr('Slope')
191            Layout.alignment: Qt.AlignRight
192        }
193        Shotcut.SliderSpinner {
194            id: slopeSlider
195            minimumValue: 0
196            maximumValue: 100
197            decimals: 1
198            suffix: ' %'
199            value: filter.getDouble(slopeParam) * 100
200            onValueChanged: filter.set(slopeParam, value / 100)
201        }
202        Shotcut.UndoButton {
203            onClicked: slopeSlider.value = slopeDefault * 100
204        }
205
206        Label {
207            text: qsTr('Hue gate')
208            Layout.alignment: Qt.AlignRight
209        }
210        Shotcut.SliderSpinner {
211            id: hueGateSlider
212            minimumValue: 0
213            maximumValue: 100
214            decimals: 1
215            suffix: ' %'
216            value: filter.getDouble(hueGateParam) * 100
217            onValueChanged: filter.set(hueGateParam, value / 100)
218        }
219        Shotcut.UndoButton {
220            onClicked: hueGateSlider.value = hueGateDefault * 100
221        }
222
223        Label {
224            text: qsTr('Saturation threshold')
225            Layout.alignment: Qt.AlignRight
226        }
227        Shotcut.SliderSpinner {
228            id: saturationSlider
229            minimumValue: 0
230            maximumValue: 100
231            decimals: 1
232            suffix: ' %'
233            value: filter.getDouble(saturationParam) * 100
234            onValueChanged: filter.set(saturationParam, value / 100)
235        }
236        Shotcut.UndoButton {
237            onClicked: saturationSlider.value = saturationDefault * 100
238        }
239
240        Label {
241            text: qsTr('Operation 1')
242            Layout.alignment: Qt.AlignRight
243        }
244        Shotcut.ComboBox {
245            id: operation1Combo
246            implicitWidth: 180
247            model: [qsTr('None'), qsTr('De-Key'), qsTr('Desaturate'), qsTr('Adjust Luma')]
248            onActivated: filter.set(operation1Param, currentIndex)
249        }
250        Shotcut.UndoButton {
251            onClicked: {
252                filter.set(operation1Param, operation1Default)
253                operation1Combo.currentIndex = operation1Default
254            }
255        }
256
257        Label {
258            text: qsTr('Amount 1')
259            Layout.alignment: Qt.AlignRight
260        }
261        Shotcut.SliderSpinner {
262            id: amount1Slider
263            minimumValue: 0
264            maximumValue: 100
265            decimals: 1
266            suffix: ' %'
267            value: filter.getDouble(amount1Param) * 100
268            onValueChanged: filter.set(amount1Param, value / 100)
269        }
270        Shotcut.UndoButton {
271            onClicked: amount1Slider.value = amount1Default * 100
272        }
273
274        Label {
275            text: qsTr('Operation 2')
276            Layout.alignment: Qt.AlignRight
277        }
278        Shotcut.ComboBox {
279            id: operation2Combo
280            implicitWidth: 180
281            model: [qsTr('None'), qsTr('De-Key'), qsTr('Desaturate'), qsTr('Adjust Luma')]
282            onActivated: filter.set(operation2Param, currentIndex)
283        }
284        Shotcut.UndoButton {
285            onClicked: {
286                filter.set(operation2Param, operation2Default)
287                operation2Combo.currentIndex = operation2Default
288            }
289        }
290
291        Label {
292            text: qsTr('Amount 2')
293            Layout.alignment: Qt.AlignRight
294        }
295        Shotcut.SliderSpinner {
296            id: amount2Slider
297            minimumValue: 0
298            maximumValue: 100
299            decimals: 1
300            suffix: ' %'
301            value: filter.getDouble(amount2Param) * 100
302            onValueChanged: filter.set(amount2Param, value / 100)
303        }
304        Shotcut.UndoButton {
305            onClicked: amount2Slider.value = amount2Default * 100
306        }
307
308        Label {}
309        CheckBox {
310            id: showMaskCheckbox
311            text: qsTr('Show mask')
312            onCheckedChanged: filter.set(showMaskParam, checked)
313        }
314        Shotcut.UndoButton {
315            onClicked: showMaskCheckbox.checked = showMaskDefault
316        }
317
318        Label {}
319        CheckBox {
320            id: maskAlphaCheckbox
321            text: qsTr('Send mask to alpha channel')
322            onCheckedChanged: filter.set(maskAlphaParam, checked)
323        }
324        Shotcut.UndoButton {
325            onClicked: maskAlphaCheckbox.checked = maskAlphaDefault
326        }
327
328        Item { Layout.fillHeight: true }
329    }
330}
331