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