CuteLogger
Fast and simple logging solution for Qt based applications
timelinedock.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 TIMELINEDOCK_H
19 #define TIMELINEDOCK_H
20 
21 #include <QDockWidget>
22 #include <QQuickWidget>
23 #include <QApplication>
24 #include <QTimer>
25 #include <QDateTime>
26 #include "models/markersmodel.h"
27 #include "models/multitrackmodel.h"
28 #include "models/subtitlesmodel.h"
29 #include "models/subtitlesselectionmodel.h"
30 #include "sharedframe.h"
31 #include "jobs/ffmpegjob.h"
32 
33 namespace Timeline {
34 class UpdateCommand;
35 class TrimCommand;
36 }
37 class UndoHelper;
38 class QMenu;
39 
40 class TimelineDock : public QDockWidget
41 {
42  Q_OBJECT
43  Q_PROPERTY(int position READ position WRITE setPosition NOTIFY positionChanged)
44  Q_PROPERTY(int currentTrack READ currentTrack WRITE setCurrentTrack NOTIFY currentTrackChanged)
45  Q_PROPERTY(QVariantList selection READ selectionForJS WRITE setSelectionFromJS NOTIFY
46  selectionChanged)
47  Q_PROPERTY(bool isRecording READ isRecording NOTIFY isRecordingChanged)
48  Q_PROPERTY(int loopStart READ loopStart NOTIFY loopChanged)
49  Q_PROPERTY(int loopEnd READ loopEnd NOTIFY loopChanged)
50 
51 public:
52  explicit TimelineDock(QWidget *parent = 0);
53  ~TimelineDock();
54 
55  enum TrimLocation {
56  TrimInPoint,
57  TrimOutPoint
58  };
59 
60  MultitrackModel *model()
61  {
62  return &m_model;
63  }
64  MarkersModel *markersModel()
65  {
66  return & m_markersModel;
67  }
68  SubtitlesModel *subtitlesModel()
69  {
70  return & m_subtitlesModel;
71  }
72  SubtitlesSelectionModel *subtitlesSelectionModel()
73  {
74  return & m_subtitlesSelectionModel;
75  }
76  int position() const
77  {
78  return m_position;
79  }
80  void setPosition(int position);
81  Mlt::Producer producerForClip(int trackIndex, int clipIndex);
82  int clipIndexAtPlayhead(int trackIndex = -1);
83  int clipIndexAtPosition(int trackIndex, int position);
84  void chooseClipAtPosition(int position, int &trackIndex, int &clipIndex);
85  void setCurrentTrack(int currentTrack);
86  int currentTrack() const;
87  int clipCount(int trackIndex) const;
88  void setSelectionFromJS(const QVariantList &list);
89  void setSelection(QList<QPoint> selection = QList<QPoint>(), int trackIndex = -1,
90  bool isMultitrack = false);
91  QVariantList selectionForJS() const;
92  const QList<QPoint> selection() const;
93  const QVector<QUuid> selectionUuids();
94  const QList<QPoint> uuidsToSelection(QVector<QUuid> uuids) const;
95  void saveAndClearSelection();
96  Q_INVOKABLE void restoreSelection();
97  Q_INVOKABLE QVariantList getGroupForClip(int trackIndex, int clipIndex);
98  void selectClipUnderPlayhead();
99  int centerOfClip(int trackIndex, int clipIndex);
100  bool isTrackLocked(int trackIndex) const;
101  void trimClipAtPlayhead(TrimLocation location, bool ripple);
102  Q_INVOKABLE bool isMultitrackSelected() const
103  {
104  return m_selection.isMultitrackSelected;
105  }
106  Q_INVOKABLE int selectedTrack() const
107  {
108  return m_selection.selectedTrack;
109  }
110  Q_INVOKABLE bool isFloating() const
111  {
112  return QDockWidget::isFloating();
113  }
114  Q_INVOKABLE static void openProperties();
115  void emitSelectedChanged(const QVector<int> &roles);
116  void replaceClipsWithHash(const QString &hash, Mlt::Producer &producer);
117  Q_INVOKABLE void recordAudio();
118  Q_INVOKABLE void stopRecording();
119  bool isRecording() const
120  {
121  return m_isRecording;
122  }
123  int addTrackIfNeeded(TrackType trackType);
124  void getSelectionRange(int *start, int *end);
125  int loopStart() const
126  {
127  return m_loopStart;
128  }
129  int loopEnd() const
130  {
131  return m_loopEnd;
132  }
133 
134 signals:
135  void currentTrackChanged();
136  void selectionChanged();
137  void seeked(int position);
138  void positionChanged(int position);
139  void loopChanged();
140  void clipOpened(Mlt::Producer *producer);
141  void dragging(const QPointF &pos, int duration);
142  void dropped();
143  void dropAccepted(const QString &xml);
144  void fadeInChanged(int duration);
145  void fadeOutChanged(int duration);
146  void selected(Mlt::Producer *producer);
147  void clipClicked();
148  void showStatusMessage(QString);
149  void clipCopied();
150  void clipMoved(int fromTrack, int toTrack, int clipIndex, int position, bool ripple);
151  void filteredClicked();
152  void durationChanged();
153  void transitionAdded(int trackIndex, int clipIndex, int position, bool ripple);
154  void zoomIn();
155  void zoomOut();
156  void zoomToFit();
157  void setZoom(double value);
158  void markerRangesChanged();
159  void markerSeeked(int markerIndex);
160  void isRecordingChanged(bool);
161  void multitrackSelected();
162  void warnTrackLocked(int trackIndex);
163  void refreshWaveforms();
164  void updateThumbnails(int trackIndex, int clipIndex);
165 
166 public slots:
167  int addAudioTrack();
168  int addVideoTrack();
169  void alignSelectedClips();
170  void onShowFrame(const SharedFrame &frame);
171  void onSeeked(int position);
172  void append(int trackIndex);
173  void remove(int trackIndex, int clipIndex, bool ignoreTransition = false);
174  bool mergeClipWithNext(int trackIndex, int clipIndex, bool dryrun);
175  void lift(int trackIndex, int clipIndex, bool ignoreTransition = false);
176  void removeSelection(bool withCopy = false);
177  void liftSelection();
178  void incrementCurrentTrack(int by);
179  void selectTrackHead(int trackIndex);
180  void selectMultitrack();
181  void copy(int trackIndex, int clipIndex);
182  void setTrackName(int trackIndex, const QString &value);
183  void toggleTrackMute(int trackIndex);
184  void toggleTrackHidden(int trackIndex);
185  void setTrackComposite(int trackIndex, bool composite);
186  void setTrackLock(int trackIndex, bool lock);
187  bool moveClip(int fromTrack, int toTrack, int clipIndex, int position, bool ripple);
188  void onClipMoved(int fromTrack, int toTrack, int clipIndex, int position, bool ripple);
189  bool trimClipIn(int trackIndex, int clipIndex, int oldClipIndex, int delta, bool ripple);
190  bool trimClipOut(int trackIndex, int clipIndex, int delta, bool ripple);
191  void insert(int trackIndex, int position = -1, const QString &xml = QString(), bool seek = true);
192  void overwrite(int trackIndex, int position = -1, const QString &xml = QString(), bool seek = true);
193  void appendFromPlaylist(Mlt::Playlist *playlist, bool skipProxy, bool emptyTrack);
194  void fadeIn(int trackIndex, int clipIndex = -1, int duration = -1);
195  void fadeOut(int trackIndex, int clipIndex = -1, int duration = -1);
196  void seekPreviousEdit();
197  void seekNextEdit();
198  void seekInPoint(int clipIndex);
199  void clearSelectionIfInvalid();
200  void insertTrack();
201  void insertAudioTrack();
202  void insertVideoTrack();
203  void removeTrack();
204  void moveTrack(int fromTrackIndex, int toTrackIndex);
205  void moveTrackUp();
206  void moveTrackDown();
207  void onProducerChanged(Mlt::Producer *);
208  void emitSelectedFromSelection();
209  void remakeAudioLevels(int trackIndex, int clipIndex, bool force = true);
210  void commitTrimCommand();
211  void onRowsInserted(const QModelIndex &parent, int first, int last);
212  void onRowsRemoved(const QModelIndex &parent, int first, int last);
213  void onRowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination,
214  int row);
215  void detachAudio(int trackIndex, int clipIndex);
216  void selectAll();
217  void selectAllOnCurrentTrack();
218  void onProducerModified();
219  void replace(int trackIndex, int clipIndex, const QString &xml = QString());
220  void createOrEditMarker();
221  void createOrEditSelectionMarker();
222  void createMarker();
223  void editMarker(int markerIndex);
224  void deleteMarker(int markerIndex = -1);
225  void seekNextMarker();
226  void seekPrevMarker();
227  void onFilterModelChanged();
228  void trimClipIn(bool ripple = false);
229  void trimClipOut(bool ripple = false);
230  void initLoad();
231  void handleDrop(int trackIndex, int position, QString xml);
232  void onLoopChanged(int start, int end);
233 
234 protected:
235  void dragEnterEvent(QDragEnterEvent *event);
236  void dragMoveEvent(QDragMoveEvent *event);
237  void dragLeaveEvent(QDragLeaveEvent *event);
238  void dropEvent(QDropEvent *event);
239  bool event(QEvent *event);
240  void keyPressEvent(QKeyEvent *event);
241  void keyReleaseEvent(QKeyEvent *event);
242 
243 private:
244  bool isBlank(int trackIndex, int clipIndex);
245  bool clipsAreSelected();
246  bool blankIsSelected();
247  bool nothingIsSelected();
248  bool isTransition(int trackIndex, int clipIndex);
249  void emitNonSeekableWarning();
250  void addTrackIfNeeded(int mltTrackIndex, Mlt::Producer *srcTrack);
251  void setupActions();
252  bool isMultitrackValid()
253  {
254  return m_model.tractor() && !m_model.trackList().empty();
255  }
256  void reportSelectionChange();
257  void applyCopiedFiltersToSelectdClips();
258  void insertOrOverwriteDrop(int trackIndex, int position, const QString &xml);
259 
260  QQuickWidget m_quickView;
261  MultitrackModel m_model;
262  MarkersModel m_markersModel;
263  SubtitlesModel m_subtitlesModel;
264  SubtitlesSelectionModel m_subtitlesSelectionModel;
265  int m_position;
266  std::unique_ptr<Timeline::UpdateCommand> m_updateCommand;
267  bool m_ignoreNextPositionChange;
268  struct Selection {
269  QList<QPoint> selectedClips; // x is the clip index, y is the track index
270  int selectedTrack;
271  bool isMultitrackSelected;
272  };
273  Selection m_selection;
274  int m_savedSelectedTrack;
275  bool m_savedIsMultitrackSelected;
276  QVector<QUuid> m_savedSelectionUuids;
277  QTimer m_selectionSignalTimer;
278  std::unique_ptr<Timeline::TrimCommand> m_trimCommand;
279  std::unique_ptr<UndoHelper> m_undoHelper;
280  int m_trimDelta;
281  int m_transitionDelta;
282  bool m_isRecording {false};
283  std::unique_ptr<AbstractJob> m_recordJob;
284  QTimer m_recordingTimer;
285  QDateTime m_recordingTime;
286  int m_recordingTrackIndex;
287  int m_recordingClipIndex;
288  int m_currentTrack {0};
289  QMenu *m_mainMenu;
290  QMenu *m_clipMenu;
291  int m_loopStart;
292  int m_loopEnd;
293 
294 private slots:
295  void load(bool force);
296  void onTopLevelChanged(bool floating);
297  void onTransitionAdded(int trackIndex, int clipIndex, int position, bool ripple);
298  void selectClip(int trackIndex, int clipIndex);
299  void onMultitrackClosed();
300  void reloadTimelineModels();
301  void onRecordStarted();
302  void updateRecording();
303  void onRecordFinished(AbstractJob *, bool);
304  void onWarnTrackLocked();
305  void onTimelineRightClicked();
306  void onClipRightClicked();
307  void onNoMoreEmptyTracks(bool isAudio);
308 };
309 
310 #endif // TIMELINEDOCK_H
The SharedFrame provides thread safe access to Mlt::Frame data.
Definition: sharedframe.h:49