Skip to content

Commit 9fe89e2

Browse files
committed
Fix Pasting filters does not create history
As reported here: https://forum.shotcut.org/t/pasting-filters-does-not-create-history/47308
1 parent 0647112 commit 9fe89e2

9 files changed

+80
-26
lines changed

src/commands/filtercommands.cpp

+50
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "controllers/filtercontroller.h"
2222
#include "mainwindow.h"
2323
#include "mltcontroller.h"
24+
#include "qmltypes/qmlapplication.h"
2425
#include "qmltypes/qmlmetadata.h"
2526

2627
class FindProducerParser : public Mlt::Parser
@@ -291,6 +292,55 @@ bool DisableCommand::mergeWith(const QUndoCommand *other)
291292
*/
292293
}
293294

295+
PasteCommand::PasteCommand(AttachedFiltersModel &model,
296+
const QString &filterProducerXml,
297+
QUndoCommand *parent)
298+
: QUndoCommand(parent)
299+
, m_model(model)
300+
, m_xml(filterProducerXml)
301+
, m_producerUuid(MLT.ensureHasUuid(*model.producer()))
302+
{
303+
setText(QObject::tr("Paste filters"));
304+
m_beforeXml = MLT.XML(model.producer());
305+
}
306+
307+
void PasteCommand::redo()
308+
{
309+
LOG_DEBUG() << text();
310+
Mlt::Producer producer = findProducer(m_producerUuid);
311+
Q_ASSERT(producer.is_valid());
312+
Mlt::Profile profile(kDefaultMltProfile);
313+
Mlt::Producer filtersProducer(profile, "xml-string", m_xml.toUtf8().constData());
314+
if (filtersProducer.is_valid() && filtersProducer.filter_count() > 0) {
315+
MLT.pasteFilters(&producer, &filtersProducer);
316+
}
317+
emit QmlApplication::singleton().filtersPasted(&producer);
318+
}
319+
320+
void PasteCommand::undo()
321+
{
322+
LOG_DEBUG() << text();
323+
Mlt::Producer producer = findProducer(m_producerUuid);
324+
Q_ASSERT(producer.is_valid());
325+
// Remove all filters
326+
for (int i = 0; i < producer.filter_count(); i++) {
327+
Mlt::Filter *filter = producer.filter(i);
328+
if (filter && filter->is_valid() && !filter->get_int("_loader")
329+
&& !filter->get_int(kShotcutHiddenProperty)) {
330+
producer.detach(*filter);
331+
i--;
332+
}
333+
delete filter;
334+
}
335+
// Restore the "before" filters
336+
Mlt::Profile profile(kDefaultMltProfile);
337+
Mlt::Producer filtersProducer(profile, "xml-string", m_beforeXml.toUtf8().constData());
338+
if (filtersProducer.is_valid() && filtersProducer.filter_count() > 0) {
339+
MLT.pasteFilters(&producer, &filtersProducer);
340+
}
341+
emit QmlApplication::singleton().filtersPasted(&producer);
342+
}
343+
294344
UndoParameterCommand::UndoParameterCommand(const QString &name,
295345
FilterController *controller,
296346
int row,

src/commands/filtercommands.h

+16
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,22 @@ class DisableCommand : public QUndoCommand
136136
bool m_disabled;
137137
};
138138

139+
class PasteCommand : public QUndoCommand
140+
{
141+
public:
142+
PasteCommand(AttachedFiltersModel &model,
143+
const QString &filterProducerXml,
144+
QUndoCommand *parent = 0);
145+
void redo();
146+
void undo();
147+
148+
private:
149+
AttachedFiltersModel &m_model;
150+
QString m_xml;
151+
QString m_beforeXml;
152+
QUuid m_producerUuid;
153+
};
154+
139155
class UndoParameterCommand : public QUndoCommand
140156
{
141157
public:

src/docks/filtersdock.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ void FiltersDock::setupActions()
264264
icon = QIcon::fromTheme("edit-paste", QIcon(":/icons/oxygen/32x32/actions/edit-paste.png"));
265265
action->setIcon(icon);
266266
connect(action, &QAction::triggered, this, [=]() {
267-
QmlApplication::singleton().pasteFilters();
267+
MAIN.filterController()->attachedModel()->pasteFilters();
268268
});
269269
addAction(action);
270270
Actions.add("filtersPasteFiltersAction", action, windowTitle());

src/mainwindow.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -3480,6 +3480,7 @@ void MainWindow::onProducerModified()
34803480
{
34813481
setWindowModified(true);
34823482
sourceUpdated();
3483+
MLT.refreshConsumer();
34833484
}
34843485

34853486
void MainWindow::onFilterModelChanged()

src/models/attachedfiltersmodel.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,16 @@ bool AttachedFiltersModel::move(int fromRow, int toRow)
739739
return moveRows(parent, fromRow, 1, parent, toRow);
740740
}
741741

742+
void AttachedFiltersModel::pasteFilters()
743+
{
744+
if (m_producer && QmlApplication::confirmOutputFilter()) {
745+
QString s = QGuiApplication::clipboard()->text();
746+
if (MLT.isMltXml(s)) {
747+
MAIN.undoStack()->push(new Filter::PasteCommand(*this, s));
748+
}
749+
}
750+
}
751+
742752
void AttachedFiltersModel::reset(Mlt::Producer *producer)
743753
{
744754
beginResetModel();

src/models/attachedfiltersmodel.h

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public slots:
8585
int addService(Mlt::Service *service);
8686
void remove(int row);
8787
bool move(int fromRow, int toRow);
88+
void pasteFilters();
8889

8990
private:
9091
static void producerChanged(mlt_properties owner, AttachedFiltersModel *model);

src/qml/views/filter/filterview.qml

+1-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ Rectangle {
241241
opacity: enabled ? 1 : 0.5
242242
icon.name: 'edit-paste'
243243
icon.source: 'qrc:///icons/oxygen/32x32/actions/edit-paste.png'
244-
onClicked: application.pasteFilters()
244+
onClicked: attachedfiltersmodel.pasteFilters()
245245

246246
Shotcut.HoverTip {
247247
text: qsTr('Paste filters')

src/qmltypes/qmlapplication.cpp

-23
Original file line numberDiff line numberDiff line change
@@ -140,29 +140,6 @@ void QmlApplication::copyCurrentFilter()
140140
emit QmlApplication::singleton().filtersCopied();
141141
}
142142

143-
void QmlApplication::pasteFilters()
144-
{
145-
QScopedPointer<Mlt::Producer> producer(
146-
new Mlt::Producer(MAIN.filterController()->attachedModel()->producer()));
147-
if (confirmOutputFilter()) {
148-
QString s = QGuiApplication::clipboard()->text();
149-
if (MLT.isMltXml(s)) {
150-
Mlt::Profile profile(kDefaultMltProfile);
151-
Mlt::Producer filtersProducer(profile, "xml-string", s.toUtf8().constData());
152-
if (filtersProducer.is_valid() && filtersProducer.filter_count() > 0
153-
&& filtersProducer.get_int(kShotcutFiltersClipboard)) {
154-
MLT.pasteFilters(producer.get(), &filtersProducer);
155-
} else {
156-
MLT.pasteFilters(producer.data());
157-
}
158-
} else {
159-
MLT.pasteFilters(producer.data());
160-
}
161-
emit QmlApplication::singleton().filtersPasted(
162-
MAIN.filterController()->attachedModel()->producer());
163-
}
164-
}
165-
166143
QString QmlApplication::clockFromFrames(int frames)
167144
{
168145
if (MLT.producer()) {

src/qmltypes/qmlapplication.h

-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ class QmlApplication : public QObject
5454
Q_INVOKABLE static void copyAllFilters();
5555
Q_INVOKABLE static void copyEnabledFilters();
5656
Q_INVOKABLE static void copyCurrentFilter();
57-
Q_INVOKABLE static void pasteFilters();
5857
Q_INVOKABLE static QString clockFromFrames(int frames);
5958
Q_INVOKABLE static QString timeFromFrames(int frames);
6059
Q_INVOKABLE static int audioChannels();

0 commit comments

Comments
 (0)