1/*
2 * Copyright (c) 2020-2021 Meltytech, LLC
3 * Written by Austin Brooks <ab.shotcut@outlook.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
20import QtQuick 2.12
21import QtQuick.Controls 2.12
22import QtQuick.Layouts 1.12
23import QtQuick.Window 2.12
24import Shotcut.Controls 1.0 as Shotcut
25
26
27Item {
28    property string methodParam: 'av.method'
29    property string methodDefault: 'garrote'
30    property var methodValues: ['soft', 'garrote', 'hard']
31
32    property string nstepsParam: 'av.nsteps'
33    property int nstepsDefault: 7
34
35    property string thresholdParam: 'av.threshold'
36    property double thresholdDefault: 10
37
38    property string percentParam: 'av.percent'
39    property double percentDefault: 85
40
41    property var allParams: [methodParam, nstepsParam, thresholdParam, percentParam]
42
43
44    width: 350
45    height: 200
46
47
48    function getComboIndex (value, values) {
49        for ( var i = 0 ; i < values.length ; ++i ) {
50            if ( values[i] === value ) {
51                return i
52            }
53        }
54        return -1
55    }
56
57
58    function setControls () {
59        idMethod.currentIndex = getComboIndex(filter.get(methodParam), methodValues)
60        idNsteps.value = parseInt(filter.get(nstepsParam))
61        idThreshold.value = filter.getDouble(thresholdParam)
62        idPercent.value = filter.getDouble(percentParam)
63    }
64
65
66    function getMaxSteps () {
67        var min = Math.min(profile.width, profile.height)
68
69        var i = 1
70        while ( Math.pow(2,i) <= min ) {
71            ++i
72        }
73
74        return i - 1
75    }
76
77
78    Component.onCompleted: {
79        filter.blockSignals = true
80        if ( filter.isNew ) {
81            // Custom preset
82            filter.set(methodParam, 'garrote')
83            filter.set(nstepsParam, 5)
84            filter.set(thresholdParam, 7)
85            filter.set(percentParam, 85)
86            filter.savePreset(allParams, qsTr('Light'))
87
88            // Custom preset
89            filter.set(methodParam, 'garrote')
90            filter.set(nstepsParam, 7)
91            filter.set(thresholdParam, 10)
92            filter.set(percentParam, 85)
93            filter.savePreset(allParams, qsTr('Medium'))
94
95            // Custom preset
96            filter.set(methodParam, 'garrote')
97            filter.set(nstepsParam, 8)
98            filter.set(thresholdParam, 16)
99            filter.set(percentParam, 85)
100            filter.savePreset(allParams, qsTr('Heavy'))
101
102            // Default preset
103            filter.set(methodParam, methodDefault)
104            filter.set(nstepsParam, nstepsDefault)
105            filter.set(thresholdParam, thresholdDefault)
106            filter.set(percentParam, percentDefault)
107            filter.savePreset(allParams)
108        }
109        filter.blockSignals = false
110
111        setControls()
112    }
113
114
115    GridLayout {
116        columns: 3
117        anchors.fill: parent
118        anchors.margins: 8
119
120        // Row split
121
122        Label {
123            text: qsTr('Preset')
124            Layout.alignment: Qt.AlignRight
125        }
126        Shotcut.Preset {
127            id: idPreset
128            Layout.columnSpan: 2
129            parameters: allParams
130            onPresetSelected: setControls()
131        }
132
133        // Row split
134
135        Label {
136            text: qsTr('Method')
137            Layout.alignment: Qt.AlignRight
138        }
139        Shotcut.ComboBox {
140            id: idMethod
141            implicitWidth: 180
142            model: [qsTr('Soft'), qsTr('Garrote'), qsTr('Hard', 'Remove Noise Wavelet filter')]
143            onActivated: filter.set(methodParam, methodValues[currentIndex])
144        }
145        Shotcut.UndoButton {
146            onClicked: {
147                idMethod.currentIndex = getComboIndex(methodDefault, methodValues)
148                filter.set(methodParam, methodValues[idMethod.currentIndex])
149            }
150        }
151
152        // Row split
153
154        Label {
155            text: qsTr('Decompose')
156            Layout.alignment: Qt.AlignRight
157        }
158        Shotcut.SliderSpinner {
159            id: idNsteps
160            minimumValue: 1
161            maximumValue: 32
162            onValueChanged: filter.set(nstepsParam, value)
163        }
164        Shotcut.UndoButton {
165            onClicked: idNsteps.value = nstepsDefault
166        }
167
168        // Row split
169
170        Label {
171            text: qsTr('Threshold')
172            Layout.alignment: Qt.AlignRight
173        }
174        Shotcut.SliderSpinner {
175            id: idThreshold
176            minimumValue: 0
177            maximumValue: 64
178            onValueChanged: filter.set(thresholdParam, value)
179        }
180        Shotcut.UndoButton {
181            onClicked: idThreshold.value = thresholdDefault
182        }
183
184        // Row split
185
186        Label {
187            text: qsTr('Percent')
188            Layout.alignment: Qt.AlignRight
189        }
190        Shotcut.SliderSpinner {
191            id: idPercent
192            minimumValue: 0
193            maximumValue: 100
194            suffix: ' %'
195            onValueChanged: filter.set(percentParam, value)
196        }
197        Shotcut.UndoButton {
198            onClicked: idPercent.value = percentDefault
199        }
200
201        // Row split
202
203        Label {
204            text: qsTr('Max decompositions for the current video mode') + ': ' + getMaxSteps()
205            Layout.alignment: Qt.AlignHCenter
206            Layout.columnSpan: 3
207        }
208
209        // Row split
210
211        Label {
212            text: qsTr('More information') + ': <a href="http://ffmpeg.org/ffmpeg-all.html#vaguedenoiser">FFmpeg vaguedenoiser</a>'
213            Layout.alignment: Qt.AlignHCenter
214            Layout.columnSpan: 3
215
216            MouseArea {
217                anchors.fill: parent
218                acceptedButtons: Qt.NoButton
219                cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
220            }
221
222            onLinkActivated: Qt.openUrlExternally(link)
223        }
224
225        // Filler
226
227        Item {
228            Layout.columnSpan: 3
229            Layout.fillHeight: true
230        }
231    }
232}
233