CuteLogger
Fast and simple logging solution for Qt based applications
timelinecommands.h
1 /*
2  * Copyright (c) 2013-2024 Meltytech, LLC
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef COMMANDS_H
19 #define COMMANDS_H
20 
21 #include "models/multitrackmodel.h"
22 #include "models/markersmodel.h"
23 #include "docks/timelinedock.h"
24 #include "undohelper.h"
25 #include <QUndoCommand>
26 #include <QString>
27 #include <QObject>
28 #include <QUuid>
29 #include <MltTransition.h>
30 #include <MltProducer.h>
31 
32 #include <vector>
33 
34 namespace Timeline {
35 
36 enum {
37  UndoIdTrimClipIn = 100,
38  UndoIdTrimClipOut,
39  UndoIdFadeIn,
40  UndoIdFadeOut,
41  UndoIdTrimTransitionIn,
42  UndoIdTrimTransitionOut,
43  UndoIdAddTransitionByTrimIn,
44  UndoIdAddTransitionByTrimOut,
45  UndoIdUpdate,
46  UndoIdMoveClip
47 };
48 
49 struct ClipPosition {
50  ClipPosition(int track, int clip)
51  {
52  trackIndex = track;
53  clipIndex = clip;
54  }
55 
56  bool operator < (const ClipPosition &rhs) const
57  {
58  if (trackIndex == rhs.trackIndex) {
59  return clipIndex < rhs.clipIndex;
60  } else {
61  return trackIndex < rhs.trackIndex;
62  }
63  }
64 
65  int trackIndex;
66  int clipIndex;
67 };
68 
69 class AppendCommand : public QUndoCommand
70 {
71 public:
72  AppendCommand(MultitrackModel &model, int trackIndex, const QString &xml, bool skipProxy = false,
73  bool seek = true, QUndoCommand *parent = 0);
74  void redo();
75  void undo();
76 private:
77  MultitrackModel &m_model;
78  int m_trackIndex;
79  QString m_xml;
80  UndoHelper m_undoHelper;
81  bool m_skipProxy;
82  bool m_seek;
83 };
84 
85 class InsertCommand : public QUndoCommand
86 {
87 public:
88  InsertCommand(MultitrackModel &model, MarkersModel &markersModel, int trackIndex, int position,
89  const QString &xml, bool seek = true, QUndoCommand *parent = 0);
90  void redo();
91  void undo();
92 private:
93  MultitrackModel &m_model;
94  MarkersModel &m_markersModel;
95  int m_trackIndex;
96  int m_position;
97  QString m_xml;
98  QStringList m_oldTracks;
99  UndoHelper m_undoHelper;
100  bool m_seek;
101  bool m_rippleAllTracks;
102  bool m_rippleMarkers;
103  int m_markersShift;
104 };
105 
106 class OverwriteCommand : public QUndoCommand
107 {
108 public:
109  OverwriteCommand(MultitrackModel &model, int trackIndex, int position, const QString &xml,
110  bool seek = true, QUndoCommand *parent = 0);
111  void redo();
112  void undo();
113 private:
114  MultitrackModel &m_model;
115  int m_trackIndex;
116  int m_position;
117  QString m_xml;
118  UndoHelper m_undoHelper;
119  bool m_seek;
120 };
121 
122 class LiftCommand : public QUndoCommand
123 {
124 public:
125  LiftCommand(MultitrackModel &model, int trackIndex, int clipIndex, QUndoCommand *parent = 0);
126  void redo();
127  void undo();
128 private:
129  MultitrackModel &m_model;
130  int m_trackIndex;
131  int m_clipIndex;
132  UndoHelper m_undoHelper;
133 };
134 
135 class RemoveCommand : public QUndoCommand
136 {
137 public:
138  RemoveCommand(MultitrackModel &model, MarkersModel &markersModel, int trackIndex, int clipIndex,
139  QUndoCommand *parent = 0);
140  void redo();
141  void undo();
142 private:
143  MultitrackModel &m_model;
144  MarkersModel &m_markersModel;
145  int m_trackIndex;
146  int m_clipIndex;
147  UndoHelper m_undoHelper;
148  bool m_rippleAllTracks;
149  bool m_rippleMarkers;
150  int m_markerRemoveStart;
151  int m_markerRemoveEnd;
152  QList<Markers::Marker> m_markers;
153 };
154 
155 class GroupCommand : public QUndoCommand
156 {
157 public:
158  GroupCommand(MultitrackModel &model, QUndoCommand *parent = 0);
159  void addToGroup(int trackIndex, int clipIndex);
160  void redo();
161  void undo();
162 private:
163  MultitrackModel &m_model;
164  QList<ClipPosition> m_clips;
165  QMap<ClipPosition, int> m_prevGroups;
166 };
167 
168 class UngroupCommand : public QUndoCommand
169 {
170 public:
171  UngroupCommand(MultitrackModel &model, QUndoCommand *parent = 0);
172  void removeFromGroup(int trackIndex, int clipIndex);
173  void redo();
174  void undo();
175 private:
176  MultitrackModel &m_model;
177  QMap<ClipPosition, int> m_prevGroups;
178 };
179 
180 class NameTrackCommand : public QUndoCommand
181 {
182 public:
183  NameTrackCommand(MultitrackModel &model, int trackIndex, const QString &name,
184  QUndoCommand *parent = 0);
185  void redo();
186  void undo();
187 private:
188  MultitrackModel &m_model;
189  int m_trackIndex;
190  QString m_name;
191  QString m_oldName;
192 };
193 
194 class MergeCommand : public QUndoCommand
195 {
196 public:
197  MergeCommand(MultitrackModel &model, int trackIndex, int clipIndex, QUndoCommand *parent = 0);
198  void redo();
199  void undo();
200 private:
201  MultitrackModel &m_model;
202  int m_trackIndex;
203  int m_clipIndex;
204  UndoHelper m_undoHelper;
205 };
206 
207 class MuteTrackCommand : public QUndoCommand
208 {
209 public:
210  MuteTrackCommand(MultitrackModel &model, int trackIndex, QUndoCommand *parent = 0);
211  void redo();
212  void undo();
213 private:
214  MultitrackModel &m_model;
215  int m_trackIndex;
216  bool m_oldValue;
217 };
218 
219 class HideTrackCommand : public QUndoCommand
220 {
221 public:
222  HideTrackCommand(MultitrackModel &model, int trackIndex, QUndoCommand *parent = 0);
223  void redo();
224  void undo();
225 private:
226  MultitrackModel &m_model;
227  int m_trackIndex;
228  bool m_oldValue;
229 };
230 
231 class CompositeTrackCommand : public QUndoCommand
232 {
233 public:
234  CompositeTrackCommand(MultitrackModel &model, int trackIndex, bool value, QUndoCommand *parent = 0);
235  void redo();
236  void undo();
237 private:
238  MultitrackModel &m_model;
239  int m_trackIndex;
240  bool m_value;
241  bool m_oldValue;
242 };
243 
244 class LockTrackCommand : public QUndoCommand
245 {
246 public:
247  LockTrackCommand(MultitrackModel &model, int trackIndex, bool value, QUndoCommand *parent = 0);
248  void redo();
249  void undo();
250 private:
251  MultitrackModel &m_model;
252  int m_trackIndex;
253  bool m_value;
254  bool m_oldValue;
255 };
256 
257 class MoveClipCommand : public QUndoCommand
258 {
259 public:
260  MoveClipCommand(TimelineDock &timeline, int trackDelta, int positionDelta, bool ripple,
261  QUndoCommand *parent = 0);
262  void addClip(int trackIndex, int clipIndex);
263  void redo();
264  void undo();
265 protected:
266  int id() const
267  {
268  return UndoIdMoveClip;
269  }
270  bool mergeWith(const QUndoCommand *other);
271 private:
272  void redoMarkers();
273 
274  TimelineDock &m_timeline;
275  MultitrackModel &m_model;
276  MarkersModel &m_markersModel;
277 
278  struct Info {
279  int trackIndex;
280  int clipIndex;
281  int frame_in;
282  int frame_out;
283  int start;
284  int group;
285  QUuid uuid;
286 
287  Info()
288  : trackIndex(-1)
289  , clipIndex(-1)
290  , frame_in(-1)
291  , frame_out(-1)
292  , start(0)
293  , group(-1)
294  {}
295  };
296 
297  int m_trackDelta;
298  int m_positionDelta;
299  bool m_ripple;
300  bool m_rippleAllTracks;
301  bool m_rippleMarkers;
302  UndoHelper m_undoHelper;
303  QMultiMap<int, Info> m_clips; // ordered by position
304  bool m_redo;
305  int m_earliestStart;
306  QList<Markers::Marker> m_markers;
307 };
308 
309 class TrimCommand : public QUndoCommand
310 {
311 public:
312  explicit TrimCommand(QUndoCommand *parent = 0) : QUndoCommand(parent) {}
313  void setUndoHelper(UndoHelper *helper)
314  {
315  m_undoHelper.reset(helper);
316  }
317 
318 protected:
319  QScopedPointer<UndoHelper> m_undoHelper;
320 };
321 
322 class TrimClipInCommand : public TrimCommand
323 {
324 public:
325  TrimClipInCommand(MultitrackModel &model, MarkersModel &markersModel, int trackIndex, int clipIndex,
326  int delta, bool ripple, bool redo = true, QUndoCommand *parent = 0);
327  void redo();
328  void undo();
329 protected:
330  int id() const
331  {
332  return UndoIdTrimClipIn;
333  }
334  bool mergeWith(const QUndoCommand *other);
335 private:
336  MultitrackModel &m_model;
337  MarkersModel &m_markersModel;
338  int m_trackIndex;
339  int m_clipIndex;
340  int m_delta;
341  bool m_ripple;
342  bool m_rippleAllTracks;
343  bool m_rippleMarkers;
344  bool m_redo;
345  int m_markerRemoveStart;
346  int m_markerRemoveEnd;
347  QList<Markers::Marker> m_markers;
348 };
349 
350 class TrimClipOutCommand : public TrimCommand
351 {
352 public:
353  TrimClipOutCommand(MultitrackModel &model, MarkersModel &markersModel, int trackIndex,
354  int clipIndex, int delta, bool ripple, bool redo = true, QUndoCommand *parent = 0);
355  void redo();
356  void undo();
357 protected:
358  int id() const
359  {
360  return UndoIdTrimClipOut;
361  }
362  bool mergeWith(const QUndoCommand *other);
363 private:
364  MultitrackModel &m_model;
365  MarkersModel &m_markersModel;
366  int m_trackIndex;
367  int m_clipIndex;
368  int m_delta;
369  bool m_ripple;
370  bool m_rippleAllTracks;
371  bool m_rippleMarkers;
372  bool m_redo;
373  int m_markerRemoveStart;
374  int m_markerRemoveEnd;
375  QList<Markers::Marker> m_markers;
376 };
377 
378 class SplitCommand : public QUndoCommand
379 {
380 public:
381  SplitCommand(MultitrackModel &model, const std::vector<int> &trackIndex,
382  const std::vector<int> &clipIndex,
383  int position,
384  QUndoCommand *parent = 0);
385  void redo();
386  void undo();
387 private:
388  MultitrackModel &m_model;
389  std::vector<int> m_trackIndex;
390  std::vector<int> m_clipIndex;
391  int m_position;
392  UndoHelper m_undoHelper;
393 };
394 
395 class FadeInCommand : public QUndoCommand
396 {
397 public:
398  FadeInCommand(MultitrackModel &model, int trackIndex, int clipIndex, int duration,
399  QUndoCommand *parent = 0);
400  void redo();
401  void undo();
402 protected:
403  int id() const
404  {
405  return UndoIdFadeIn;
406  }
407  bool mergeWith(const QUndoCommand *other);
408 private:
409  MultitrackModel &m_model;
410  int m_trackIndex;
411  int m_clipIndex;
412  int m_duration;
413  int m_previous;
414 };
415 
416 class FadeOutCommand : public QUndoCommand
417 {
418 public:
419  FadeOutCommand(MultitrackModel &model, int trackIndex, int clipIndex, int duration,
420  QUndoCommand *parent = 0);
421  void redo();
422  void undo();
423 protected:
424  int id() const
425  {
426  return UndoIdFadeOut;
427  }
428  bool mergeWith(const QUndoCommand *other);
429 private:
430  MultitrackModel &m_model;
431  int m_trackIndex;
432  int m_clipIndex;
433  int m_duration;
434  int m_previous;
435 };
436 
437 class AddTransitionCommand : public QUndoCommand
438 {
439 public:
440  AddTransitionCommand(TimelineDock &timeline, int trackIndex, int clipIndex, int position,
441  bool ripple, QUndoCommand *parent = 0);
442  void redo();
443  void undo();
444  int getTransitionIndex() const
445  {
446  return m_transitionIndex;
447  }
448 private:
449  TimelineDock &m_timeline;
450  MultitrackModel &m_model;
451  MarkersModel &m_markersModel;
452  int m_trackIndex;
453  int m_clipIndex;
454  int m_position;
455  int m_transitionIndex;
456  bool m_ripple;
457  UndoHelper m_undoHelper;
458  bool m_rippleAllTracks;
459  bool m_rippleMarkers;
460  int m_markerOldStart;
461  int m_markerNewStart;
462  QList<Markers::Marker> m_markers;
463 };
464 
465 class TrimTransitionInCommand : public TrimCommand
466 {
467 public:
468  TrimTransitionInCommand(MultitrackModel &model, int trackIndex, int clipIndex, int delta,
469  bool redo = true, QUndoCommand *parent = 0);
470  void redo();
471  void undo();
472 protected:
473  int id() const
474  {
475  return UndoIdTrimTransitionIn;
476  }
477  bool mergeWith(const QUndoCommand *other);
478 private:
479  MultitrackModel &m_model;
480  int m_trackIndex;
481  int m_clipIndex;
482  int m_delta;
483  bool m_notify;
484  bool m_redo;
485 };
486 
487 class TrimTransitionOutCommand : public TrimCommand
488 {
489 public:
490  TrimTransitionOutCommand(MultitrackModel &model, int trackIndex, int clipIndex, int delta,
491  bool redo = true, QUndoCommand *parent = 0);
492  void redo();
493  void undo();
494 protected:
495  int id() const
496  {
497  return UndoIdTrimTransitionOut;
498  }
499  bool mergeWith(const QUndoCommand *other);
500 private:
501  MultitrackModel &m_model;
502  int m_trackIndex;
503  int m_clipIndex;
504  int m_delta;
505  bool m_notify;
506  bool m_redo;
507 };
508 
509 class AddTransitionByTrimInCommand : public TrimCommand
510 {
511 public:
512  AddTransitionByTrimInCommand(TimelineDock &timeline, int trackIndex, int clipIndex, int duration,
513  int trimDelta, bool redo = true, QUndoCommand *parent = 0);
514  void redo();
515  void undo();
516 protected:
517  int id() const
518  {
519  return UndoIdAddTransitionByTrimIn;
520  }
521  bool mergeWith(const QUndoCommand *other);
522 private:
523  TimelineDock &m_timeline;
524  int m_trackIndex;
525  int m_clipIndex;
526  int m_duration;
527  int m_trimDelta;
528  bool m_notify;
529  bool m_redo;
530 };
531 
532 class RemoveTransitionByTrimInCommand : public TrimCommand
533 {
534 public:
535  RemoveTransitionByTrimInCommand(MultitrackModel &model, int trackIndex, int clipIndex, int delta,
536  QString xml, bool redo = true, QUndoCommand *parent = 0);
537  void redo();
538  void undo();
539 private:
540  MultitrackModel &m_model;
541  int m_trackIndex;
542  int m_clipIndex;
543  int m_delta;
544  QString m_xml;
545  bool m_redo;
546 };
547 
548 class RemoveTransitionByTrimOutCommand : public TrimCommand
549 {
550 public:
551  RemoveTransitionByTrimOutCommand(MultitrackModel &model, int trackIndex, int clipIndex, int delta,
552  QString xml, bool redo = true, QUndoCommand *parent = 0);
553  void redo();
554  void undo();
555 private:
556  MultitrackModel &m_model;
557  int m_trackIndex;
558  int m_clipIndex;
559  int m_delta;
560  QString m_xml;
561  bool m_redo;
562 };
563 
564 class AddTransitionByTrimOutCommand : public TrimCommand
565 {
566 public:
567  AddTransitionByTrimOutCommand(MultitrackModel &model, int trackIndex, int clipIndex, int duration,
568  int trimDelta, bool redo = true, QUndoCommand *parent = 0);
569  void redo();
570  void undo();
571 protected:
572  int id() const
573  {
574  return UndoIdAddTransitionByTrimOut;
575  }
576  bool mergeWith(const QUndoCommand *other);
577 private:
578  MultitrackModel &m_model;
579  int m_trackIndex;
580  int m_clipIndex;
581  int m_duration;
582  int m_trimDelta;
583  bool m_notify;
584  bool m_redo;
585 };
586 
587 class AddTrackCommand: public QUndoCommand
588 {
589 public:
590  AddTrackCommand(MultitrackModel &model, bool isVideo, QUndoCommand *parent = 0);
591  void redo();
592  void undo();
593 private:
594  MultitrackModel &m_model;
595  int m_trackIndex;
596  bool m_isVideo;
597  QUuid m_uuid;
598 };
599 
600 class InsertTrackCommand : public QUndoCommand
601 {
602 public:
603  InsertTrackCommand(MultitrackModel &model, int trackIndex, TrackType trackType = PlaylistTrackType,
604  QUndoCommand *parent = 0);
605  void redo();
606  void undo();
607 private:
608  MultitrackModel &m_model;
609  int m_trackIndex;
610  TrackType m_trackType;
611  QUuid m_uuid;
612 };
613 
614 class RemoveTrackCommand : public QUndoCommand
615 {
616 public:
617  RemoveTrackCommand(MultitrackModel &model, int trackIndex, QUndoCommand *parent = 0);
618  void redo();
619  void undo();
620 private:
621  MultitrackModel &m_model;
622  int m_trackIndex;
623  TrackType m_trackType;
624  QString m_trackName;
625  UndoHelper m_undoHelper;
626  QScopedPointer<Mlt::Producer> m_filtersProducer;
627  QUuid m_uuid;
628 };
629 
630 class MoveTrackCommand : public QUndoCommand
631 {
632 public:
633  MoveTrackCommand(MultitrackModel &model, int fromTrackIndex, int toTrackIndex,
634  QUndoCommand *parent = 0);
635  void redo();
636  void undo();
637 private:
638  MultitrackModel &m_model;
639  int m_fromTrackIndex;
640  int m_toTrackIndex;
641 };
642 
643 class ChangeBlendModeCommand : public QObject, public QUndoCommand
644 {
645  Q_OBJECT
646 public:
647  ChangeBlendModeCommand(Mlt::Transition &transition, const QString &propertyName,
648  const QString &mode, QUndoCommand *parent = 0);
649  void redo();
650  void undo();
651 signals:
652  void modeChanged(QString &mode);
653 private:
654  Mlt::Transition m_transition;
655  QString m_propertyName;
656  QString m_newMode;
657  QString m_oldMode;
658 };
659 
660 class UpdateCommand : public QUndoCommand
661 {
662 public:
663  UpdateCommand(TimelineDock &timeline, int trackIndex, int clipIndex, int position,
664  QUndoCommand *parent = 0);
665  void setXmlAfter(const QString &xml);
666  void setPosition(int trackIndex, int clipIndex, int position);
667  void setRippleAllTracks(bool);
668  int trackIndex() const
669  {
670  return m_trackIndex;
671  }
672  int clipIndex() const
673  {
674  return m_clipIndex;
675  }
676  int position() const
677  {
678  return m_position;
679  }
680  void redo();
681  void undo();
682 private:
683  TimelineDock &m_timeline;
684  int m_trackIndex;
685  int m_clipIndex;
686  int m_position;
687  QString m_xmlAfter;
688  bool m_isFirstRedo;
689  UndoHelper m_undoHelper;
690  bool m_ripple;
691  bool m_rippleAllTracks;
692 };
693 
694 class DetachAudioCommand: public QUndoCommand
695 {
696 public:
697  DetachAudioCommand(TimelineDock &timeline, int trackIndex, int clipIndex, int position,
698  const QString &xml, QUndoCommand *parent = 0);
699  void redo();
700  void undo();
701 private:
702  TimelineDock &m_timeline;
703  int m_trackIndex;
704  int m_clipIndex;
705  int m_position;
706  int m_targetTrackIndex;
707  QString m_xml;
708  UndoHelper m_undoHelper;
709  bool m_trackAdded;
710  QUuid m_uuid;
711 };
712 
713 class ReplaceCommand : public QUndoCommand
714 {
715 public:
716  ReplaceCommand(MultitrackModel &model, int trackIndex, int clipIndex, const QString &xml,
717  QUndoCommand *parent = nullptr);
718  void redo();
719  void undo();
720 private:
721  MultitrackModel &m_model;
722  int m_trackIndex;
723  int m_clipIndex;
724  QString m_xml;
725  bool m_isFirstRedo;
726  UndoHelper m_undoHelper;
727 };
728 
729 
730 class AlignClipsCommand : public QUndoCommand
731 {
732 public:
733  AlignClipsCommand(MultitrackModel &model, QUndoCommand *parent = 0);
734  void addAlignment(QUuid uuid, int offset, double speedCompensation);
735  void redo();
736  void undo();
737 
738 private:
739  MultitrackModel &m_model;
740  UndoHelper m_undoHelper;
741  bool m_redo;
742  struct Alignment {
743  QUuid uuid;
744  int offset;
745  double speed;
746  };
747  QVector<Alignment> m_alignments;
748 };
749 
750 class ApplyFiltersCommand : public QUndoCommand
751 {
752 public:
753  ApplyFiltersCommand(MultitrackModel &model, const QString &filterProducerXml,
754  QUndoCommand *parent = 0);
755  void addClip(int trackIndex, int clipIndex);
756  void redo();
757  void undo();
758 
759 private:
760  MultitrackModel &m_model;
761  QString m_xml;
762  QMap<ClipPosition, QString> m_prevFilters;
763 };
764 
765 } // namespace Timeline
766 
767 #endif