Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/qml/filters/delogo/meta.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2018 Meltytech, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import QtQuick 2.0
import org.shotcut.qml 1.0

Metadata {
type: Metadata.Filter
name: qsTr("Remove Spot")
mlt_service: 'avfilter.delogo'
qml: 'ui.qml'
vui: 'vui.qml'
allowMultiple: true
}
150 changes: 150 additions & 0 deletions src/qml/filters/delogo/ui.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* Copyright (c) 2018 Meltytech, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import QtQuick 2.0
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import Shotcut.Controls 1.0

Item {
// Center the box in the image by default
property double wDefault: profile.width / 5
property double hDefault: profile.height / 5
property double xDefault: profile.width / 2 - wDefault / 2
property double yDefault: profile.height / 2 - hDefault / 2

property var defaultParameters: ["av.x", "av.y", "av.w", "av.h"]

width: 200
height: 125
Component.onCompleted: {
if (filter.isNew) {
filter.set("av.x", xDefault)
filter.set("av.y", yDefault)
filter.set("av.w", wDefault)
filter.set("av.h", hDefault)
filter.savePreset(defaultParameters)
}
setControls()
}

function setControls() {
rectX.text = filter.get("av.x")
rectY.text = filter.get("av.y")
rectW.text = filter.get("av.w")
rectH.text = filter.get("av.h")
}

function setFilter() {
filter.set("av.x", parseInt(rectX.text))
filter.set("av.y", parseInt(rectY.text))
filter.set("av.w", parseInt(rectW.text))
filter.set("av.h", parseInt(rectH.text))
}

GridLayout {
columns: 5
anchors.fill: parent
anchors.margins: 8

Label {
text: qsTr('Preset')
Layout.alignment: Qt.AlignRight
}
Preset {
id: preset
parameters: defaultParameters
Layout.columnSpan: 4
onPresetSelected: setControls()
}

Label {
text: qsTr('Position')
Layout.alignment: Qt.AlignRight
}
RowLayout {
Layout.columnSpan: 4
TextField {
id: rectX
horizontalAlignment: Qt.AlignRight
validator: IntValidator {
bottom: 0
}
onEditingFinished: {
text = Math.min(parseInt(text), profile.width - parseInt(rectW.text) - 1)
text = Math.max(parseInt(text), 1)
if (filter.get("av.x") !== parseInt(text)) setFilter()
}
}
Label { text: ',' }
TextField {
id: rectY
horizontalAlignment: Qt.AlignRight
validator: IntValidator {
bottom: 0
}
onEditingFinished: {
text = Math.min(parseInt(text), profile.height - parseInt(rectH.text) - 1)
text = Math.max(parseInt(text), 1)
if (filter.get("av.y") !== parseInt(text)) setFilter()
}
}
}

Label {
text: qsTr('Size')
Layout.alignment: Qt.AlignRight
}
RowLayout {
Layout.columnSpan: 4
TextField {
id: rectW
horizontalAlignment: Qt.AlignRight
validator: IntValidator {
bottom: 0
}
onEditingFinished: {
text = Math.min(parseInt(text), profile.width - parseInt(rectX.text) - 1)
text = Math.max(parseInt(text), 1)
if (filter.get("av.w") !== parseInt(text)) setFilter()
}
}
Label { text: 'x' }
TextField {
id: rectH
horizontalAlignment: Qt.AlignRight
validator: IntValidator {
bottom: 0
}
onEditingFinished: {
text = Math.min(parseInt(text), profile.height - parseInt(rectY.text) - 1)
text = Math.max(parseInt(text), 1)
if (filter.get("av.h") !== parseInt(text)) setFilter()
}
}
}

Item { Layout.fillHeight: true }
}

Connections {
target: filter
onChanged: {
setControls()
}
}
}
81 changes: 81 additions & 0 deletions src/qml/filters/delogo/vui.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2018 Meltytech, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import QtQuick 2.1
import Shotcut.Controls 1.0

RectVui {
id: rectVui
boundary: Qt.rect(1, 1, profile.width - 2, profile.height - 2)

property bool _blockUpdates: false;

onFilterRectChanged: {
if (_blockUpdates) return

rectVui.filterRect.x = Math.min(rectVui.filterRect.x, profile.width - rectVui.filterRect.width - 1)
rectVui.filterRect.x = Math.max(rectVui.filterRect.x, 1)
rectVui.filterRect.y = Math.min(rectVui.filterRect.y, profile.height - rectVui.filterRect.height - 1)
rectVui.filterRect.y = Math.max(rectVui.filterRect.y, 1)
rectVui.filterRect.width = Math.min(rectVui.filterRect.width, profile.width - rectVui.filterRect.x - 1)
rectVui.filterRect.width = Math.max(rectVui.filterRect.width, 1)
rectVui.filterRect.height = Math.min(rectVui.filterRect.height, profile.width - rectVui.filterRect.y - 1)
rectVui.filterRect.height = Math.max(rectVui.filterRect.height, 1)

if (rectVui.filterRect.x != filter.get("av.x") ||
rectVui.filterRect.y != filter.get("av.y") ||
rectVui.filterRect.width != filter.get("av.w") ||
rectVui.filterRect.height != filter.get("av.h") )
{
_blockUpdates = true
filter.set("av.x", rectVui.filterRect.x)
filter.set("av.y", rectVui.filterRect.y)
filter.set("av.w", rectVui.filterRect.width)
filter.set("av.h", rectVui.filterRect.height)
_blockUpdates = false
}
}

Component.onCompleted: {
if (_blockUpdates) return
if (rectVui.filterRect.x != filter.get("av.x") ||
rectVui.filterRect.y != filter.get("av.y") ||
rectVui.filterRect.width != filter.get("av.w") ||
rectVui.filterRect.height != filter.get("av.h") )
{
_blockUpdates = true
rectVui.filterRect = Qt.rect(filter.get("av.x"), filter.get("av.y"), filter.get("av.w"), filter.get("av.h"))
_blockUpdates = false
}
}

Connections {
target: filter
onChanged: {
if (_blockUpdates) return
if (rectVui.filterRect.x != filter.get("av.x") ||
rectVui.filterRect.y != filter.get("av.y") ||
rectVui.filterRect.width != filter.get("av.w") ||
rectVui.filterRect.height != filter.get("av.h") )
{
_blockUpdates = true
rectVui.filterRect = Qt.rect(filter.get("av.x"), filter.get("av.y"), filter.get("av.w"), filter.get("av.h"))
_blockUpdates = false
}
}
}
}
70 changes: 70 additions & 0 deletions src/qml/modules/Shotcut/Controls/RectVui.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2017-2018 Meltytech, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import QtQuick 2.1
import Shotcut.Controls 1.0

VuiBase {
property rect filterRect
property rect boundary: Qt.rect(-10000, -10000, 20000, 20000)
property real _zoom: (video.zoom > 0)? video.zoom : 1.0

onFilterRectChanged: {
rectangle.setHandles(filterRect)
}

Flickable {
anchors.fill: parent
interactive: false
clip: true
contentWidth: video.rect.width * _zoom
contentHeight: video.rect.height * _zoom
contentX: video.offset.x
contentY: video.offset.y

Item {
id: videoItem
x: video.rect.x
y: video.rect.y
width: video.rect.width
height: video.rect.height
scale: _zoom

RectangleControl {
id: rectangle
widthScale: video.rect.width / profile.width
heightScale: video.rect.height / profile.height
handleSize: Math.max(Math.round(8 / _zoom), 4)
borderSize: Math.max(Math.round(1.33 / _zoom), 1)
onWidthScaleChanged: {
setHandles(filterRect)
setBoundary(boundary)
}
onHeightScaleChanged: {
setHandles(filterRect)
setBoundary(boundary)
}
onRectChanged: {
filterRect = Qt.rect(Math.round(rect.x / rectangle.widthScale),
Math.round(rect.y / rectangle.heightScale),
Math.round(rect.width / rectangle.widthScale),
Math.round(rect.height / rectangle.heightScale))
}
}
}
}
}
Loading