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