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