Skip to content

Commit a71e8ca

Browse files
committed
Fix crash after moving clip with filter and undo twice
The trim command was also causing a spurious filter change command which would cause crashing. As reported here: https://forum.shotcut.org/t/crash-after-moving-clip-with-filter/47467
1 parent 88f50b0 commit a71e8ca

8 files changed

+55
-0
lines changed

src/commands/timelinecommands.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,7 @@ TrimClipInCommand::TrimClipInCommand(MultitrackModel &model,
855855

856856
void TrimClipInCommand::redo()
857857
{
858+
MAIN.filterController()->pauseUndoTracking();
858859
if (m_rippleMarkers) {
859860
// Remove and shift markers as appropriate
860861
bool markersModified = false;
@@ -911,16 +912,19 @@ void TrimClipInCommand::redo()
911912
m_undoHelper->recordAfterState();
912913
m_redo = true;
913914
}
915+
MAIN.filterController()->resumeUndoTracking();
914916
}
915917

916918
void TrimClipInCommand::undo()
917919
{
918920
LOG_DEBUG() << "trackIndex" << m_trackIndex << "clipIndex" << m_clipIndex << "delta" << m_delta;
919921
Q_ASSERT(m_undoHelper);
922+
MAIN.filterController()->pauseUndoTracking();
920923
m_undoHelper->undoChanges();
921924
if (m_rippleMarkers && m_markerRemoveStart >= 0) {
922925
m_markersModel.doReplace(m_markers);
923926
}
927+
MAIN.filterController()->resumeUndoTracking();
924928
}
925929

926930
bool TrimClipInCommand::mergeWith(const QUndoCommand *other)
@@ -961,6 +965,7 @@ TrimClipOutCommand::TrimClipOutCommand(MultitrackModel &model,
961965

962966
void TrimClipOutCommand::redo()
963967
{
968+
MAIN.filterController()->pauseUndoTracking();
964969
if (m_rippleMarkers) {
965970
// Remove and shift markers as appropriate
966971
bool markersModified = false;
@@ -1019,16 +1024,19 @@ void TrimClipOutCommand::redo()
10191024
m_undoHelper->recordAfterState();
10201025
m_redo = true;
10211026
}
1027+
MAIN.filterController()->resumeUndoTracking();
10221028
}
10231029

10241030
void TrimClipOutCommand::undo()
10251031
{
10261032
LOG_DEBUG() << "trackIndex" << m_trackIndex << "clipIndex" << m_clipIndex << "delta" << m_delta;
10271033
Q_ASSERT(m_undoHelper);
1034+
MAIN.filterController()->pauseUndoTracking();
10281035
m_undoHelper->undoChanges();
10291036
if (m_rippleMarkers && m_markerRemoveStart >= 0) {
10301037
m_markersModel.doReplace(m_markers);
10311038
}
1039+
MAIN.filterController()->resumeUndoTracking();
10321040
}
10331041

10341042
bool TrimClipOutCommand::mergeWith(const QUndoCommand *other)
@@ -1262,9 +1270,11 @@ TrimTransitionInCommand::TrimTransitionInCommand(MultitrackModel &model,
12621270
void TrimTransitionInCommand::redo()
12631271
{
12641272
if (m_redo) {
1273+
MAIN.filterController()->pauseUndoTracking();
12651274
m_model.trimTransitionIn(m_trackIndex, m_clipIndex, m_delta);
12661275
if (m_notify && m_clipIndex >= 0)
12671276
m_model.notifyClipIn(m_trackIndex, m_clipIndex);
1277+
MAIN.filterController()->resumeUndoTracking();
12681278
} else {
12691279
m_redo = true;
12701280
}
@@ -1274,9 +1284,11 @@ void TrimTransitionInCommand::undo()
12741284
{
12751285
LOG_DEBUG() << "trackIndex" << m_trackIndex << "clipIndex" << m_clipIndex << "delta" << m_delta;
12761286
if (m_clipIndex >= 0) {
1287+
MAIN.filterController()->pauseUndoTracking();
12771288
m_model.trimTransitionIn(m_trackIndex, m_clipIndex, -m_delta);
12781289
m_model.notifyClipIn(m_trackIndex, m_clipIndex);
12791290
m_notify = true;
1291+
MAIN.filterController()->resumeUndoTracking();
12801292
} else
12811293
LOG_WARNING() << "invalid clip index" << m_clipIndex;
12821294
}
@@ -1311,9 +1323,11 @@ void TrimTransitionOutCommand::redo()
13111323
{
13121324
if (m_redo) {
13131325
LOG_DEBUG() << "trackIndex" << m_trackIndex << "clipIndex" << m_clipIndex;
1326+
MAIN.filterController()->pauseUndoTracking();
13141327
m_model.trimTransitionOut(m_trackIndex, m_clipIndex, m_delta);
13151328
if (m_notify && m_clipIndex >= 0)
13161329
m_model.notifyClipOut(m_trackIndex, m_clipIndex);
1330+
MAIN.filterController()->resumeUndoTracking();
13171331
} else {
13181332
m_redo = true;
13191333
}
@@ -1324,9 +1338,11 @@ void TrimTransitionOutCommand::undo()
13241338
if (m_clipIndex >= 0) {
13251339
LOG_DEBUG() << "trackIndex" << m_trackIndex << "clipIndex" << m_clipIndex << "delta"
13261340
<< m_delta;
1341+
MAIN.filterController()->pauseUndoTracking();
13271342
m_model.trimTransitionOut(m_trackIndex, m_clipIndex, -m_delta);
13281343
m_model.notifyClipOut(m_trackIndex, m_clipIndex);
13291344
m_notify = true;
1345+
MAIN.filterController()->resumeUndoTracking();
13301346
} else
13311347
LOG_WARNING() << "invalid clip index" << m_clipIndex;
13321348
}

src/controllers/filtercontroller.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,20 @@ void FilterController::onProducerChanged()
363363
emit m_attachedModel.trackTitleChanged();
364364
}
365365

366+
void FilterController::pauseUndoTracking()
367+
{
368+
if (m_currentFilter && !m_attachedModel.isSourceClip()) {
369+
m_currentFilter->stopUndoTracking();
370+
}
371+
}
372+
373+
void FilterController::resumeUndoTracking()
374+
{
375+
if (m_currentFilter && !m_attachedModel.isSourceClip()) {
376+
m_currentFilter->startUndoTracking();
377+
}
378+
}
379+
366380
void FilterController::addMetadata(QmlMetadata *meta)
367381
{
368382
m_metadataModel.add(meta);

src/controllers/filtercontroller.h

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ public slots:
6666
void onServiceOutChanged(int delta, Mlt::Service *service = 0);
6767
void removeCurrent();
6868
void onProducerChanged();
69+
void pauseUndoTracking();
70+
void resumeUndoTracking();
6971

7072
private slots:
7173
void handleAttachedModelChange();

src/docks/timelinedock.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -2685,6 +2685,7 @@ void TimelineDock::commitTrimCommand()
26852685
}
26862686
m_trimDelta = 0;
26872687
m_transitionDelta = 0;
2688+
emit trimEnded();
26882689
}
26892690

26902691
void TimelineDock::onRowsInserted(const QModelIndex &parent, int first, int last)
@@ -3202,6 +3203,7 @@ void TimelineDock::onClipMoved(int fromTrack, int toTrack, int clipIndex, int po
32023203

32033204
bool TimelineDock::trimClipIn(int trackIndex, int clipIndex, int oldClipIndex, int delta, bool ripple)
32043205
{
3206+
emit trimStarted();
32053207
if (dynamic_cast<Timeline::RemoveTransitionByTrimInCommand *>(m_trimCommand.get())) {
32063208
if (delta < 0) {
32073209
// Do not trim past the removed tansition
@@ -3292,6 +3294,7 @@ bool TimelineDock::trimClipIn(int trackIndex, int clipIndex, int oldClipIndex, i
32923294

32933295
bool TimelineDock::trimClipOut(int trackIndex, int clipIndex, int delta, bool ripple)
32943296
{
3297+
emit trimStarted();
32953298
if (dynamic_cast<Timeline::RemoveTransitionByTrimOutCommand *>(m_trimCommand.get())) {
32963299
if (delta < 0) {
32973300
// Do not trim past the removed tansition

src/docks/timelinedock.h

+2
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ class TimelineDock : public QDockWidget
128128
void warnTrackLocked(int trackIndex);
129129
void refreshWaveforms();
130130
void updateThumbnails(int trackIndex, int clipIndex);
131+
void trimStarted();
132+
void trimEnded();
131133

132134
public slots:
133135
int addAudioTrack();

src/mainwindow.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,14 @@ void MainWindow::setupAndConnectDocks()
666666
m_filterController->motionTrackerModel(),
667667
&MotionTrackerModel::removeFromService);
668668
connect(this, SIGNAL(audioChannelsChanged()), m_filterController, SLOT(setProducer()));
669+
connect(m_timelineDock,
670+
&TimelineDock::trimStarted,
671+
m_filterController,
672+
&FilterController::pauseUndoTracking);
673+
connect(m_timelineDock,
674+
&TimelineDock::trimEnded,
675+
m_filterController,
676+
&FilterController::resumeUndoTracking);
669677

670678
m_markersDock = new MarkersDock(this);
671679
m_markersDock->hide();

src/qmltypes/qmlfilter.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,15 @@ void QmlFilter::startUndoTracking()
801801
}
802802
}
803803

804+
void QmlFilter::stopUndoTracking()
805+
{
806+
if (!m_previousState.count()) {
807+
LOG_DEBUG() << "Undo tracking has not started yet";
808+
return;
809+
}
810+
m_previousState = Mlt::Properties();
811+
}
812+
804813
void QmlFilter::startUndoParameterCommand(const QString &desc)
805814
{
806815
if (!m_previousState.count()) {

src/qmltypes/qmlfilter.h

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ class QmlFilter : public QObject
141141

142142
// Functions for undo/redo
143143
void startUndoTracking();
144+
void stopUndoTracking();
144145
Q_INVOKABLE void startUndoParameterCommand(const QString &desc = QString());
145146
void startUndoAddKeyframeCommand();
146147
void startUndoRemoveKeyframeCommand();

0 commit comments

Comments
 (0)