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