timelinecontroller.h 18.5 KB
Newer Older
1
/***************************************************************************
2
 *   Copyright (C) 2017 by Jean-Baptiste Mardelle                          *
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *   This file is part of Kdenlive. See www.kdenlive.org.                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) version 3 or any later version accepted by the       *
 *   membership of KDE e.V. (or its successor approved  by the membership  *
 *   of KDE e.V.), which shall act as a proxy defined in Section 14 of     *
 *   version 3 of the license.                                             *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
 ***************************************************************************/

#ifndef TIMELINECONTROLLER_H
#define TIMELINECONTROLLER_H

Nicolas Carion's avatar
Nicolas Carion committed
25
#include "definitions.h"
26
#include "timeline2/model/timelineitemmodel.hpp"
Nicolas Carion's avatar
linting  
Nicolas Carion committed
27
#include "timelinewidget.h"
28

29 30 31
class PreviewManager;
class QAction;

Nicolas Carion's avatar
linting  
Nicolas Carion committed
32
// see https://bugreports.qt.io/browse/QTBUG-57714, don't expose a QWidget as a context property
33 34 35 36 37 38 39 40 41 42 43 44
class TimelineController : public QObject
{
    Q_OBJECT
    /* @brief holds a list of currently selected clips (list of clipId's)
     */
    Q_PROPERTY(QList<int> selection READ selection WRITE setSelection NOTIFY selectionChanged)
    /* @brief holds the timeline zoom factor
     */
    Q_PROPERTY(double scaleFactor READ scaleFactor WRITE setScaleFactor NOTIFY scaleFactorChanged)
    /* @brief holds the current project duration
     */
    Q_PROPERTY(int duration READ duration NOTIFY durationChanged)
45
    Q_PROPERTY(int fullDuration READ fullDuration NOTIFY durationChanged)
46 47 48 49
    Q_PROPERTY(bool audioThumbFormat READ audioThumbFormat NOTIFY audioThumbFormatChanged)
    /* @brief holds the current timeline position
     */
    Q_PROPERTY(int position READ position WRITE setPosition NOTIFY positionChanged)
50 51
    Q_PROPERTY(int zoneIn READ zoneIn WRITE setZoneIn NOTIFY zoneChanged)
    Q_PROPERTY(int zoneOut READ zoneOut WRITE setZoneOut NOTIFY zoneChanged)
52 53 54 55 56 57
    Q_PROPERTY(int seekPosition READ seekPosition WRITE setSeekPosition NOTIFY seekPositionChanged)
    Q_PROPERTY(bool ripple READ ripple NOTIFY rippleChanged)
    Q_PROPERTY(bool scrub READ scrub NOTIFY scrubChanged)
    Q_PROPERTY(bool showThumbnails READ showThumbnails NOTIFY showThumbnailsChanged)
    Q_PROPERTY(bool showMarkers READ showMarkers NOTIFY showMarkersChanged)
    Q_PROPERTY(bool showAudioThumbnails READ showAudioThumbnails NOTIFY showAudioThumbnailsChanged)
58 59 60
    Q_PROPERTY(QVariantList dirtyChunks READ dirtyChunks NOTIFY dirtyChunksChanged)
    Q_PROPERTY(QVariantList renderedChunks READ renderedChunks NOTIFY renderedChunksChanged)
    Q_PROPERTY(int workingPreview READ workingPreview NOTIFY workingPreviewChanged)
61
    Q_PROPERTY(bool useRuler READ useRuler NOTIFY useRulerChanged)
62
    Q_PROPERTY(int activeTrack READ activeTrack WRITE setActiveTrack NOTIFY activeTrackChanged)
63 64
    Q_PROPERTY(int audioTarget READ audioTarget WRITE setAudioTarget NOTIFY audioTargetChanged)
    Q_PROPERTY(int videoTarget READ videoTarget WRITE setVideoTarget NOTIFY videoTargetChanged)
65 66

public:
67
    TimelineController(QObject *parent);
68
    virtual ~TimelineController();
69
    /* @brief Sets the model that this widgets displays */
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
70
    void setModel(std::shared_ptr<TimelineItemModel> model);
71
    std::shared_ptr<TimelineItemModel> getModel() const;
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
72
    void setRoot(QQuickItem *root);
73 74 75 76 77 78

    Q_INVOKABLE bool isMultitrackSelected() const { return m_selection.isMultitrackSelected; }
    Q_INVOKABLE int selectedTrack() const { return m_selection.selectedTrack; }
    /* @brief Add a clip id to current selection
     */
    Q_INVOKABLE void addSelection(int newSelection);
79 80 81
    /* @brief Clear current selection and inform the view
     */
    void clearSelection();
82 83 84 85 86 87
    /* @brief Select all timeline items
     */
    void selectAll();
    /* @brief Select all items in one track
     */
    void selectCurrentTrack();
88 89 90 91 92
    /* @brief returns current timeline's zoom factor
     */
    Q_INVOKABLE double scaleFactor() const;
    /* @brief set current timeline's zoom factor
     */
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
93
    void setScaleFactorOnMouse(double scale, bool zoomOnMouse);
94 95 96 97
    Q_INVOKABLE void setScaleFactor(double scale);
    /* @brief Returns the project's duration (tractor)
     */
    Q_INVOKABLE int duration() const;
98
    Q_INVOKABLE int fullDuration() const;
99 100 101 102 103 104
    /* @brief Returns the current cursor position (frame currently displayed by MLT)
     */
    Q_INVOKABLE int position() const { return m_position; }
    /* @brief Returns the seek request position (-1 = no seek pending)
     */
    Q_INVOKABLE int seekPosition() const { return m_seekPosition; }
105 106
    Q_INVOKABLE int audioTarget() const;
    Q_INVOKABLE int videoTarget() const;
107
    Q_INVOKABLE int activeTrack() const { return m_activeTrack; }
108 109 110 111 112 113 114 115
    /* @brief Request a seek operation
       @param position is the desired new timeline position
     */
    Q_INVOKABLE int zoneIn() const { return m_zone.x(); }
    Q_INVOKABLE int zoneOut() const { return m_zone.y(); }
    Q_INVOKABLE void setZoneIn(int inPoint);
    Q_INVOKABLE void setZoneOut(int outPoint);
    void setZone(const QPoint &zone);
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
    /* @brief Request a seek operation
       @param position is the desired new timeline position
     */
    Q_INVOKABLE void setPosition(int position);
    Q_INVOKABLE bool snap();
    Q_INVOKABLE bool ripple();
    Q_INVOKABLE bool scrub();
    Q_INVOKABLE QString timecode(int frames);
    /* @brief Request inserting a new clip in timeline (dragged from bin or monitor)
       @param tid is the destination track
       @param position is the timeline position
       @param xml is the data describing the dropped clip
       @param logUndo if set to false, no undo object is stored
       @return the id of the inserted clip
     */
131
    Q_INVOKABLE int insertClip(int tid, int position, const QString &xml, bool logUndo, bool refreshView, bool useTargets);
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    /* @brief Request inserting multiple clips into the timeline (dragged from bin or monitor)
     * @param tid is the destination track
     * @param position is the timeline position
     * @param binIds the IDs of the bins being dropped
     * @param logUndo if set to false, no undo object is stored
     * @return the ids of the inserted clips
     */
    Q_INVOKABLE QList<int> insertClips(int tid, int position, const QStringList &binIds, bool logUndo, bool refreshView);
    /* @brief Request the grouping of the given clips
     * @param clipIds the ids to be grouped
     * @return the group id or -1 in case of faiure
     */
    Q_INVOKABLE int groupClips(const QList<int> &clipIds);
    /* @brief Request the ungrouping of clips
     * @param clipId the id of a clip belonging to the group
     * @return true in case of success, false otherwise
     */
    Q_INVOKABLE bool ungroupClips(int clipId);
150
    Q_INVOKABLE void copyItem();
151
    Q_INVOKABLE bool pasteItem(int clipId = -1, int tid = -1, int position = -1);
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
    /* @brief Request inserting a new composition in timeline (dragged from compositions list)
       @param tid is the destination track
       @param position is the timeline position
       @param transitionId is the data describing the dropped composition
       @param logUndo if set to false, no undo object is stored
       @return the id of the inserted composition
    */
    Q_INVOKABLE int insertComposition(int tid, int position, const QString &transitionId, bool logUndo);

    /* @brief Request deletion of the currently selected clips
     */
    Q_INVOKABLE void deleteSelectedClips();

    Q_INVOKABLE void triggerAction(const QString &name);

    /* @brief Do we want to display video thumbnails
     */
    bool showThumbnails() const;
    bool showAudioThumbnails() const;
    bool showMarkers() const;
    bool audioThumbFormat() const;
    /* @brief Do we want to display audio thumbnails
     */
    Q_INVOKABLE bool showWaveforms() const;
    /* @brief Insert a timeline track
     */
    Q_INVOKABLE void addTrack(int tid);
    /* @brief Remove a timeline track
     */
    Q_INVOKABLE void deleteTrack(int tid);
    /* @brief Group selected items in timeline
     */
    Q_INVOKABLE void groupSelection();
    /* @brief Ungroup selected items in timeline
     */
187
    Q_INVOKABLE void unGroupSelection(int cid = -1);
188 189 190 191 192
    /* @brief Ask for edit marker dialog
     */
    Q_INVOKABLE void editMarker(const QString &cid, int frame);
    /* @brief Ask for edit timeline guide dialog
     */
193
    Q_INVOKABLE void editGuide(int frame = -1);
194
    Q_INVOKABLE void moveGuide(int frame, int newFrame);
195 196
    /* @brief Add a timeline guide
     */
197
    Q_INVOKABLE void switchGuide(int frame = -1, bool deleteOnly = false);
198 199 200 201 202 203 204 205 206
    /* @brief Request monitor refresh
     */
    Q_INVOKABLE void requestRefresh();

    /* @brief Show the asset of the given item in the AssetPanel
       If the id corresponds to a clip, we show the corresponding effect stack
       If the id corresponds to a composition, we show its properties
    */
    Q_INVOKABLE void showAsset(int id);
207
    Q_INVOKABLE void showTrackAsset(int trackId);
208

209
    Q_INVOKABLE void selectItems(QVariantList arg, int startFrame, int endFrame, bool addToSelect);
210

211 212 213
    Q_INVOKABLE int headerWidth() const;
    Q_INVOKABLE void setHeaderWidth(int width);

214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
    /* @brief Seek to next snap point
     */
    void gotoNextSnap();
    /* @brief Seek to previous snap point
     */
    void gotoPreviousSnap();
    /* @brief Set current item's start point to cursor position
     */
    void setInPoint();
    /* @brief Set current item's end point to cursor position
     */
    void setOutPoint();
    /* @brief Return the project's tractor
     */
    Mlt::Tractor *tractor();
    /* @brief Sets the list of currently selected clips
       @param selection is the list of id's
       @param trackIndex is current clip's track
       @param isMultitrack is true if we want to select the whole tractor (currently unused)
     */
    void setSelection(const QList<int> &selection = QList<int>(), int trackIndex = -1, bool isMultitrack = false);
    /* @brief Get the list of currenly selected clip id's
     */
    QList<int> selection() const;
238

239 240 241
    /* @brief Add an asset (effect, composition)
     */
    void addAsset(const QVariantMap data);
242

243 244
    /* @brief Cuts the clip on current track at timeline position
     */
245
    Q_INVOKABLE void cutClipUnderCursor(int position = -1, int track = -1);
246 247
    /* @brief Request a spacer operation
     */
248 249 250 251
    Q_INVOKABLE int requestSpacerStartOperation(int trackId, int position);
    /* @brief Request a spacer operation
     */
    Q_INVOKABLE bool requestSpacerEndOperation(int clipId, int startPosition, int endPosition);
252 253
    /* @brief Request a Fade in effect for clip
     */
254
    Q_INVOKABLE void adjustFade(int cid, const QString &effectId, int duration, int initialDuration);
255

256
    Q_INVOKABLE const QString getTrackNameFromMltIndex(int trackPos);
257 258
    /* @brief Request inserting space in a track
     */
259 260
    Q_INVOKABLE void insertSpace(int trackId = -1, int frame = -1);
    Q_INVOKABLE void removeSpace(int trackId = -1, int frame = -1, bool affectAllTracks = false);
261
    /* @brief If clip is enabled, disable, otherwise enable
262
     */
263
    Q_INVOKABLE void switchEnableState(int clipId);
264 265 266 267 268

    Q_INVOKABLE void requestClipCut(int clipId, int position);

    Q_INVOKABLE void extract(int clipId);

269
    Q_INVOKABLE void splitAudio(int clipId);
270
    Q_INVOKABLE void splitVideo(int clipId);
271 272 273 274

    /* @brief Seeks to selected clip start / end
     */
    Q_INVOKABLE void pasteEffects(int targetId, int sourceId);
275
    Q_INVOKABLE double fps() const;
276

277 278
    void switchTrackLock(bool applyToAll = false);
    void switchTargetTrack();
279

280
    const QString getTrackNameFromIndex(int trackIndex);
281 282 283
    /* @brief Seeks to selected clip start / end
     */
    void seekCurrentClip(bool seekToEnd = false);
284 285 286
    /* @brief Seeks to a clip start (or end) based on it's clip id
     */
    void seekToClip(int cid, bool seekToEnd);
287 288 289
    /* @brief Returns the number of tracks (audioTrakcs, videoTracks)
     */
    QPoint getTracksCount() const;
290 291 292
    /* @brief Request monitor refresh if item (clip or composition) is under timeline cursor
     */
    void refreshItem(int id);
293 294 295
    /* @brief Seek timeline to mouse position
     */
    void seekToMouse();
296

297 298 299 300
    /* @brief User enabled / disabled snapping, update timeline behavior
     */
    void snapChanged(bool snap);

301 302 303
    /* @brief Returns a list of all luma files used in the project
     */
    QStringList extractCompositionLumas() const;
304 305 306
    /* @brief Get the frame where mouse is positionned
     */
    int getMousePos();
307 308 309
    /* @brief Get the frame where mouse is positionned
     */
    int getMouseTrack();
310 311 312
    /* @brief Returns a map of track ids/track names
     */
    QMap<int, QString> getTrackNames(bool videoOnly);
313
    /* @brief Returns the transition a track index for a composition (MLT index / Track id)
314
     */
Nicolas Carion's avatar
Nicolas Carion committed
315
    QPair<int, int> getCompositionATrack(int cid) const;
316
    void setCompositionATrack(int cid, int aTrack);
317 318 319
    /* @brief Return true if composition's a_track is automatic (no forced track)
     */
    bool compositionAutoTrack(int cid) const;
320
    const QString getClipBinId(int clipId) const;
321
    void focusItem(int itemId);
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
    /* @brief Create and display a split clip view to compare effect
     */
    bool createSplitOverlay(Mlt::Filter *filter);
    /* @brief Delete the split clip view to compare effect
     */
    void removeSplitOverlay();
    /* @brief Add current timeline zone to preview rendering
     */
    void addPreviewRange(bool add);
    /* @brief Clear current timeline zone from preview rendering
     */
    void clearPreviewRange();
    void startPreviewRender();
    void stopPreviewRender();
    QVariantList dirtyChunks() const;
    QVariantList renderedChunks() const;
338 339
    /* @brief returns the frame currently processed by timeline preview, -1 if none
     */
340
    int workingPreview() const;
341 342

    /** @brief Return true if we want to use timeline ruler zone for editing */
343
    bool useRuler() const;
344 345 346 347 348 349
    /* @brief Load timeline preview from saved doc
     */
    void loadPreview(QString chunks, QString dirty, const QDateTime &documentDate, int enable);
    /* @brief Return document properties with added settings from timeline
     */
    QMap<QString, QString> documentProperties();
350 351 352 353 354

    /** @brief Change track compsiting mode */
    void switchCompositing(int mode);

    /** @brief Change a clip item's speed in timeline */
355
    Q_INVOKABLE void changeItemSpeed(int clipId, int speed);
356 357 358 359
    /** @brief Delete selected zone and fill gap by moving following clips
     *  @param lift if true, the zone will simply be deleted but clips won't be moved
     */
    void extractZone(QPoint zone, bool liftOnly = false);
360 361 362 363
    /** @brief Insert clip monitor into timeline
     *  @returns the zone end position or -1 on fail
     */
    int insertZone(const QString &binId, QPoint zone, bool overwrite);
Nicolas Carion's avatar
Nicolas Carion committed
364
    void updateClip(int clipId, QVector<int> roles);
365
    void showClipKeyframes(int clipId, bool value);
366
    void showCompositionKeyframes(int clipId, bool value);
367 368
    /** @brief Returns last usable timeline position (seek request or current pos) */
    int timelinePosition() const;
369 370
    /** @brief Adjust all timeline tracks height */
    void resetTrackHeight();
371 372
    /** @brief timeline preview params changed, reset */
    void resetPreview();
373 374
    /** @brief Select the clip in active track under cursor */
    void selectCurrentItem(ObjectType type, bool select, bool addToCurrent = false);
375 376
    /** @brief Set target tracks (video, audio) */
    void setTargetTracks(QPair<int, int> targets);
377

378 379
public slots:
    void selectMultitrack();
380
    Q_INVOKABLE void setSeekPosition(int position);
381 382
    Q_INVOKABLE void setAudioTarget(int track);
    Q_INVOKABLE void setVideoTarget(int track);
383
    Q_INVOKABLE void setActiveTrack(int track);
384
    void onSeeked(int position);
385
    void addEffectToCurrentClip(const QStringList &effectData);
386 387
    /** @brief Dis / enable timeline preview. */
    void disablePreview(bool disable);
388
    void invalidateClip(int cid);
389
    void invalidateZone(int in, int out);
390
    void checkDuration();
391

392
private:
393
    QQuickItem *m_root;
394 395
    KActionCollection *m_actionCollection;
    std::shared_ptr<TimelineItemModel> m_model;
396
    bool m_usePreview;
397 398
    struct Selection
    {
399
        QList<int> selectedItems;
400 401 402 403 404
        int selectedTrack;
        bool isMultitrackSelected;
    };
    int m_position;
    int m_seekPosition;
405 406
    int m_audioTarget;
    int m_videoTarget;
407
    int m_activeTrack;
408
    QPoint m_zone;
409 410 411 412
    double m_scale;
    static int m_duration;
    Selection m_selection;
    Selection m_savedSelection;
413 414
    PreviewManager *m_timelinePreview;
    QAction *m_disablePreview;
415
    void emitSelectedFromSelection();
416 417
    int getCurrentItem();
    void initializePreview();
418 419
    // Get a list of currently selected items, including clips grouped with selection
    std::unordered_set<int> getCurrentSelectionIds() const;
420 421 422 423 424 425 426 427 428 429 430

signals:
    void selected(Mlt::Producer *producer);
    void selectionChanged();
    void frameFormatChanged();
    void trackHeightChanged();
    void scaleFactorChanged();
    void audioThumbFormatChanged();
    void durationChanged();
    void positionChanged();
    void seekPositionChanged();
431 432
    void audioTargetChanged();
    void videoTargetChanged();
433
    void activeTrackChanged();
434 435 436 437 438 439
    void showThumbnailsChanged();
    void showAudioThumbnailsChanged();
    void showMarkersChanged();
    void rippleChanged();
    void scrubChanged();
    void seeked(int position);
440 441
    void zoneChanged();
    void zoneMoved(const QPoint &zone);
442
    /* @brief Requests that a given parameter model is displayed in the asset panel */
443
    void showTransitionModel(int tid, std::shared_ptr<AssetParameterModel>);
444
    void showItemEffectStack(const QString &clipName, std::shared_ptr<EffectStackModel>, QSize frameSize, bool showKeyframes);
445 446 447 448 449
    /* @brief notify of chunks change
     */
    void dirtyChunksChanged();
    void renderedChunksChanged();
    void workingPreviewChanged();
450
    void useRulerChanged();
451 452 453
};

#endif