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
33namespace Timeline {
34class UpdateCommand;
35class TrimCommand;
36}
37class UndoHelper;
38class QMenu;
39
40class 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
51public:
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
134signals:
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
166public 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);
174 bool mergeClipWithNext(int trackIndex, int clipIndex, bool dryrun);
175 void lift(int trackIndex, int clipIndex);
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
234protected:
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
243private:
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
294private 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