Skip to content

Commit a788aef

Browse files
committed
Add "Copy Current Filter" action
As suggested here: https://forum.shotcut.org/t/copy-single-filters/13909
1 parent 6b7de9b commit a788aef

10 files changed

Lines changed: 67 additions & 8 deletions

File tree

icons/dark/32x32/edit-select.png

458 Bytes
Loading

icons/light/32x32/edit-select.png

206 Bytes
Loading
991 Bytes
Loading

icons/resources.qrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,12 @@
227227
<file>oxygen/32x32/actions/edit-copy.png</file>
228228
<file>oxygen/32x32/actions/edit-cut.png</file>
229229
<file>oxygen/32x32/actions/edit-paste.png</file>
230+
<file>oxygen/32x32/actions/edit-select.png</file>
230231
<file>oxygen/32x32/actions/edit-select-all.png</file>
231232
<file>light/32x32/edit-copy.png</file>
232233
<file>light/32x32/edit-cut.png</file>
233234
<file>light/32x32/edit-paste.png</file>
235+
<file>light/32x32/edit-select.png</file>
234236
<file>light/32x32/edit-select-all.png</file>
235237
<file>oxygen/32x32/actions/format-indent-less.png</file>
236238
<file>oxygen/32x32/actions/format-indent-more.png</file>
@@ -267,6 +269,7 @@
267269
<file>dark/32x32/edit-copy.png</file>
268270
<file>dark/32x32/edit-cut.png</file>
269271
<file>dark/32x32/edit-paste.png</file>
272+
<file>dark/32x32/edit-select.png</file>
270273
<file>dark/32x32/edit-select-all.png</file>
271274
<file>dark/32x32/format-indent-less.png</file>
272275
<file>dark/32x32/format-indent-more.png</file>

src/docks/filtersdock.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,17 @@ void FiltersDock::setupActions()
228228
addAction(action);
229229
Actions.add("filtersCopyFiltersAction", action, windowTitle());
230230

231+
action = new QAction(tr("Copy Current Filter"), this);
232+
action->setToolTip(tr("Copy current filter to the clipboard"));
233+
icon = QIcon::fromTheme("edit-copy",
234+
QIcon(":/icons/oxygen/32x32/actions/edit-select.png"));
235+
action->setIcon(icon);
236+
connect(action, &QAction::triggered, this, [ = ]() {
237+
QmlApplication::singleton().copyCurrentFilter();
238+
});
239+
addAction(action);
240+
Actions.add("filtersCopyCurrentFilterAction", action, windowTitle());
241+
231242
action = new QAction(tr("Paste Filters"), this);
232243
action->setToolTip(tr("Paste the filters from the clipboard"));
233244
icon = QIcon::fromTheme("edit-paste",

src/mltcontroller.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,13 +1117,14 @@ static int indexOfFirstNonGpu(Producer &toProducer)
11171117
}
11181118

11191119
void Controller::copyFilters(Producer &fromProducer, Producer &toProducer, bool fromClipboard,
1120-
bool includeDisabled)
1120+
bool includeDisabled, int filterIndex)
11211121
{
11221122
int in = fromProducer.get(kFilterInProperty) ? fromProducer.get_int(kFilterInProperty) :
11231123
fromProducer.get_in();
11241124
int out = fromProducer.get(kFilterOutProperty) ? fromProducer.get_int(
11251125
kFilterOutProperty) : fromProducer.get_out();
11261126
int count = fromProducer.filter_count();
1127+
int filterCount = 0;
11271128

11281129
// Get the index of the first non-GPU filter or link in toProducer
11291130
int firstNonGpuService = fromClipboard ? indexOfFirstNonGpu(toProducer) : -1;
@@ -1132,8 +1133,16 @@ void Controller::copyFilters(Producer &fromProducer, Producer &toProducer, bool
11321133
QScopedPointer<Mlt::Filter> fromFilter(fromProducer.filter(i));
11331134
if (fromFilter && fromFilter->is_valid() && !fromFilter->get_int("_loader")
11341135
&& !fromFilter->get_int(kShotcutHiddenProperty)
1135-
&& fromFilter->get("mlt_service")
1136-
&& (includeDisabled || !fromFilter->get_int("disable"))) {
1136+
&& fromFilter->get("mlt_service")) {
1137+
1138+
filterCount++;
1139+
if (filterIndex != -1 && filterIndex != (filterCount - 1)) {
1140+
continue;
1141+
}
1142+
1143+
if (!includeDisabled && fromFilter->get_int("disable")) {
1144+
continue;
1145+
}
11371146

11381147
// Determine if filter can be added
11391148
auto metadata = MAIN.filterController()->metadataForService(fromFilter.data());
@@ -1177,6 +1186,10 @@ void Controller::copyFilters(Producer &fromProducer, Producer &toProducer, bool
11771186
QScopedPointer<Mlt::Link> fromLink(fromChain.link(i));
11781187
if (fromLink && fromLink->is_valid() && fromLink->get("mlt_service")
11791188
&& !fromLink->get_int("_loader")) {
1189+
filterCount++;
1190+
if (filterIndex != -1 && filterIndex != (filterCount - 1)) {
1191+
continue;
1192+
}
11801193
Mlt::Link toLink(fromLink->get("mlt_service"));
11811194
if (toLink.is_valid()) {
11821195
toLink.inherit(*fromLink);
@@ -1190,14 +1203,15 @@ void Controller::copyFilters(Producer &fromProducer, Producer &toProducer, bool
11901203
}
11911204
}
11921205

1193-
void Controller::copyFilters(Mlt::Producer *producer)
1206+
void Controller::copyFilters(Mlt::Producer *producer, int filterIndex)
11941207
{
1208+
bool includeDisabled = filterIndex >= 0;
11951209
if (producer && producer->is_valid()) {
11961210
initFiltersClipboard();
1197-
copyFilters(*producer, *m_filtersClipboard, false, false);
1211+
copyFilters(*producer, *m_filtersClipboard, false, includeDisabled, filterIndex);
11981212
} else if (m_producer && m_producer->is_valid()) {
11991213
initFiltersClipboard();
1200-
copyFilters(*m_producer, *m_filtersClipboard, false, false);
1214+
copyFilters(*m_producer, *m_filtersClipboard, false, includeDisabled, filterIndex);
12011215
}
12021216
}
12031217

src/mltcontroller.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,9 @@ class Controller
130130
void setUuid(Mlt::Properties &properties, QUuid uid) const;
131131
QUuid ensureHasUuid(Mlt::Properties &properties) const;
132132
static void copyFilters(Mlt::Producer &fromProducer, Mlt::Producer &toProducer,
133-
bool fromClipboard = false, bool includeDisabled = true);
134-
void copyFilters(Mlt::Producer *producer = nullptr);
133+
bool fromClipboard = false, bool includeDisabled = true,
134+
int filterIndex = -1);
135+
void copyFilters(Mlt::Producer *producer = nullptr, int filterIndex = -1);
135136
void pasteFilters(Mlt::Producer *producer = nullptr, Mlt::Producer *fromProducer = nullptr);
136137
static void adjustFilters(Mlt::Producer &producer, int startIndex = 0);
137138
static void adjustFilter(Mlt::Filter *filter, int in, int out, int inDelta, int outDelta,

src/qml/views/filter/filterview.qml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,21 @@ Rectangle {
232232
}
233233
}
234234

235+
Shotcut.Button {
236+
id: copySelectedButton
237+
238+
implicitWidth: height
239+
icon.name: 'edit-select'
240+
icon.source: 'qrc:///icons/oxygen/32x32/actions/edit-select.png'
241+
enabled: selectedIndex > Shotcut.Filter.NoCurrentFilter
242+
opacity: enabled ? 1 : 0.5
243+
onClicked: application.copyCurrentFilter()
244+
245+
Shotcut.HoverTip {
246+
text: qsTr('Copy current filter')
247+
}
248+
}
249+
235250
Shotcut.Button {
236251
id: pasteButton
237252

src/qmltypes/qmlapplication.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,20 @@ void QmlApplication::copyFilters()
116116
emit QmlApplication::singleton().filtersCopied();
117117
}
118118

119+
void QmlApplication::copyCurrentFilter()
120+
{
121+
int currentIndex = MAIN.filterController()->currentIndex();
122+
if (currentIndex < 0) {
123+
MAIN.showStatusMessage(tr("Select a filter to copy"));
124+
return;
125+
}
126+
QScopedPointer<Mlt::Producer> producer(new Mlt::Producer(
127+
MAIN.filterController()->attachedModel()->producer()));
128+
MLT.copyFilters(producer.data(), currentIndex);
129+
QGuiApplication::clipboard()->setText(MLT.filtersClipboardXML());
130+
emit QmlApplication::singleton().filtersCopied();
131+
}
132+
119133
void QmlApplication::pasteFilters()
120134
{
121135
QScopedPointer<Mlt::Producer> producer(new Mlt::Producer(

src/qmltypes/qmlapplication.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class QmlApplication : public QObject
5252
static QRect mainWinRect();
5353
static bool hasFiltersOnClipboard();
5454
Q_INVOKABLE static void copyFilters();
55+
Q_INVOKABLE static void copyCurrentFilter();
5556
Q_INVOKABLE static void pasteFilters();
5657
Q_INVOKABLE static QString clockFromFrames(int frames);
5758
Q_INVOKABLE static QString timeFromFrames(int frames);

0 commit comments

Comments
 (0)