diff --git a/src/assets/keyframes/model/rotoscoping/rotowidget.hpp b/src/assets/keyframes/model/rotoscoping/rotowidget.hpp index 6b0136017..86783ed12 100644 --- a/src/assets/keyframes/model/rotoscoping/rotowidget.hpp +++ b/src/assets/keyframes/model/rotoscoping/rotowidget.hpp @@ -1,72 +1,71 @@ /* Copyright (C) 2018 Jean-Baptiste Mardelle 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 . */ #ifndef ROTOHELPER_H #define ROTOHELPER_H #include "bpoint.h" +#include #include #include -#include class Monitor; class RotoWidget : public QWidget { Q_OBJECT public: /* @brief Construct a keyframe list bound to the given effect @param init_value is the value taken by the param at time 0. @param model is the asset this parameter belong to @param index is the index of this parameter in its model */ explicit RotoWidget(Monitor *monitor, QPersistentModelIndex index, QWidget *parent = nullptr); /** @brief Send signals to the monitor to update the qml overlay. @param returns : true if the monitor's connection was changed to active. */ bool connectMonitor(bool activate); /** @brief Returns a spline defined as string, based on its control points and frame size @param value : the control points @param frame: the frame size */ static QVariant getSpline(QVariant value, const QSize frame); /** @brief Returns a list of spline control points, based on its string definition and frame size @param value : the spline's string definition @param frame: the frame size */ static QList getPoints(QVariant value, const QSize frame); private: Monitor *m_monitor; QPersistentModelIndex m_index; bool m_active; private slots: void slotUpdateRotoMonitor(const QVariantList &v); signals: - void updateRotoKeyframe(QPersistentModelIndex, const QVariantList&); + void updateRotoKeyframe(QPersistentModelIndex, const QVariantList &); }; #endif - diff --git a/src/assets/view/widgets/colorwheel.h b/src/assets/view/widgets/colorwheel.h index 1392930f2..e978c7d56 100644 --- a/src/assets/view/widgets/colorwheel.h +++ b/src/assets/view/widgets/colorwheel.h @@ -1,98 +1,98 @@ /* * Copyright (c) 2013 Meltytech, LLC * Author: Dan Dennedy * * 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 3 of the License, or * (at your option) any later version. * * 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 . */ #ifndef COLORWHEELPARAM_H #define COLORWHEELPARAM_H #include #include #include class NegQColor { public: - int8_t sign_r=1; - int8_t sign_g=1; - int8_t sign_b=1; + int8_t sign_r = 1; + int8_t sign_g = 1; + int8_t sign_b = 1; QColor qcolor; static NegQColor fromHsvF(qreal h, qreal s, qreal l, qreal a = 1.0); static NegQColor fromRgbF(qreal r, qreal g, qreal b, qreal a = 1.0); qreal redF(); qreal greenF(); qreal blueF(); qreal valueF(); int hue(); qreal hueF(); qreal saturationF(); }; class ColorWheel : public QWidget { Q_OBJECT public: explicit ColorWheel(const QString &id, const QString &name, const NegQColor &color, QWidget *parent = nullptr); QSize sizeHint() const override; QSize minimumSizeHint() const override; NegQColor color() const; void setColor(const NegQColor &color); void setFactorDefaultZero(qreal factor, qreal defvalue, qreal zero); signals: void colorChange(const NegQColor &color); public slots: void changeColor(const NegQColor &color); protected: void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void resizeEvent(QResizeEvent *event) override; void paintEvent(QPaintEvent *event) override; private: QString m_id; QSize m_initialSize; QImage m_image; bool m_isMouseDown; QPoint m_lastPoint; int m_margin; int m_sliderWidth; QRegion m_wheelRegion; QRegion m_sliderRegion; NegQColor m_color; bool m_isInWheel; bool m_isInSquare; int m_unitSize; QString m_name; qreal m_sizeFactor = 1; qreal m_defaultValue = 1; qreal m_zeroShift = 0; int wheelSize() const; NegQColor colorForPoint(const QPoint &point); void drawWheel(); void drawWheelDot(QPainter &painter); void drawSliderBar(QPainter &painter); void drawSlider(); QString getParamValues(); }; #endif // COLORWHEEL_H diff --git a/src/bin/abstractprojectitem.h b/src/bin/abstractprojectitem.h index eca883f8b..0f47110de 100644 --- a/src/bin/abstractprojectitem.h +++ b/src/bin/abstractprojectitem.h @@ -1,215 +1,215 @@ /* Copyright (C) 2012 Till Theato Copyright (C) 2014 Jean-Baptiste Mardelle 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 . */ #ifndef ABSTRACTPROJECTITEM_H #define ABSTRACTPROJECTITEM_H #include "abstractmodel/treeitem.hpp" #include "undohelper.hpp" #include +#include #include #include -#include class ProjectClip; class ProjectFolder; class Bin; class QDomElement; class QDomDocument; class ProjectItemModel; /** * @class AbstractProjectItem * @brief Base class for all project items (clips, folders, ...). * * Project items are stored in a tree like structure ... */ class AbstractProjectItem : public QObject, public TreeItem { Q_OBJECT public: enum PROJECTITEMTYPE { FolderUpItem = 0, FolderItem = 1, ClipItem = 2, SubClipItem = 3 }; /** * @brief Constructor. * @param type is the type of the bin item * @param id is the binId * @param model is the ptr to the item model * @param isRoot is true if this is the topmost folder */ AbstractProjectItem(PROJECTITEMTYPE type, const QString &id, const std::shared_ptr &model, bool isRoot = false); bool operator==(const std::shared_ptr &projectItem) const; /** @brief Returns a pointer to the parent item (or NULL). */ std::shared_ptr parent() const; /** @brief Returns the type of this item (folder, clip, subclip, etc). */ PROJECTITEMTYPE itemType() const; /** @brief Used to search for a clip with a specific id. */ virtual std::shared_ptr clip(const QString &id) = 0; /** @brief Used to search for a folder with a specific id. */ virtual std::shared_ptr folder(const QString &id) = 0; virtual std::shared_ptr clipAt(int ix) = 0; /** @brief Recursively disable/enable bin effects. */ virtual void setBinEffectsEnabled(bool enabled) = 0; /** @brief This function executes what should be done when the item is deleted but without deleting effectively. For example, the item will deregister itself from the model and delete the clips from the timeline. However, the object is NOT actually deleted, and the tree structure is preserved. @param Undo,Redo are the lambdas accumulating the update. */ virtual bool selfSoftDelete(Fun &undo, Fun &redo); /** @brief Returns the clip's id. */ const QString &clipId() const; virtual QPoint zone() const; // TODO refac : these ref counting are probably deprecated by smart ptrs /** @brief Set current usage count. */ void setRefCount(uint count); /** @brief Returns clip's current usage count in timeline. */ uint refCount() const; /** @brief Increase usage count. */ void addRef(); /** @brief Decrease usage count. */ void removeRef(); enum DataType { // display name of item DataName = Qt::DisplayRole, // image thumbnail DataThumbnail = Qt::DecorationRole, // Tooltip text,usually full path ClipToolTip = Qt::ToolTipRole, // unique id of the project clip / folder DataId = Qt::UserRole, // creation date DataDate, // Description for item (user editable) DataDescription, // Number of occurrences used in timeline UsageCount, // Empty if clip has no effect, icon otherwise IconOverlay, // item type (clip, subclip, folder) ItemTypeRole, // Duration of the clip DataDuration, // If there is a running job, which type JobType, // Current progress of the job JobProgress, // error message if job crashes (not fully implemented) JobMessage, JobStatus, // Item status (ready or not, missing, waiting, ...) ClipStatus }; enum CLIPSTATUS { StatusReady = 0, StatusMissing, StatusWaiting, StatusDeleting }; void setClipStatus(AbstractProjectItem::CLIPSTATUS status); AbstractProjectItem::CLIPSTATUS clipStatus() const; bool statusReady() const; /** @brief Returns the data that describes this item. * @param type type of data to return * * This function is necessary for interaction with ProjectItemModel. */ QVariant getData(DataType type) const; /** * @brief Returns the amount of different types of data this item supports. * * This base class supports only DataName and DataDescription, so the return value is always 2. * This function is necessary for interaction with ProjectItemModel. */ virtual int supportedDataCount() const; /** @brief Returns the (displayable) name of this item. */ QString name() const; /** @brief Sets a new (displayable) name. */ virtual void setName(const QString &name); /** @brief Returns the (displayable) description of this item. */ QString description() const; /** @brief Sets a new description. */ virtual void setDescription(const QString &description); virtual QDomElement toXml(QDomDocument &document, bool includeMeta = false) = 0; virtual QString getToolTip() const = 0; virtual bool rename(const QString &name, int column) = 0; /* @brief Return the bin id of the last parent that this element got, even if this parent has already been destroyed. Return the empty string if the element was parentless */ QString lastParentId() const; /* @brief This is an overload of TreeItem::updateParent that tracks the id of the id of the parent */ void updateParent(std::shared_ptr newParent) override; /* Returns a ptr to the enclosing dir, and nullptr if none is found. @param strict if set to false, the enclosing dir of a dir is itself, otherwise we try to find a "true" parent */ std::shared_ptr getEnclosingFolder(bool strict = false); /** @brief Returns true if a clip corresponding to this bin is inserted in a timeline. Note that this function does not account for children, use TreeItem::accumulate if you want to get that information as well. */ virtual bool isIncludedInTimeline() { return false; } signals: void childAdded(AbstractProjectItem *child); void aboutToRemoveChild(AbstractProjectItem *child); protected: QString m_name; QString m_description; QIcon m_thumbnail; QString m_duration; QDateTime m_date; QString m_binId; uint m_usage; CLIPSTATUS m_clipStatus; PROJECTITEMTYPE m_itemType; QString m_lastParentId; /** @brief Returns a rounded border pixmap from the @param source pixmap. */ QPixmap roundedPixmap(const QPixmap &source); mutable QReadWriteLock m_lock; // This is a lock that ensures safety in case of concurrent access private: bool m_isCurrent; }; #endif diff --git a/src/bin/bin.h b/src/bin/bin.h index 86a835c7f..273b3f8bb 100644 --- a/src/bin/bin.h +++ b/src/bin/bin.h @@ -1,478 +1,478 @@ /* Copyright (C) 2012 Till Theato Copyright (C) 2014 Jean-Baptiste Mardelle 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 . */ #ifndef KDENLIVE_BIN_H #define KDENLIVE_BIN_H #include "abstractprojectitem.h" #include "timecode.h" #include #include #include #include #include #include #include -#include #include #include #include #include +#include #include #include class AbstractProjectItem; class BinItemDelegate; class BinMessageWidget; class ClipController; class EffectStackModel; class InvalidDialog; class KdenliveDoc; class Monitor; class ProjectClip; class ProjectFolder; class ProjectFolderUp; class ProjectItemModel; class ProjectSortProxyModel; class QDockWidget; class QMenu; class QScrollArea; class QTimeLine; class QToolBar; class QToolButton; class QUndoCommand; class QVBoxLayout; class SmallJobLabel; namespace Mlt { class Producer; } class MyListView : public QListView { Q_OBJECT public: explicit MyListView(QWidget *parent = nullptr); protected: void focusInEvent(QFocusEvent *event) override; signals: void focusView(); }; class MyTreeView : public QTreeView { Q_OBJECT Q_PROPERTY(bool editing READ isEditing WRITE setEditing) public: explicit MyTreeView(QWidget *parent = nullptr); void setEditing(bool edit); protected: void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void focusInEvent(QFocusEvent *event) override; void keyPressEvent(QKeyEvent *event) override; protected slots: void closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint) override; void editorDestroyed(QObject *editor) override; private: QPoint m_startPos; bool m_editing; bool performDrag(); bool isEditing() const; signals: void focusView(); }; class BinMessageWidget : public KMessageWidget { Q_OBJECT public: explicit BinMessageWidget(QWidget *parent = nullptr); BinMessageWidget(const QString &text, QWidget *parent = nullptr); protected: bool event(QEvent *ev) override; signals: void messageClosing(); }; class SmallJobLabel : public QPushButton { Q_OBJECT public: explicit SmallJobLabel(QWidget *parent = nullptr); static const QString getStyleSheet(const QPalette &p); void setAction(QAction *action); private: enum ItemRole { NameRole = Qt::UserRole, DurationRole, UsageRole }; QTimeLine *m_timeLine; QAction *m_action; public slots: void slotSetJobCount(int jobCount); private slots: void slotTimeLineChanged(qreal value); void slotTimeLineFinished(); }; class LineEventEater : public QObject { Q_OBJECT public: explicit LineEventEater(QObject *parent = nullptr); protected: bool eventFilter(QObject *obj, QEvent *event) override; signals: void clearSearchLine(); void showClearButton(bool); }; /** * @class Bin * @brief The bin widget takes care of both item model and view upon project opening. */ class Bin : public QWidget { Q_OBJECT /** @brief Defines the view types (icon view, tree view,...) */ enum BinViewType { BinTreeView, BinIconView }; public: explicit Bin(const std::shared_ptr &model, QWidget *parent = nullptr); ~Bin(); bool isLoading; /** @brief Sets the document for the bin and initialize some stuff */ void setDocument(KdenliveDoc *project); /** @brief Create a clip item from its xml description */ void createClip(const QDomElement &xml); /** @brief Used to notify the Model View that an item was updated */ void emitItemUpdated(std::shared_ptr item); /** @brief Set monitor associated with this bin (clipmonitor) */ void setMonitor(Monitor *monitor); /** @brief Returns the clip monitor */ Monitor *monitor(); /** @brief Open a producer in the clip monitor */ void openProducer(std::shared_ptr controller); void openProducer(std::shared_ptr controller, int in, int out); /** @brief Get a clip from it's id */ std::shared_ptr getBinClip(const QString &id); /** @brief Returns a list of selected clip ids @param excludeFolders: if true, ids of folders are not returned */ std::vector selectedClipsIds(bool excludeFolders = true); // Returns the selected clips QList> selectedClips(); /** @brief Current producer has changed, refresh monitor and timeline*/ void refreshClip(const QString &id); void setupMenu(QMenu *addMenu, QAction *defaultAction, const QHash &actions); /** @brief The source file was modified, we will reload it soon, disable item in the meantime */ void setWaitingStatus(const QString &id); const QString getDocumentProperty(const QString &key); /** @brief A proxy clip was just created, pass it to the responsible item */ void gotProxy(const QString &id, const QString &path); /** @brief Ask MLT to reload this clip's producer */ void reloadClip(const QString &id); void doMoveClip(const QString &id, const QString &newParentId); void doMoveFolder(const QString &id, const QString &newParentId); void setupGeneratorMenu(); /** @brief Set focus to the Bin view. */ void focusBinView() const; /** @brief Get a string list of all clip ids that are inside a folder defined by id. */ QStringList getBinFolderClipIds(const QString &id) const; /** @brief Build a rename subclip command. */ void renameSubClipCommand(const QString &id, const QString &newName, const QString &oldName, int in, int out); /** @brief Rename a clip zone (subclip). */ void renameSubClip(const QString &id, const QString &newName, const QString &oldName, int in, int out); /** @brief Returns current project's timecode. */ Timecode projectTimecode() const; /** @brief Trigger timecode format refresh where needed. */ void updateTimecodeFormat(); /** @brief Edit an effect settings to a bin clip. */ void editMasterEffect(std::shared_ptr clip); /** @brief An effect setting was changed, update stack if displayed. */ void updateMasterEffect(ClipController *ctl); /** @brief Display a message about an operation in status bar. */ void emitMessage(const QString &, int, MessageType); void rebuildMenu(); void refreshIcons(); /** @brief This function change the global enabled state of the bin effects */ void setBinEffectsEnabled(bool enabled); void requestAudioThumbs(const QString &id, long duration); /** @brief Proxy status for the project changed, update. */ void refreshProxySettings(); /** @brief A clip is ready, update its info panel if displayed. */ void emitRefreshPanel(const QString &id); /** @brief Returns true if there is no clip. */ bool isEmpty() const; /** @brief Trigger reload of all clips. */ void reloadAllProducers(); /** @brief Get usage stats for project bin. */ void getBinStats(uint *used, uint *unused, qint64 *usedSize, qint64 *unusedSize); /** @brief Returns the clip properties dockwidget. */ QDockWidget *clipPropertiesDock(); /** @brief Returns a document's cache dir. ok is set to false if folder does not exist */ QDir getCacheDir(CacheType type, bool *ok) const; void rebuildProxies(); /** @brief Return a list of all clips hashes used in this project */ QStringList getProxyHashList(); /** @brief Get info (id, name) of a folder (or the currently selected one) */ const QStringList getFolderInfo(const QModelIndex &selectedIx = QModelIndex()); /** @brief Get binId of the current selected folder */ QString getCurrentFolder(); /** @brief Save a clip zone as MLT playlist */ void saveZone(const QStringList &info, const QDir &dir); // TODO refac: remove this and call directly the function in ProjectItemModel void cleanup(); private slots: void slotAddClip(); void slotReloadClip(); /** @brief Set sorting column */ void slotSetSorting(); /** @brief Show/hide date column */ void slotShowDateColumn(bool show); void slotShowDescColumn(bool show); /** @brief Setup the bin view type (icon view, tree view, ...). * @param action The action whose data defines the view type or nullptr to keep default view */ void slotInitView(QAction *action); /** @brief Update status for clip jobs */ void slotUpdateJobStatus(const QString &, int, int, const QString &label = QString(), const QString &actionName = QString(), const QString &details = QString()); void slotSetIconSize(int size); void selectProxyModel(const QModelIndex &id); void slotSaveHeaders(); void slotItemDropped(const QStringList &ids, const QModelIndex &parent); void slotItemDropped(const QList &urls, const QModelIndex &parent); void slotEffectDropped(const QStringList &effectData, const QModelIndex &parent); void slotItemEdited(const QModelIndex &, const QModelIndex &, const QVector &); /** @brief Reset all text and log data from info message widget. */ void slotResetInfoMessage(); /** @brief Show dialog prompting for removal of invalid clips. */ void slotQueryRemoval(const QString &id, const QString &url, const QString &errorMessage); /** @brief Request display of current clip in monitor. */ void slotOpenCurrent(); void slotZoomView(bool zoomIn); /** @brief Widget gained focus, make sure we display effects for master clip. */ void slotGotFocus(); /** @brief Rename a Bin Item. */ void slotRenameItem(); void slotCreateAudioThumbs(); void doRefreshPanel(const QString &id); /** @brief Send audio thumb data to monitor for display. */ void slotSendAudioThumb(const QString &id); void doRefreshAudioThumbs(const QString &id); /** @brief Enable item view and hide message */ void slotMessageActionTriggered(); /** @brief Request editing of title or slideshow clip */ void slotEditClip(); /** @brief Enable / disable clear button on search line * this is a workaround foq Qt bug 54676 */ void showClearButton(bool show); public slots: void slotRemoveInvalidClip(const QString &id, bool replace, const QString &errorMessage); /** @brief Reload clip thumbnail - when frame for thumbnail changed */ void slotRefreshClipThumbnail(const QString &id); void slotDeleteClip(); void slotItemDoubleClicked(const QModelIndex &ix, const QPoint pos); void slotSwitchClipProperties(std::shared_ptr clip); void slotSwitchClipProperties(); /** @brief Creates a new folder with optional name, and returns new folder's id */ QString slotAddFolder(const QString &folderName = QString()); void slotCreateProjectClip(); void slotEditClipCommand(const QString &id, const QMap &oldProps, const QMap &newProps); /** @brief Start a filter job requested by a filter applied in timeline */ void slotStartFilterJob(const ItemInfo &info, const QString &id, QMap &filterParams, QMap &consumerParams, QMap &extraParams); /** @brief Open current clip in an external editing application */ void slotOpenClip(); void slotDuplicateClip(); void slotLocateClip(); /** @brief Add extra data to a clip. */ void slotAddClipExtraData(const QString &id, const QString &key, const QString &data = QString(), QUndoCommand *groupCommand = nullptr); void slotUpdateClipProperties(const QString &id, const QMap &properties, bool refreshPropertiesPanel); /** @brief Pass some important properties to timeline track producers. */ void updateTimelineProducers(const QString &id, const QMap &passProperties); /** @brief Add effect to active Bin clip (used when double clicking an effect in list). */ void slotAddEffect(QString id, const QStringList &effectData); /** @brief Request current frame from project monitor. * @param clipId is the id of a clip we want to hide from screenshot * @param request true to start capture process, false to end it. It is necessary to emit a false after image is received **/ void slotGetCurrentProjectImage(const QString &clipId, bool request); void slotExpandUrl(const ItemInfo &info, const QString &url, QUndoCommand *command); void abortAudioThumbs(); /** @brief Abort all ongoing operations to prepare close. */ void abortOperations(); void doDisplayMessage(const QString &text, KMessageWidget::MessageType type, const QList &actions = QList()); /** @brief Reset all clip usage to 0 */ void resetUsageCount(); /** @brief Select a clip in the Bin from its id. */ void selectClipById(const QString &id, int frame = -1, const QPoint &zone = QPoint()); void slotAddClipToProject(const QUrl &url); void droppedUrls(const QList &urls, const QStringList &folderInfo = QStringList()); /** @brief Returns the effectstack of a given clip. */ std::shared_ptr getClipEffectStack(int itemId); int getClipDuration(int itemId) const; protected: /* This function is called whenever an item is selected to propagate signals (for ex request to show the clip in the monitor) */ void setCurrent(std::shared_ptr item); void selectClip(const std::shared_ptr &clip); void contextMenuEvent(QContextMenuEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override; private: std::shared_ptr m_itemModel; QAbstractItemView *m_itemView; /** @brief An "Up" item that is inserted in bin when using icon view so that user can navigate up */ std::shared_ptr m_folderUp; BinItemDelegate *m_binTreeViewDelegate; ProjectSortProxyModel *m_proxyModel; QToolBar *m_toolbar; KdenliveDoc *m_doc; QLineEdit *m_searchLine; QToolButton *m_addButton; QMenu *m_extractAudioAction; QMenu *m_transcodeAction; QMenu *m_clipsActionsMenu; QAction *m_inTimelineAction; QAction *m_showDate; QAction *m_showDesc; /** @brief Default view type (icon, tree, ...) */ BinViewType m_listType; /** @brief Default icon size for the views. */ QSize m_iconSize; /** @brief Keeps the column width info of the tree view. */ QByteArray m_headerInfo; QVBoxLayout *m_layout; QDockWidget *m_propertiesDock; QScrollArea *m_propertiesPanel; QSlider *m_slider; Monitor *m_monitor; QIcon m_blankThumb; QMenu *m_menu; QAction *m_openAction; QAction *m_editAction; QAction *m_reloadAction; QAction *m_duplicateAction; QAction *m_locateAction; QAction *m_proxyAction; QAction *m_deleteAction; QAction *m_renameAction; QMenu *m_jobsMenu; QAction *m_cancelJobs; QAction *m_discardCurrentClipJobs; QAction *m_discardPendingJobs; SmallJobLabel *m_infoLabel; /** @brief The info widget for failed jobs. */ BinMessageWidget *m_infoMessage; QStringList m_errorLog; InvalidDialog *m_invalidClipDialog; /** @brief Set to true if widget just gained focus (means we have to update effect stack . */ bool m_gainedFocus; /** @brief List of Clip Ids that want an audio thumb. */ QStringList m_audioThumbsList; QString m_processingAudioThumb; QMutex m_audioThumbMutex; /** @brief Total number of milliseconds to process for audio thumbnails */ long m_audioDuration; /** @brief Total number of milliseconds already processed for audio thumbnails */ long m_processedAudio; /** @brief Indicates whether audio thumbnail creation is running. */ QFuture m_audioThumbsThread; void showClipProperties(std::shared_ptr clip, bool forceRefresh = false); /** @brief Get the QModelIndex value for an item in the Bin. */ QModelIndex getIndexForId(const QString &id, bool folderWanted) const; std::shared_ptr getFirstSelectedClip(); void showTitleWidget(std::shared_ptr clip); void showSlideshowWidget(std::shared_ptr clip); void processAudioThumbs(); signals: void itemUpdated(std::shared_ptr); void producerReady(const QString &id); /** @brief Save folder info into MLT. */ void storeFolder(const QString &folderId, const QString &parentId, const QString &oldParentId, const QString &folderName); void gotFilterJobResults(const QString &, int, int, stringMap, stringMap); /** @brief Trigger timecode format refresh where needed. */ void refreshTimeCode(); /** @brief Request display of effect stack for a Bin clip. */ void requestShowEffectStack(const QString &clipName, std::shared_ptr, QSize frameSize, bool showKeyframes); /** @brief Request that the given clip is displayed in the clip monitor */ void requestClipShow(std::shared_ptr); void displayBinMessage(const QString &, KMessageWidget::MessageType); void displayMessage(const QString &, int, MessageType); void requesteInvalidRemoval(const QString &, const QString &, const QString &); /** @brief Analysis data changed, refresh panel. */ void updateAnalysisData(const QString &); void openClip(std::shared_ptr c, int in = -1, int out = -1); /** @brief Fill context menu with occurrences of this clip in timeline. */ void findInTimeline(const QString &, QList ids = QList()); void clipNameChanged(const QString &); /** @brief A clip was updated, request panel update. */ void refreshPanel(const QString &id); }; #endif diff --git a/src/definitions.h b/src/definitions.h index 917382807..0e81cdfce 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -1,330 +1,330 @@ /*************************************************************************** * Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@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) any later version. * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ #ifndef DEFINITIONS_H #define DEFINITIONS_H #include "effectslist/effectslist.h" #include "gentime.h" #include "kdenlive_debug.h" #include #include #include #include #include const int MAXCLIPDURATION = 15000; namespace Kdenlive { enum MonitorId { NoMonitor = 0x01, ClipMonitor = 0x02, ProjectMonitor = 0x04, RecordMonitor = 0x08, StopMotionMonitor = 0x10, DvdMonitor = 0x20 }; const int DefaultThumbHeight = 100; } // namespace Kdenlive enum class GroupType { Normal, Selection, // in that case, the group is used to emulate a selection AVSplit, // in that case, the group links the audio and video of the same clip Leaf // This is a leaf (clip or composition) }; const QString groupTypeToStr(GroupType t); GroupType groupTypeFromStr(const QString &s); enum class ObjectType { TimelineClip, TimelineComposition, TimelineTrack, BinClip, NoItem }; using ObjectId = std::pair; enum OperationType { None = 0, WaitingForConfirm, MoveOperation, ResizeStart, ResizeEnd, RollingStart, RollingEnd, RippleStart, RippleEnd, FadeIn, FadeOut, TransitionStart, TransitionEnd, MoveGuide, KeyFrame, Seek, Spacer, RubberSelection, ScrollTimeline, ZoomTimeline }; namespace PlaylistState { Q_NAMESPACE enum ClipState { VideoOnly = 1, AudioOnly = 2, Disabled = 3 }; Q_ENUM_NS(ClipState) } // namespace PlaylistState // returns a pair corresponding to (video, audio) std::pair stateToBool(PlaylistState::ClipState state); PlaylistState::ClipState stateFromBool(std::pair av); namespace TimelineMode { enum EditMode { NormalEdit = 0, OverwriteEdit = 1, InsertEdit = 2 }; } namespace ClipType { Q_NAMESPACE enum ProducerType { Unknown = 0, Audio = 1, Video = 2, AV = 3, Color = 4, Image = 5, Text = 6, SlideShow = 7, Virtual = 8, Playlist = 9, WebVfx = 10, TextTemplate = 11, QText }; Q_ENUM_NS(ProducerType) -} +} // namespace ClipType enum ProjectItemType { ProjectClipType = 0, ProjectFolderType, ProjectSubclipType }; enum GraphicsRectItem { AVWidget = 70000, LabelWidget, TransitionWidget, GroupWidget }; enum ProjectTool { SelectTool = 0, RazorTool = 1, SpacerTool = 2 }; enum MonitorSceneType { MonitorSceneNone = 0, MonitorSceneDefault, MonitorSceneGeometry, MonitorSceneCorners, MonitorSceneRoto, MonitorSceneSplit, MonitorSceneRipple }; enum MessageType { DefaultMessage, ProcessingJobMessage, OperationCompletedMessage, InformationMessage, ErrorMessage, MltError }; enum TrackType { AudioTrack = 0, VideoTrack = 1, AnyTrack = 2 }; enum CacheType { SystemCacheRoot = -1, CacheRoot = 0, CacheBase = 1, CachePreview = 2, CacheProxy = 3, CacheAudio = 4, CacheThumbs = 5 }; enum TrimMode { NormalTrim, RippleTrim, RollingTrim, SlipTrim, SlideTrim }; class TrackInfo { public: TrackType type; QString trackName; bool isMute; bool isBlind; bool isLocked; int duration; EffectsList effectsList; TrackInfo() : type(VideoTrack) , isMute(0) , isBlind(0) , isLocked(0) , duration(0) , effectsList(true) { } }; struct requestClipInfo { QDomElement xml; QString clipId; int imageHeight; bool replaceProducer; bool operator==(const requestClipInfo &a) const { return clipId == a.clipId; } }; typedef QMap stringMap; typedef QMap> audioByteArray; typedef QVector audioShortVector; class ItemInfo { public: /** startPos is the position where the clip starts on the track */ GenTime startPos; /** endPos is the duration where the clip ends on the track */ GenTime endPos; /** cropStart is the position where the sub-clip starts, relative to the clip's 0 position */ GenTime cropStart; /** cropDuration is the duration of the clip */ GenTime cropDuration; /** Track number */ int track; ItemInfo() : track(0) { } bool isValid() const { return startPos != endPos; } bool contains(GenTime pos) const { if (startPos == endPos) { return true; } return (pos <= endPos && pos >= startPos); } bool operator==(const ItemInfo &a) const { return startPos == a.startPos && endPos == a.endPos && track == a.track && cropStart == a.cropStart; } }; class TransitionInfo { public: /** startPos is the position where the clip starts on the track */ GenTime startPos; /** endPos is the duration where the clip ends on the track */ GenTime endPos; /** the track on which the transition is (b_track)*/ int b_track; /** the track on which the transition is applied (a_track)*/ int a_track; /** Does the user request for a special a_track */ bool forceTrack; TransitionInfo() : b_track(0) , a_track(0) , forceTrack(0) { } }; class CommentedTime { public: CommentedTime(); CommentedTime(const GenTime &time, const QString &comment, int markerType = 0); CommentedTime(const QString &hash, const GenTime &time); QString comment() const; GenTime time() const; /** @brief Returns a string containing infos needed to store marker info. string equals marker type + QLatin1Char(':') + marker comment */ QString hash() const; void setComment(const QString &comm); void setMarkerType(int t); int markerType() const; static QColor markerColor(int type); /* Implementation of > operator; Works identically as with basic types. */ bool operator>(const CommentedTime &op) const; /* Implementation of < operator; Works identically as with basic types. */ bool operator<(const CommentedTime &op) const; /* Implementation of >= operator; Works identically as with basic types. */ bool operator>=(const CommentedTime &op) const; /* Implementation of <= operator; Works identically as with basic types. */ bool operator<=(const CommentedTime &op) const; /* Implementation of == operator; Works identically as with basic types. */ bool operator==(const CommentedTime &op) const; /* Implementation of != operator; Works identically as with basic types. */ bool operator!=(const CommentedTime &op) const; private: GenTime m_time; QString m_comment; int m_type; }; QDebug operator<<(QDebug qd, const ItemInfo &info); // we provide hash function for qstring and QPersistentModelIndex namespace std { template <> struct hash { std::size_t operator()(const QString &k) const { return qHash(k); } }; template <> struct hash { std::size_t operator()(const QPersistentModelIndex &k) const { return qHash(k); } }; } // namespace std // The following is a hack that allows to use shared_from_this in the case of a multiple inheritance. // Credit: https://stackoverflow.com/questions/14939190/boost-shared-from-this-and-multiple-inheritance template struct enable_shared_from_this_virtual; class enable_shared_from_this_virtual_base : public std::enable_shared_from_this { typedef std::enable_shared_from_this base_type; template friend struct enable_shared_from_this_virtual; std::shared_ptr shared_from_this() { return base_type::shared_from_this(); } std::shared_ptr shared_from_this() const { return base_type::shared_from_this(); } }; template struct enable_shared_from_this_virtual : virtual enable_shared_from_this_virtual_base { typedef enable_shared_from_this_virtual_base base_type; public: std::shared_ptr shared_from_this() { std::shared_ptr result(base_type::shared_from_this(), static_cast(this)); return result; } std::shared_ptr shared_from_this() const { std::shared_ptr result(base_type::shared_from_this(), static_cast(this)); return result; } }; // This is a small trick to have a QAbstractItemModel with shared_from_this enabled without multiple inheritance // Be careful, if you use this class, you have to make sure to init weak_this_ when you construct a shared_ptr to your object template class QAbstractItemModel_shared_from_this : public QAbstractItemModel { protected: QAbstractItemModel_shared_from_this() : QAbstractItemModel() { } public: std::shared_ptr shared_from_this() { std::shared_ptr p(weak_this_); assert(p.get() == this); return p; } std::shared_ptr shared_from_this() const { std::shared_ptr p(weak_this_); assert(p.get() == this); return p; } public: // actually private, but avoids compiler template friendship issues mutable std::weak_ptr weak_this_; }; #endif diff --git a/src/dialogs/renderwidget.h b/src/dialogs/renderwidget.h index 8965432a2..bfb740644 100644 --- a/src/dialogs/renderwidget.h +++ b/src/dialogs/renderwidget.h @@ -1,240 +1,242 @@ /*************************************************************************** * Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@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) any later version. * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ #ifndef RENDERWIDGET_H #define RENDERWIDGET_H #include #include #include #include #ifdef KF5_USE_PURPOSE -namespace Purpose { class Menu; } +namespace Purpose { +class Menu; +} #endif #include "definitions.h" #include "ui_renderwidget_ui.h" class QDomElement; class QKeyEvent; // RenderViewDelegate is used to draw the progress bars. class RenderViewDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit RenderViewDelegate(QWidget *parent) : QStyledItemDelegate(parent) { } void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { if (index.column() == 1) { painter->save(); QStyleOptionViewItem opt(option); QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget); QFont font = painter->font(); font.setBold(true); painter->setFont(font); QRect r1 = option.rect; r1.adjust(0, textMargin, 0, -textMargin); int mid = (int)((r1.height() / 2)); r1.setBottom(r1.y() + mid); QRect bounding; painter->drawText(r1, Qt::AlignLeft | Qt::AlignTop, index.data().toString(), &bounding); r1.moveTop(r1.bottom() - textMargin); font.setBold(false); painter->setFont(font); painter->drawText(r1, Qt::AlignLeft | Qt::AlignTop, index.data(Qt::UserRole).toString()); int progress = index.data(Qt::UserRole + 3).toInt(); if (progress > 0 && progress < 100) { // draw progress bar QColor color = option.palette.alternateBase().color(); QColor fgColor = option.palette.text().color(); color.setAlpha(150); fgColor.setAlpha(150); painter->setBrush(QBrush(color)); painter->setPen(QPen(fgColor)); int width = qMin(200, r1.width() - 4); QRect bgrect(r1.left() + 2, option.rect.bottom() - 6 - textMargin, width, 6); painter->drawRoundedRect(bgrect, 3, 3); painter->setBrush(QBrush(fgColor)); bgrect.adjust(2, 2, 0, -1); painter->setPen(Qt::NoPen); bgrect.setWidth((width - 2) * progress / 100); painter->drawRect(bgrect); } else { r1.setBottom(opt.rect.bottom()); r1.setTop(r1.bottom() - mid); painter->drawText(r1, Qt::AlignLeft | Qt::AlignBottom, index.data(Qt::UserRole + 5).toString()); } painter->restore(); } else { QStyledItemDelegate::paint(painter, option, index); } } }; class RenderJobItem : public QTreeWidgetItem { public: explicit RenderJobItem(QTreeWidget *parent, const QStringList &strings, int type = QTreeWidgetItem::Type); void setStatus(int status); int status() const; void setMetadata(const QString &data); const QString metadata() const; void render(); private: int m_status; QString m_data; }; class RenderWidget : public QDialog { Q_OBJECT public: explicit RenderWidget(const QString &projectfolder, bool enableProxy, QWidget *parent = nullptr); virtual ~RenderWidget(); void setGuides(const QList &guidesList, double duration); void focusFirstVisibleItem(const QString &profile = QString()); void setRenderJob(const QString &dest, int progress = 0); void setRenderStatus(const QString &dest, int status, const QString &error); void setDocumentPath(const QString &path); void reloadProfiles(); void setRenderProfile(const QMap &props); int waitingJobsCount() const; QString getFreeScriptName(const QUrl &projectName = QUrl(), const QString &prefix = QString()); bool startWaitingRenderJobs(); /** @brief Returns true if the export audio checkbox is set to automatic. */ bool automaticAudioExport() const; /** @brief Returns true if user wants audio export. */ bool selectedAudioExport() const; /** @brief Show / hide proxy settings. */ void updateProxyConfig(bool enable); /** @brief Should we render using proxy clips. */ bool proxyRendering(); /** @brief Returns true if the stem audio export checkbox is set. */ bool isStemAudioExportEnabled() const; enum RenderError { CompositeError = 0, ProfileError = 1, ProxyWarning = 2, PlaybackError = 3 }; /** @brief Display warning message in render widget. */ void errorMessage(RenderError type, const QString &message); protected: QSize sizeHint() const override; void keyPressEvent(QKeyEvent *e) override; public slots: void slotExport(bool scriptExport, int zoneIn, int zoneOut, const QMap &metadata, const QList &playlistPaths, const QList &trackNames, const QString &scriptPath, bool exportAudio); void slotAbortCurrentJob(); void slotPrepareExport(bool scriptExport = false, const QString &scriptPath = QString()); void adjustViewToProfile(); private slots: void slotUpdateButtons(const QUrl &url); void slotUpdateButtons(); void refreshView(); /** @brief Updates available options when a new format has been selected. */ void refreshParams(); void slotSaveProfile(); void slotEditProfile(); void slotDeleteProfile(bool dontRefresh = false); void slotUpdateGuideBox(); void slotCheckStartGuidePosition(); void slotCheckEndGuidePosition(); void showInfoPanel(); void slotStartScript(); void slotDeleteScript(); void slotGenerateScript(); void parseScriptFiles(); void slotCheckScript(); void slotCheckJob(); void slotEditItem(QTreeWidgetItem *item); void slotCLeanUpJobs(); void slotHideLog(); void slotPlayRendering(QTreeWidgetItem *item, int); void slotStartCurrentJob(); void slotCopyToFavorites(); void slotUpdateEncodeThreads(int); void slotUpdateRescaleHeight(int); void slotUpdateRescaleWidth(int); void slotSwitchAspectRatio(); /** @brief Update export audio label depending on current settings. */ void slotUpdateAudioLabel(int ix); /** @brief Enable / disable the rescale options. */ void setRescaleEnabled(bool enable); /** @brief Adjust video/audio quality spinboxes from quality slider. */ void adjustAVQualities(int quality); /** @brief Adjust quality slider from video spinbox. */ void adjustQuality(int videoQuality); /** @brief Show updated command parameter in tooltip. */ void adjustSpeed(int videoQuality); /** @brief Display warning on proxy rendering. */ void slotProxyWarn(bool enableProxy); /** @brief User shared a rendered file, give feedback. */ void slotShareActionFinished(const QJsonObject &output, int error, const QString &message); private: Ui::RenderWidget_UI m_view; QString m_projectFolder; RenderViewDelegate *m_scriptsDelegate; RenderViewDelegate *m_jobsDelegate; bool m_blockProcessing; QString m_renderer; KMessageWidget *m_infoMessage; KMessageWidget *m_jobInfoMessage; QMap m_errorMessages; #ifdef KF5_USE_PURPOSE Purpose::Menu *m_shareMenu; #endif void parseMltPresets(); void parseProfiles(const QString &selectedProfile = QString()); void parseFile(const QString &exportFile, bool editable); void updateButtons(); QUrl filenameWithExtension(QUrl url, const QString &extension); /** @brief Check if a job needs to be started. */ void checkRenderStatus(); void startRendering(RenderJobItem *item); bool saveProfile(QDomElement newprofile); /** @brief Create a rendering profile from MLT preset. */ QTreeWidgetItem *loadFromMltPreset(const QString &groupName, const QString &path, const QString &profileName); void checkCodecs(); signals: void abortProcess(const QString &url); void openDvdWizard(const QString &url); /** Send the info about rendering that will be saved in the document: (profile destination, profile name and url of rendered file */ void selectedRenderProfile(const QMap &renderProps); void prepareRenderingData(bool scriptExport, bool zoneOnly, const QString &chapterFile, const QString scriptPath); void shutdown(); }; #endif diff --git a/src/effectstack/widgets/colorwheel.h b/src/effectstack/widgets/colorwheel.h index b79cf0611..13ecdc0a9 100644 --- a/src/effectstack/widgets/colorwheel.h +++ b/src/effectstack/widgets/colorwheel.h @@ -1,97 +1,97 @@ /* * Copyright (c) 2013 Meltytech, LLC * Author: Dan Dennedy * * 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 3 of the License, or * (at your option) any later version. * * 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 . */ #ifndef COLORWHEEL_H #define COLORWHEEL_H #include #include #include class NegQColor { public: - int8_t sign_r=1; - int8_t sign_g=1; - int8_t sign_b=1; + int8_t sign_r = 1; + int8_t sign_g = 1; + int8_t sign_b = 1; QColor qcolor; static NegQColor fromHsvF(qreal h, qreal s, qreal l, qreal a = 1.0); static NegQColor fromRgbF(qreal r, qreal g, qreal b, qreal a = 1.0); qreal redF(); qreal greenF(); qreal blueF(); qreal valueF(); int hue(); qreal hueF(); qreal saturationF(); }; class ColorWheel : public QWidget { Q_OBJECT public: explicit ColorWheel(const QString &id, const QString &name, const NegQColor &color, QWidget *parent = nullptr); QSize sizeHint() const override; QSize minimumSizeHint() const override; QColor color(); void setColor(const QColor &color); signals: void colorChange(const NegQColor &color); public slots: void changeColor(const NegQColor &color); protected: void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void resizeEvent(QResizeEvent *event) override; void paintEvent(QPaintEvent *event) override; private: QString m_id; QSize m_initialSize; QImage m_image; bool m_isMouseDown; QPoint m_lastPoint; int m_margin; int m_sliderWidth; QRegion m_wheelRegion; QRegion m_sliderRegion; NegQColor m_color; bool m_isInWheel; bool m_isInSquare; int m_unitSize; QString m_name; qreal m_sizeFactor = 1; qreal m_defaultValue = 1; qreal m_zeroShift = 0; int wheelSize() const; NegQColor colorForPoint(const QPoint &point); void drawWheel(); void drawWheelDot(QPainter &painter); void drawSliderBar(QPainter &painter); void drawSlider(); QString getParamValues(); }; #endif // COLORWHEEL_H diff --git a/src/jobs/thumbjob.hpp b/src/jobs/thumbjob.hpp index 2e4eb063b..8926e3865 100644 --- a/src/jobs/thumbjob.hpp +++ b/src/jobs/thumbjob.hpp @@ -1,70 +1,70 @@ /*************************************************************************** * Copyright (C) 2017 by Nicolas Carion * * 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 . * ***************************************************************************/ #pragma once #include "abstractclipjob.h" -#include #include +#include /* @brief This class represents the job that corresponds to computing the thumb of a clip */ class ProjectClip; namespace Mlt { class Producer; } class ThumbJob : public AbstractClipJob { Q_OBJECT public: /* @brief Extract a thumb for given clip. @param frameNumber is the frame to extract. Leave to -1 for default @param persistent: if true, we will use the persistent cache (for query and saving) */ ThumbJob(const QString &binId, int imageHeight, int frameNumber = -1, bool persistent = false, bool reloadAllThumbs = false); const QString getDescription() const override; bool startJob() override; /** @brief This is to be called after the job finished. By design, the job should store the result of the computation but not share it with the rest of the code. This happens when we call commitResult */ bool commitResult(Fun &undo, Fun &redo) override; private: int m_frameNumber; int m_fullWidth; int m_imageHeight; std::shared_ptr m_binClip; std::shared_ptr m_prod; QImage m_result; bool m_done{false}; bool m_persistent; bool m_reloadAll; bool m_inCache{false}; bool m_subClip{false}; // true if we operate on a subclip }; diff --git a/src/mltcontroller/effectscontroller.h b/src/mltcontroller/effectscontroller.h index c73c0e8c6..0502d5647 100644 --- a/src/mltcontroller/effectscontroller.h +++ b/src/mltcontroller/effectscontroller.h @@ -1,118 +1,118 @@ /* Copyright (C) 2015 Jean-Baptiste Mardelle 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 . */ #ifndef EFFECTSCONTROLLER_H #define EFFECTSCONTROLLER_H #include "definitions.h" -#include #include +#include #include /**) * @class EffectInfo * @brief A class holding some meta info for effects widgets, like state (collapsed or not, ...) * @author Jean-Baptiste Mardelle */ class EffectInfo { public: EffectInfo(); bool isCollapsed; bool groupIsCollapsed; int groupIndex; QString groupName; QString toString() const; void fromString(const QString &value); }; /**) * @class EffectParameter * @brief Base class holding a parameter name / value. Is this really useful? QMap ? * @author Jean-Baptiste Mardelle */ class EffectParameter { public: EffectParameter(const QString &name, const QString &value); QString name() const; QString value() const; void setValue(const QString &value); private: QString m_name; QString m_value; }; /**) * @class EffectsParameterList * @brief Use our own list for effect parameters so that they are not sorted in any ways, because * some effects like sox need a precise order * @author Jean-Baptiste Mardelle */ class EffectsParameterList : public QList { public: EffectsParameterList(); bool hasParam(const QString &name) const; QString paramValue(const QString &name, const QString &defaultValue = QString()) const; void addParam(const QString &name, const QString &value); void removeParam(const QString &name); }; /** * @namespace EffectsController * @brief Provides convenience methods to manage effects and convert between MLT's Filter format and Kdenlive's internal formats (xml or lists). */ namespace EffectsController { /** @brief Gets the effect parameters that will be passed to Mlt. */ EffectsParameterList getEffectArgs(const QDomElement &effect); /** @brief Get effect parameters ready for MLT*/ void adjustEffectParameters(EffectsParameterList ¶meters, const QDomNodeList ¶ms, const QString &prefix = QString()); /** @brief Returns an value from a string by replacing "%width" and "%height" with given profile values: * @param info The struct that gives width & height * @param eval The string to be evaluated, for example: "%width / 2" * @return the evaluated value */ double getStringEval(QString eval, const QPoint &frameSize = QPoint()); QString getStringRectEval(QString eval); /** @brief Initialize some track effects parameters */ void initTrackEffect(const QDomElement &effect); /** @brief Initialize some effects parameters: keyframes, fades, in / out points */ void initEffect(const ItemInfo &info, const EffectsList &list, const QString &proxy, QDomElement effect, int diff = 0, int offset = 0); /** @brief Adjust keyframes to the new clip. */ const QString adjustKeyframes(const QString &keyframes, int oldIn, int newIn, int newEnd); EffectsParameterList addEffect(const QDomElement &effect); /** @brief Keyframe frame numbers are relative to clip's crop start. So when saving an effect, remove clip cropstart from keyframe numbers so that when we apply * effect on another clip, frame numbers are applied relative to the new clip's crop start. */ void offsetKeyframes(int in, const QDomElement &effect); } // namespace EffectsController #endif diff --git a/src/monitor/monitorproxy.h b/src/monitor/monitorproxy.h index 33b45a085..115edfe2a 100644 --- a/src/monitor/monitorproxy.h +++ b/src/monitor/monitorproxy.h @@ -1,105 +1,104 @@ /*************************************************************************** * Copyright (C) 2018 by Jean-Baptiste Mardelle (jb@kdenlive.org) * * 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 . * ***************************************************************************/ - -/** @brief This class is a wrapper around the monitor / glwidget and handles communication +/** @brief This class is a wrapper around the monitor / glwidget and handles communication * with the qml overlay through its properties. */ #ifndef MONITORPROXY_H #define MONITORPROXY_H -#include #include +#include class GLWidget; class MonitorProxy : public QObject { Q_OBJECT // Q_PROPERTY(int consumerPosition READ consumerPosition NOTIFY consumerPositionChanged) Q_PROPERTY(int position READ position NOTIFY positionChanged) Q_PROPERTY(int seekPosition READ seekPosition WRITE setSeekPosition NOTIFY seekPositionChanged) Q_PROPERTY(int zoneIn READ zoneIn WRITE setZoneIn NOTIFY zoneChanged) Q_PROPERTY(int zoneOut READ zoneOut WRITE setZoneOut NOTIFY zoneChanged) Q_PROPERTY(int rulerHeight READ rulerHeight NOTIFY rulerHeightChanged) Q_PROPERTY(QString markerComment READ markerComment NOTIFY markerCommentChanged) Q_PROPERTY(int overlayType READ overlayType WRITE setOverlayType NOTIFY overlayTypeChanged) public: MonitorProxy(GLWidget *parent); int seekPosition() const; /** brief: Returns true if we are still in a seek operation * */ bool seeking() const; int position() const; int rulerHeight() const; int overlayType() const; void setOverlayType(int ix); QString markerComment() const; Q_INVOKABLE void requestSeekPosition(int pos); /** brief: Returns seek position or consumer position when not seeking * */ int seekOrCurrentPosition() const; void setPosition(int pos, bool *seekStopped); void setMarkerComment(const QString &comment); void setSeekPosition(int pos); void pauseAndSeek(int pos); int zoneIn() const; int zoneOut() const; void setZoneIn(int pos); void setZoneOut(int pos); Q_INVOKABLE void setZone(int in, int out); /** brief: Activate clip monitor if param is true, project monitor otherwise * */ Q_INVOKABLE void activateClipMonitor(bool isClipMonitor); void setZone(QPoint zone); void resetZone(); QPoint zone() const; QImage extractFrame(int frame_position, const QString &path = QString(), int width = -1, int height = -1, bool useSourceProfile = false); Q_INVOKABLE QString toTimecode(int frames) const; signals: void positionChanged(); void seekPositionChanged(); void seekRequestChanged(); void zoneChanged(); void markerCommentChanged(); void rulerHeightChanged(); void addSnap(int); void removeSnap(int); void triggerAction(const QString &name); void overlayTypeChanged(); void seekNextKeyframe(); void seekPreviousKeyframe(); void addRemoveKeyframe(); void seekToKeyframe(); private: GLWidget *q; int m_position; int m_seekPosition; int m_zoneIn; int m_zoneOut; QString m_markerComment; }; #endif diff --git a/src/project/dialogs/noteswidget.h b/src/project/dialogs/noteswidget.h index 33efa8518..81d1b244d 100644 --- a/src/project/dialogs/noteswidget.h +++ b/src/project/dialogs/noteswidget.h @@ -1,51 +1,52 @@ /*************************************************************************** * Copyright (C) 2011 by Jean-Baptiste Mardelle (jb@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) any later version. * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ #ifndef NOTESWIDGET_H #define NOTESWIDGET_H #include /** * @class NotesWidget * @brief A small text editor to create project notes. * @author Jean-Baptiste Mardelle */ class NotesWidget : public QTextEdit { Q_OBJECT public: explicit NotesWidget(QWidget *parent = nullptr); ~NotesWidget(); /** @brief insert current timeline timecode and focus widget to allow entering quick note */ void addProjectNote(); + protected: void mouseMoveEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override; private slots: void slotFillNotesMenu(const QPoint &pos); signals: void insertNotesTimecode(); void seekProject(int); }; #endif diff --git a/src/project/dialogs/temporarydata.h b/src/project/dialogs/temporarydata.h index aa1481651..0f79f48dd 100644 --- a/src/project/dialogs/temporarydata.h +++ b/src/project/dialogs/temporarydata.h @@ -1,148 +1,148 @@ /* Copyright (C) 2016 Jean-Baptiste Mardelle 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 . */ #ifndef TEMPORARYDATA_H #define TEMPORARYDATA_H #include "definitions.h" #include #include -#include #include +#include class KdenliveDoc; class QPaintEvent; class QLabel; class QGridLayout; class QTreeWidget; class QPushButton; /** * @class ChartWidget * @brief Chart drawing widget. * */ class ChartWidget : public QWidget { public: explicit ChartWidget(QWidget *parent = nullptr); void setSegments(const QList &segments); protected: void paintEvent(QPaintEvent *event) override; private: QList m_segments; }; /** * @class TreeWidgetItem * @brief Manage custom sort order for size. * */ class TreeWidgetItem : public QTreeWidgetItem { public: TreeWidgetItem(QTreeWidget *parent) : QTreeWidgetItem(parent) { } private: bool operator<(const QTreeWidgetItem &other) const override { int column = treeWidget()->sortColumn(); switch (column) { case 0: return text(column).toLower() < other.text(column).toLower(); break; default: return data(column, Qt::UserRole) < other.data(column, Qt::UserRole); break; } } }; /** * @class TemporaryData * @brief Dialog allowing management of project's temporary data. * */ class TemporaryData : public QWidget { Q_OBJECT public: explicit TemporaryData(KdenliveDoc *doc, bool currentProjectOnly, QWidget *parent = nullptr); private: KdenliveDoc *m_doc; ChartWidget *m_currentPie; ChartWidget *m_globalPie; QLabel *m_previewSize; QLabel *m_proxySize; QLabel *m_audioSize; QLabel *m_thumbSize; QLabel *m_currentSize; QLabel *m_globalSize; QLabel *m_selectedSize; QWidget *m_currentPage; QWidget *m_globalPage; QTreeWidget *m_listWidget; QGridLayout *m_grid; KIO::filesize_t m_totalCurrent; KIO::filesize_t m_totalGlobal; QList mCurrentSizes; QList mGlobalSizes; QStringList m_globalDirectories; QString m_processingDirectory; QDir m_globalDir; QStringList m_proxies; QPushButton *m_globalDelete; void updateDataInfo(); void updateGlobalInfo(); void updateTotal(); void buildGlobalCacheDialog(int minHeight); void processglobalDirectories(); private slots: void gotPreviewSize(KJob *job); void gotProxySize(KIO::filesize_t total); void gotAudioSize(KJob *job); void gotThumbSize(KJob *job); void gotFolderSize(KJob *job); void refreshGlobalPie(); void deletePreview(); void deleteProxy(); void deleteAudio(); void deleteThumbs(); void deleteCurrentCacheData(); void openCacheFolder(); void deleteSelected(); signals: void disableProxies(); void disablePreview(); }; #endif diff --git a/src/timeline2/model/clipmodel.hpp b/src/timeline2/model/clipmodel.hpp index 74634e4f7..ab7d34100 100644 --- a/src/timeline2/model/clipmodel.hpp +++ b/src/timeline2/model/clipmodel.hpp @@ -1,196 +1,198 @@ /*************************************************************************** * Copyright (C) 2017 by Nicolas Carion * * 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 . * ***************************************************************************/ #ifndef CLIPMODEL_H #define CLIPMODEL_H #include "moveableItem.hpp" #include "undohelper.hpp" #include #include namespace Mlt { class Producer; } class EffectStackModel; class MarkerListModel; class ProjectClip; class TimelineModel; class TrackModel; class KeyframeModel; /* @brief This class represents a Clip object, as viewed by the backend. In general, the Gui associated with it will send modification queries (such as resize or move), and this class authorize them or not depending on the validity of the modifications */ class ClipModel : public MoveableItem { ClipModel() = delete; protected: /* This constructor is not meant to be called, call the static construct instead */ ClipModel(std::shared_ptr parent, std::shared_ptr prod, const QString &binClipId, int id, PlaylistState::ClipState state, double speed = 1.); public: ~ClipModel(); /* @brief Creates a clip, which references itself to the parent timeline Returns the (unique) id of the created clip @param parent is a pointer to the timeline @param binClip is the id of the bin clip associated @param id Requested id of the clip. Automatic if -1 */ static int construct(const std::shared_ptr &parent, const QString &binClipId, int id, PlaylistState::ClipState state); /* @brief Creates a clip, which references itself to the parent timeline Returns the (unique) id of the created clip This variants assumes a producer is already known, which should typically happen only at loading time. Note that there is no guarantee that this producer is actually going to be used. It might be discarded. */ static int construct(const std::shared_ptr &parent, const QString &binClipId, std::shared_ptr producer, PlaylistState::ClipState state); /* @brief returns a property of the clip, or from it's parent if it's a cut */ const QString getProperty(const QString &name) const override; int getIntProperty(const QString &name) const; double getDoubleProperty(const QString &name) const; QSize getFrameSize() const; Q_INVOKABLE bool showKeyframes() const; Q_INVOKABLE void setShowKeyframes(bool show); /* @brief Returns true if the clip can be converted to a video clip */ bool canBeVideo() const; /* @brief Returns true if the clip can be converted to an audio clip */ bool canBeAudio() const; /** @brief Returns the timeline clip status (video / audio only) */ PlaylistState::ClipState clipState() const; /** @brief Returns the bin clip type (image, color, AV, ...) */ ClipType::ProducerType clipType() const; /** @brief Sets the timeline clip status (video / audio only) */ bool setClipState(PlaylistState::ClipState state, Fun &undo, Fun &redo); protected: // helper fuctions that creates the lambda Fun setClipState_lambda(PlaylistState::ClipState state); public: /* @brief returns the length of the item on the timeline */ int getPlaytime() const override; /** @brief Returns audio cache data from bin clip to display audio thumbs */ QVariant getAudioWaveform(); /** @brief Returns the bin clip's id */ const QString &binId() const; void registerClipToBin(); void deregisterClipToBin(); bool addEffect(const QString &effectId); bool copyEffect(std::shared_ptr stackModel, int rowId); /* @brief Import effects from a different stackModel */ bool importEffects(std::shared_ptr stackModel); /* @brief Import effects from a service that contains some (another clip?) */ bool importEffects(std::weak_ptr service); bool removeFade(bool fromStart); /** @brief Adjust effects duration. Should be called after each resize / cut operation */ bool adjustEffectLength(bool adjustFromEnd, int oldIn, int newIn, int oldDuration, int duration, Fun &undo, Fun &redo, bool logUndo); bool adjustEffectLength(const QString &effectName, int duration, int originalDuration, Fun &undo, Fun &redo); void passTimelineProperties(std::shared_ptr other); KeyframeModel *getKeyframeModel(); int fadeIn() const; int fadeOut() const; friend class TrackModel; friend class TimelineModel; friend class TimelineItemModel; friend class TimelineController; friend struct TimelineFunctions; protected: Mlt::Producer *service() const override; /* @brief Performs a resize of the given clip. Returns true if the operation succeeded, and otherwise nothing is modified This method is protected because it shouldn't be called directly. Call the function in the timeline instead. If a snap point is within reach, the operation will be coerced to use it. @param size is the new size of the clip @param right is true if we change the right side of the clip, false otherwise @param undo Lambda function containing the current undo stack. Will be updated with current operation @param redo Lambda function containing the current redo queue. Will be updated with current operation */ bool requestResize(int size, bool right, Fun &undo, Fun &redo, bool logUndo = true) override; /* @brief Performs a resize of the given clip. Returns true if the operation succeeded, and otherwise nothing is modified - This method should only be called if some operation before the resize did alter the previous duration, like when using timewarp operation. Otherwise the normal requestResize should be used with only size passed. + This method should only be called if some operation before the resize did alter the previous duration, like when using timewarp operation. Otherwise the + normal requestResize should be used with only size passed. */ bool requestResize(int old_in, int old_out, int oldDuration, int delta, bool right, Fun &undo, Fun &redo, bool logUndo); /* @brief This function change the global (timeline-wise) enabled state of the effects */ void setTimelineEffectsEnabled(bool enabled); /* @brief This functions should be called when the producer of the binClip changes, to allow refresh * @param state corresponds to the state of the clip we want (audio or video) - * @param speed corresponds to the speed we need. Leave to 0 to keep current speed. Warning: this function doesn't notify the model. Unless you know what you are doing, better use uteTimewarProducer to change the speed + * @param speed corresponds to the speed we need. Leave to 0 to keep current speed. Warning: this function doesn't notify the model. Unless you know what + * you are doing, better use uteTimewarProducer to change the speed */ void refreshProducerFromBin(PlaylistState::ClipState state, double speed = 0); void refreshProducerFromBin(); /* @brief This functions replaces the current producer with a slowmotion one It also resizes the producer so that set of frames contained in the clip is the same */ bool useTimewarpProducer(double speed, int extraSpace, Fun &undo, Fun &redo); // @brief Lambda that merely changes the speed (in and out are untouched) Fun useTimewarpProducer_lambda(double speed); /** @brief Returns the marker model associated with this clip */ std::shared_ptr getMarkerModel() const; bool audioEnabled() const; bool isAudioOnly() const; double getSpeed() const; protected: std::shared_ptr m_producer; std::shared_ptr m_effectStack; QString m_binClipId; // This is the Id of the bin clip this clip corresponds to. bool m_endlessResize; // Whether this clip can be freely resized bool forceThumbReload; // Used to trigger a forced thumb reload, when producer changes PlaylistState::ClipState m_currentState; ClipType::ProducerType m_clipType; double m_speed = -1; // Speed of the clip bool m_canBeVideo, m_canBeAudio; }; #endif diff --git a/src/timeline2/model/timelinemodel.hpp b/src/timeline2/model/timelinemodel.hpp index 902f031c3..10909208b 100644 --- a/src/timeline2/model/timelinemodel.hpp +++ b/src/timeline2/model/timelinemodel.hpp @@ -1,687 +1,688 @@ /*************************************************************************** * Copyright (C) 2017 by Nicolas Carion * * 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 . * ***************************************************************************/ #ifndef TIMELINEMODEL_H #define TIMELINEMODEL_H #include "definitions.h" #include "undohelper.hpp" #include #include #include #include #include #include #include #include //#define LOGGING 1 // If set to 1, we log the actions requested to the timeline as a reproducer script #ifdef LOGGING #include #endif class AssetParameterModel; class EffectStackModel; class ClipModel; class CompositionModel; class DocUndoStack; class GroupsModel; class SnapModel; class TimelineItemModel; class TrackModel; /* @brief This class represents a Timeline object, as viewed by the backend. In general, the Gui associated with it will send modification queries (such as resize or move), and this class authorize them or not depending on the validity of the modifications. This class also serves to keep track of all objects. It holds pointers to all tracks and clips, and gives them unique IDs on creation. These Ids are used in any interactions with the objects and have nothing to do with Melt IDs. This is the entry point for any modifications that has to be made on an element. The dataflow beyond this entry point may vary, for example when the user request a clip resize, the call is deferred to the clip itself, that check if there is enough data to extend by the requested amount, compute the new in and out, and then asks the track if there is enough room for extension. To avoid any confusion on which function to call first, rembember to always call the version in timeline. This is also required to generate the Undo/Redo operators Generally speaking, we don't check ahead of time if an action is going to succeed or not before applying it. We just apply it naively, and if it fails at some point, we use the undo operator that we are constructing on the fly to revert what we have done so far. For example, when we move a group of clips, we apply the move operation to all the clips inside this group (in the right order). If none fails, we are good, otherwise we revert what we've already done. This kind of behaviour frees us from the burden of simulating the actions before actually applying theme. This is a good thing because this simulation step would be very sensitive to corruptions and small discrepancies, which we try to avoid at all cost. It derives from AbstractItemModel (indirectly through TimelineItemModel) to provide the model to the QML interface. An itemModel is organized with row and columns that contain the data. It can be hierarchical, meaning that a given index (row,column) can contain another level of rows and column. Our organization is as follows: at the top level, each row contains a track. These rows are in the same order as in the actual timeline. Then each of this row contains itself sub-rows that correspond to the clips. Here the order of these sub-rows is unrelated to the chronological order of the clips, but correspond to their Id order. For example, if you have three clips, with ids 12, 45 and 150, they will receive row index 0,1 and 2. This is because the order actually doesn't matter since the clips are rendered based on their positions rather than their row order. The id order has been choosed because it is consistant with a valid ordering of the clips. The columns are never used, so the data is always in column 0 An ModelIndex in the ItemModel consists of a row number, a column number, and a parent index. In our case, tracks have always an empty parent, and the clip have a track index as parent. A ModelIndex can also store one additional integer, and we exploit this feature to store the unique ID of the object it corresponds to. */ class TimelineModel : public QAbstractItemModel_shared_from_this { Q_OBJECT protected: /* @brief this constructor should not be called. Call the static construct instead */ TimelineModel(Mlt::Profile *profile, std::weak_ptr undo_stack); public: friend class TrackModel; template friend class MoveableItem; friend class ClipModel; friend class CompositionModel; friend class GroupsModel; friend class TimelineController; friend struct TimelineFunctions; /// Two level model: tracks and clips on track enum { NameRole = Qt::UserRole + 1, - ResourceRole, /// clip only - ServiceRole, /// clip only - IsBlankRole, /// clip only - StartRole, /// clip only - BinIdRole, /// clip only - MarkersRole, /// clip only - StatusRole, /// clip only - TypeRole, /// clip only + ResourceRole, /// clip only + ServiceRole, /// clip only + IsBlankRole, /// clip only + StartRole, /// clip only + BinIdRole, /// clip only + MarkersRole, /// clip only + StatusRole, /// clip only + TypeRole, /// clip only KeyframesRole, DurationRole, - InPointRole, /// clip only - OutPointRole, /// clip only - FramerateRole, /// clip only - GroupedRole, /// clip only - HasAudio, /// clip only - CanBeAudioRole, /// clip only - CanBeVideoRole, /// clip only - IsDisabledRole, /// track only + InPointRole, /// clip only + OutPointRole, /// clip only + FramerateRole, /// clip only + GroupedRole, /// clip only + HasAudio, /// clip only + CanBeAudioRole, /// clip only + CanBeVideoRole, /// clip only + IsDisabledRole, /// track only IsAudioRole, SortRole, ShowKeyframesRole, AudioLevelsRole, /// clip only IsCompositeRole, /// track only IsLockedRole, /// track only HeightRole, /// track only TrackTagRole, /// track only FadeInRole, /// clip only FadeOutRole, /// clip only IsCompositionRole, /// clip only FileHashRole, /// clip only SpeedRole, /// clip only ReloadThumbRole, /// clip only ItemATrack, /// composition only ItemIdRole }; virtual ~TimelineModel(); Mlt::Tractor *tractor() const { return m_tractor.get(); } /* @brief Load tracks from the current tractor, used on project opening */ void loadTractor(); /* @brief Returns the current tractor's producer, useful fo control seeking, playing, etc */ Mlt::Producer *producer(); Mlt::Profile *getProfile(); /* @brief returns the number of tracks */ int getTracksCount() const; /* @brief returns the track index (id) from its position */ int getTrackIndexFromPosition(int pos) const; /* @brief returns the number of clips */ int getClipsCount() const; /* @brief returns the number of compositions */ int getCompositionsCount() const; /* @brief Returns the id of the track containing clip (-1 if it is not inserted) @param clipId Id of the clip to test */ Q_INVOKABLE int getClipTrackId(int clipId) const; /* @brief Returns the id of the track containing composition (-1 if it is not inserted) @param clipId Id of the composition to test */ Q_INVOKABLE int getCompositionTrackId(int compoId) const; /* @brief Convenience function that calls either of the previous ones based on item type*/ int getItemTrackId(int itemId) const; Q_INVOKABLE int getCompositionPosition(int compoId) const; int getCompositionPlaytime(int compoId) const; /* Returns an item position, item can be clip or composition */ int getItemPosition(int itemId) const; /* Returns an item duration, item can be clip or composition */ int getItemPlaytime(int itemId) const; /* Returns the current speed of a clip */ double getClipSpeed(int clipId) const; /* @brief Helper function to query the amount of free space around a clip * @param clipId: the queried clip. If it is not inserted on a track, this functions returns 0 * @param after: if true, we return the blank after the clip, otherwise, before. */ int getBlankSizeNearClip(int clipId, bool after) const; /* @brief if the clip belongs to a AVSplit group, then return the id of the other corresponding clip. Otherwise, returns -1 */ int getClipSplitPartner(int clipId) const; /* @brief Helper function that returns true if the given ID corresponds to a clip */ bool isClip(int id) const; /* @brief Helper function that returns true if the given ID corresponds to a composition */ bool isComposition(int id) const; /* @brief Helper function that returns true if the given ID corresponds to a track */ bool isTrack(int id) const; /* @brief Helper function that returns true if the given ID corresponds to a track */ bool isGroup(int id) const; /* @brief Given a composition Id, returns its underlying parameter model */ std::shared_ptr getCompositionParameterModel(int compoId) const; /* @brief Given a clip Id, returns its underlying effect stack model */ std::shared_ptr getClipEffectStackModel(int clipId) const; /* @brief Returns the position of clip (-1 if it is not inserted) @param clipId Id of the clip to test */ Q_INVOKABLE int getClipPosition(int clipId) const; Q_INVOKABLE bool addClipEffect(int clipId, const QString &effectId); Q_INVOKABLE bool addTrackEffect(int trackId, const QString &effectId); bool removeFade(int clipId, bool fromStart); Q_INVOKABLE bool copyClipEffect(int clipId, const QString &sourceId); bool adjustEffectLength(int clipId, const QString &effectId, int duration, int initialDuration); /* @brief Returns the closest snap point within snapDistance */ Q_INVOKABLE int suggestSnapPoint(int pos, int snapDistance); /* @brief Returns the in cut position of a clip @param clipId Id of the clip to test */ int getClipIn(int clipId) const; /* @brief Returns the bin id of the clip master @param clipId Id of the clip to test */ const QString getClipBinId(int clipId) const; /* @brief Returns the duration of a clip @param clipId Id of the clip to test */ int getClipPlaytime(int clipId) const; /* @brief Returns the duration of a clip @param clipId Id of the clip to test */ QSize getClipFrameSize(int clipId) const; /* @brief Returns the number of clips in a given track @param trackId Id of the track to test */ int getTrackClipsCount(int trackId) const; /* @brief Returns the number of compositions in a given track @param trackId Id of the track to test */ int getTrackCompositionsCount(int trackId) const; /* @brief Returns the position of the track in the order of the tracks @param trackId Id of the track to test */ int getTrackPosition(int trackId) const; /* @brief Returns the track's index in terms of mlt's internal representation */ int getTrackMltIndex(int trackId) const; /* @brief Returns the ids of the tracks below the given track in the order of the tracks Returns an empty list if no track available @param trackId Id of the track to test */ QList getLowerTracksId(int trackId, TrackType type = TrackType::AnyTrack) const; /* @brief Returns the MLT track index of the video track just below the given trackC @param trackId Id of the track to test */ int getPreviousVideoTrackPos(int trackId) const; /* @brief Retuns the Id of the corresponding audio track. If trackId corresponds to video1, this will return audio 1 and so on */ int getMirrorAudioTrackId(int trackId) const; /* @brief Move a clip to a specific position This action is undoable Returns true on success. If it fails, nothing is modified. If the clip is not in inserted in a track yet, it gets inserted for the first time. If the clip is in a group, the call is deferred to requestGroupMove @param clipId is the ID of the clip @param trackId is the ID of the target track @param position is the position where we want to move @param updateView if set to false, no signal is sent to qml @param logUndo if set to false, no undo object is stored */ Q_INVOKABLE bool requestClipMove(int clipId, int trackId, int position, bool updateView = true, bool logUndo = true, bool invalidateTimeline = false); /* @brief Move a composition to a specific position This action is undoable Returns true on success. If it fails, nothing is modified. If the clip is not in inserted in a track yet, it gets inserted for the first time. If the clip is in a group, the call is deferred to requestGroupMove @param transid is the ID of the composition @param trackId is the ID of the track */ Q_INVOKABLE bool requestCompositionMove(int compoId, int trackId, int position, bool updateView = true, bool logUndo = true); /* Same function, but accumulates undo and redo, and doesn't check for group*/ bool requestClipMove(int clipId, int trackId, int position, bool updateView, bool invalidateTimeline, Fun &undo, Fun &redo); bool requestCompositionMove(int transid, int trackId, int compositionTrack, int position, bool updateView, Fun &undo, Fun &redo); /* @brief Given an intended move, try to suggest a more valid one (accounting for snaps and missing UI calls) @param clipId id of the clip to move @param trackId id of the target track @param position target position @param snapDistance the maximum distance for a snap result, -1 for no snapping - of the clip + of the clip @param dontRefreshMasterClip when false, no view refresh is attempted */ Q_INVOKABLE int suggestClipMove(int clipId, int trackId, int position, int snapDistance = -1, bool allowViewUpdate = true); Q_INVOKABLE int suggestCompositionMove(int compoId, int trackId, int position, int snapDistance = -1); /* @brief Request clip insertion at given position. This action is undoable Returns true on success. If it fails, nothing is modified. @param binClipId id of the clip in the bin @param track Id of the track where to insert @param position Requested position @param ID return parameter of the id of the inserted clip @param logUndo if set to false, no undo object is stored @param refreshView whether the view should be refreshed @param useTargets: if true, the Audio/video split will occur on the set targets. Otherwise, they will be computed as an offset from the middle line */ bool requestClipInsertion(const QString &binClipId, int trackId, int position, int &id, bool logUndo = true, bool refreshView = false, bool useTargets = true); /* Same function, but accumulates undo and redo*/ bool requestClipInsertion(const QString &binClipId, int trackId, int position, int &id, bool logUndo, bool refreshView, bool useTargets, Fun &undo, Fun &redo); /* @brief Creates a new clip instance without inserting it. This action is undoable, returns true on success @param binClipId: Bin id of the clip to insert @param id: return parameter for the id of the newly created clip. @param state: The desired clip state (original, audio/video only). */ bool requestClipCreation(const QString &binClipId, int &id, PlaylistState::ClipState state, Fun &undo, Fun &redo); /* @brief Deletes the given clip or composition from the timeline This action is undoable Returns true on success. If it fails, nothing is modified. If the clip/composition is in a group, the call is deferred to requestGroupDeletion @param clipId is the ID of the clip/composition @param logUndo if set to false, no undo object is stored */ Q_INVOKABLE bool requestItemDeletion(int clipId, bool logUndo = true); /* Same function, but accumulates undo and redo*/ bool requestItemDeletion(int clipId, Fun &undo, Fun &redo); /* @brief Move a group to a specific position This action is undoable Returns true on success. If it fails, nothing is modified. If the clips in the group are not in inserted in a track yet, they get inserted for the first time. @param clipId is the id of the clip that triggers the group move @param groupId is the id of the group @param delta_track is the delta applied to the track index @param delta_pos is the requested position change @param updateView if set to false, no signal is sent to qml for the clip clipId @param logUndo if set to true, an undo object is created @param allowViewRefresh if false, the view will never get updated (useful for suggestMove) */ bool requestGroupMove(int clipId, int groupId, int delta_track, int delta_pos, bool updateView = true, bool logUndo = true); - bool requestGroupMove(int clipId, int groupId, int delta_track, int delta_pos, bool updateView, bool finalMove, Fun &undo, Fun &redo, bool allowViewRefresh = true); + bool requestGroupMove(int clipId, int groupId, int delta_track, int delta_pos, bool updateView, bool finalMove, Fun &undo, Fun &redo, + bool allowViewRefresh = true); /* @brief Deletes all clips inside the group that contains the given clip. This action is undoable Note that if their is a hierarchy of groups, all of them will be deleted. Returns true on success. If it fails, nothing is modified. @param clipId is the id of the clip that triggers the group deletion */ Q_INVOKABLE bool requestGroupDeletion(int clipId, bool logUndo = true); bool requestGroupDeletion(int clipId, Fun &undo, Fun &redo); /* @brief Change the duration of an item (clip or composition) This action is undoable Returns the real size reached (can be different, if snapping occurs). If it fails, nothing is modified, and -1 is returned @param itemId is the ID of the item @param size is the new size of the item @param right is true if we change the right side of the item, false otherwise @param logUndo if set to true, an undo object is created @param snap if set to true, the resize order will be coerced to use the snapping grid */ Q_INVOKABLE int requestItemResize(int itemId, int size, bool right, bool logUndo = true, int snapDistance = -1, bool allowSingleResize = false); /* Same function, but accumulates undo and redo and doesn't deal with snapping*/ bool requestItemResize(int itemId, int size, bool right, bool logUndo, Fun &undo, Fun &redo, bool blockUndo = false); /* @brief Group together a set of ids The ids are either a group ids or clip ids. The involved clip must already be inserted in a track This action is undoable Returns the group id on success, -1 if it fails and nothing is modified. Typically, ids would be ids of clips, but for convenience, some of them can be ids of groups as well. @param ids Set of ids to group */ int requestClipsGroup(const std::unordered_set &ids, bool logUndo = true, GroupType type = GroupType::Normal); int requestClipsGroup(const std::unordered_set &ids, Fun &undo, Fun &redo, GroupType type = GroupType::Normal); /* @brief Destruct the topmost group containing clip This action is undoable Returns true on success. If it fails, nothing is modified. @param id of the clip to degroup (all clips belonging to the same group will be ungrouped as well) */ bool requestClipUngroup(int id, bool logUndo = true); /* Same function, but accumulates undo and redo*/ bool requestClipUngroup(int id, Fun &undo, Fun &redo); /* @brief Create a track at given position This action is undoable Returns true on success. If it fails, nothing is modified. @param Requested position (order). If set to -1, the track is inserted last. @param id is a return parameter that holds the id of the resulting track (-1 on failure) */ bool requestTrackInsertion(int pos, int &id, const QString &trackName = QString(), bool audioTrack = false); /* Same function, but accumulates undo and redo*/ bool requestTrackInsertion(int pos, int &id, const QString &trackName, bool audioTrack, Fun &undo, Fun &redo, bool updateView = true); /* @brief Delete track with given id This also deletes all the clips contained in the track. This action is undoable Returns true on success. If it fails, nothing is modified. @param trackId id of the track to delete */ bool requestTrackDeletion(int trackId); /* Same function, but accumulates undo and redo*/ bool requestTrackDeletion(int trackId, Fun &undo, Fun &redo); /* @brief Get project duration Returns the duration in frames */ int duration() const; static int seekDuration; // Duration after project end where seeking is allowed /* @brief Get all the elements of the same group as the given clip. If there is a group hierarchy, only the topmost group is considered. @param clipId id of the clip to test */ std::unordered_set getGroupElements(int clipId); /* @brief Removes all the elements on the timeline (tracks and clips) */ bool requestReset(Fun &undo, Fun &redo); /* @brief Updates the current the pointer to the current undo_stack Must be called for example when the doc change */ void setUndoStack(std::weak_ptr undo_stack); /* @brief Requests the best snapped position for a clip @param pos is the clip's requested position @param length is the clip's duration @param pts snap points to ignore (for example currently moved clip) @param snapDistance the maximum distance for a snap result, -1 for no snapping @returns best snap position or -1 if no snap point is near */ int requestBestSnapPos(int pos, int length, const std::vector &pts = std::vector(), int snapDistance = -1); /* @brief Requests the next snapped point @param pos is the current position */ int requestNextSnapPos(int pos); /* @brief Requests the previous snapped point @param pos is the current position */ int requestPreviousSnapPos(int pos); /* @brief Add a new snap point @param pos is the current position */ void addSnap(int pos); /* @brief Remove snap point @param pos is the current position */ void removeSnap(int pos); /* @brief Request composition insertion at given position. This action is undoable Returns true on success. If it fails, nothing is modified. @param transitionId Identifier of the Mlt transition to insert (as given by repository) @param track Id of the track where to insert @param position Requested position @param length Requested initial length. @param id return parameter of the id of the inserted composition @param logUndo if set to false, no undo object is stored */ bool requestCompositionInsertion(const QString &transitionId, int trackId, int position, int length, Mlt::Properties *transProps, int &id, bool logUndo = true); /* Same function, but accumulates undo and redo*/ bool requestCompositionInsertion(const QString &transitionId, int trackId, int compositionTrack, int position, int length, Mlt::Properties *transProps, int &id, Fun &undo, Fun &redo); /* @brief This function change the global (timeline-wise) enabled state of the effects It disables/enables track and clip effects (recursively) */ void setTimelineEffectsEnabled(bool enabled); /* @brief Get a timeline clip id by its position or -1 if not found */ int getClipByPosition(int trackId, int position) const; /* @brief Get a timeline composition id by its starting position or -1 if not found */ int getCompositionByPosition(int trackId, int position) const; /* @brief Returns a list of all items that are at or after a given position. * @param trackId is the id of the track for concerned items. Setting trackId to -1 returns items on all tracks * @param position is the position where we the items should start * @param end is the position after which items will not be selected, set to -1 to get all clips on track * @param listCompositions if enabled, the list will also contains composition ids */ std::unordered_set getItemsAfterPosition(int trackId, int position, int end = -1, bool listCompositions = true); /* @brief Returns a list of all luma files used in the project */ QStringList extractCompositionLumas() const; /* @brief Inform asset view of duration change */ virtual void adjustAssetRange(int clipId, int in, int out); void requestClipReload(int clipId); void requestClipUpdate(int clipId, const QVector &roles); /** @brief Returns the effectstack of a given clip. */ std::shared_ptr getClipEffectStack(int itemId); std::shared_ptr getTrackEffectStackModel(int trackId); /** @brief Add slowmotion effect to clip in timeline. */ bool requestClipTimeWarp(int clipId, int blankSpace, double speed, Fun &undo, Fun &redo); bool changeItemSpeed(int clipId, double speed); void replugClip(int clipId); /** @brief Refresh the tractor profile in case a change was requested. */ void updateProfile(Mlt::Profile *profile); protected: /* @brief Register a new track. This is a call-back meant to be called from TrackModel @param pos indicates the number of the track we are adding. If this is -1, then we add at the end. */ void registerTrack(std::shared_ptr track, int pos = -1, bool doInsert = true, bool reloadView = true); /* @brief Register a new clip. This is a call-back meant to be called from ClipModel */ void registerClip(const std::shared_ptr &clip); /* @brief Register a new composition. This is a call-back meant to be called from CompositionModel */ void registerComposition(const std::shared_ptr &composition); /* @brief Register a new group. This is a call-back meant to be called from GroupsModel */ void registerGroup(int groupId); /* @brief Deregister and destruct the track with given id. @parame updateView Whether to send updates to the model. Must be false when called from a constructor/destructor */ Fun deregisterTrack_lambda(int id, bool updateView = false); /* @brief Return a lambda that deregisters and destructs the clip with given id. Note that the clip must already be deleted from its track and groups. */ Fun deregisterClip_lambda(int id); /* @brief Return a lambda that deregisters and destructs the composition with given id. */ Fun deregisterComposition_lambda(int compoId); /* @brief Deregister a group with given id */ void deregisterGroup(int id); /* @brief Helper function to get a pointer to the track, given its id */ std::shared_ptr getTrackById(int trackId); const std::shared_ptr getTrackById_const(int trackId) const; /*@brief Helper function to get a pointer to a clip, given its id*/ std::shared_ptr getClipPtr(int clipId) const; /*@brief Helper function to get a pointer to a composition, given its id*/ std::shared_ptr getCompositionPtr(int compoId) const; /* @brief Returns next valid unique id to create an object */ static int getNextId(); /* @brief unplant and the replant all the compositions in the correct order @param currentCompo is the id of a compo that have not yet been planted, if any. Otherwise send -1 */ bool replantCompositions(int currentCompo, bool updateView); /* @brief Unplant the composition with given Id */ bool unplantComposition(int compoId); /* Same function but accumulates undo and redo, and doesn't check for group*/ bool requestClipDeletion(int clipId, Fun &undo, Fun &redo); bool requestCompositionDeletion(int compositionId, Fun &undo, Fun &redo); /** @brief Check tracks duration and update black track accordingly */ void updateDuration(); /** @brief Get a track tag (A1, V1, V2,...) through its id */ const QString getTrackTagById(int trackId) const; /** @brief Attempt to make a clip move without ever updating the view */ bool requestClipMoveAttempt(int clipId, int trackId, int position); public: /* @brief Debugging function that checks consistency with Mlt objects */ bool checkConsistency(); protected: /* @brief Refresh project monitor if cursor was inside range */ void checkRefresh(int start, int end); /* @brief Send signal to require clearing effet/composition view */ void clearAssetView(int itemId); signals: /* @brief signal triggered by clearAssetView */ void requestClearAssetView(int); void requestMonitorRefresh(); /* @brief signal triggered by track operations */ void invalidateZone(int in, int out); /* @brief signal triggered when a track duration changed (insertion/deletion) */ void durationUpdated(); protected: std::unique_ptr m_tractor; std::list> m_allTracks; std::unordered_map>::iterator> m_iteratorTable; // this logs the iterator associated which each track id. This allows easy access of a track based on its id. std::unordered_map> m_allClips; // the keys are the clip id, and the values are the corresponding pointers std::unordered_map> m_allCompositions; // the keys are the composition id, and the values are the corresponding pointers static int next_id; // next valid id to assign std::unique_ptr m_groups; std::shared_ptr m_snaps; std::unordered_set m_allGroups; // ids of all the groups std::weak_ptr m_undoStack; Mlt::Profile *m_profile; // The black track producer. Its length / out should always be adjusted to the projects's length std::unique_ptr m_blackClip; mutable QReadWriteLock m_lock; // This is a lock that ensures safety in case of concurrent access #ifdef LOGGING std::ofstream m_logFile; // this is a temporary debug member to help reproduce issues #endif bool m_timelineEffectsEnabled; bool m_id; // id of the timeline itself // id of the currently selected group in timeline, should be destroyed on each new selection int m_temporarySelectionGroup; // The index of the temporary overlay track in tractor, or -1 if not connected int m_overlayTrackCount; // The preferred audio target for clip insertion or -1 if not defined int m_audioTarget; // The preferred video target for clip insertion or -1 if not defined int m_videoTarget; // what follows are some virtual function that corresponds to the QML. They are implemented in TimelineItemModel protected: virtual void _beginRemoveRows(const QModelIndex &, int, int) = 0; virtual void _beginInsertRows(const QModelIndex &, int, int) = 0; virtual void _endRemoveRows() = 0; virtual void _endInsertRows() = 0; virtual void notifyChange(const QModelIndex &topleft, const QModelIndex &bottomright, bool start, bool duration, bool updateThumb) = 0; virtual void notifyChange(const QModelIndex &topleft, const QModelIndex &bottomright, const QVector &roles) = 0; virtual void notifyChange(const QModelIndex &topleft, const QModelIndex &bottomright, int role) = 0; virtual QModelIndex makeClipIndexFromID(int) const = 0; virtual QModelIndex makeCompositionIndexFromID(int) const = 0; virtual QModelIndex makeTrackIndexFromID(int) const = 0; virtual void _resetView() = 0; }; #endif diff --git a/src/timeline2/view/dialogs/trackdialog.h b/src/timeline2/view/dialogs/trackdialog.h index c0ebcb3d3..b62ec2234 100644 --- a/src/timeline2/view/dialogs/trackdialog.h +++ b/src/timeline2/view/dialogs/trackdialog.h @@ -1,52 +1,52 @@ /*************************************************************************** * Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@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) any later version. * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ #ifndef TRACKDIALOG2_H #define TRACKDIALOG2_H #include "timeline2/model/timelineitemmodel.hpp" #include "ui_addtrack_ui.h" class TrackDialog : public QDialog, public Ui::AddTrack_UI { Q_OBJECT public: explicit TrackDialog(std::shared_ptr model, int trackIndex = -1, QWidget *parent = nullptr, bool deleteMode = false); /** @brief: returns the selected position in MLT */ int selectedTrackPosition() const; /** @brief: returns the selected track's trackId */ int selectedTrackId() const; /** @brief: returns true if we want to insert an audio track */ bool addAudioTrack() const; /** @brief: returns the newly created track name */ const QString trackName() const; private: int m_audioCount; int m_videoCount; - QMapm_positionByIndex; + QMap m_positionByIndex; }; #endif diff --git a/tests/test_utils.hpp b/tests/test_utils.hpp index 25f31cb0d..9b3bf7af4 100644 --- a/tests/test_utils.hpp +++ b/tests/test_utils.hpp @@ -1,85 +1,85 @@ #pragma once #include "bin/model/markerlistmodel.hpp" #include "catch.hpp" #include "doc/docundostack.hpp" #include #include #include #include #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" #pragma GCC diagnostic push #include "fakeit.hpp" #include #include #include #include #define private public #define protected public #include "assets/keyframes/model/keyframemodel.hpp" #include "assets/model/assetparametermodel.hpp" #include "bin/clipcreator.hpp" #include "bin/projectclip.h" #include "bin/projectfolder.h" #include "bin/projectitemmodel.h" #include "core.h" #include "effects/effectsrepository.hpp" #include "effects/effectstack/model/effectitemmodel.hpp" #include "effects/effectstack/model/effectstackmodel.hpp" #include "project/projectmanager.h" #include "timeline2/model/clipmodel.hpp" #include "timeline2/model/compositionmodel.hpp" #include "timeline2/model/groupsmodel.hpp" #include "timeline2/model/timelinefunctions.hpp" #include "timeline2/model/timelineitemmodel.hpp" #include "timeline2/model/timelinemodel.hpp" #include "timeline2/model/trackmodel.hpp" using namespace fakeit; #define RESET(mock) \ mock.Reset(); \ Fake(Method(mock, adjustAssetRange)); \ Spy(Method(mock, _resetView)); \ Spy(Method(mock, _beginInsertRows)); \ Spy(Method(mock, _beginRemoveRows)); \ Spy(Method(mock, _endInsertRows)); \ Spy(Method(mock, _endRemoveRows)); \ Spy(OverloadedMethod(mock, notifyChange, void(const QModelIndex &, const QModelIndex &, bool, bool, bool))); \ Spy(OverloadedMethod(mock, notifyChange, void(const QModelIndex &, const QModelIndex &, const QVector &))); \ Spy(OverloadedMethod(mock, notifyChange, void(const QModelIndex &, const QModelIndex &, int))); #define NO_OTHERS() \ VerifyNoOtherInvocations(Method(timMock, _beginRemoveRows)); \ VerifyNoOtherInvocations(Method(timMock, _beginInsertRows)); \ VerifyNoOtherInvocations(Method(timMock, _endRemoveRows)); \ VerifyNoOtherInvocations(Method(timMock, _endInsertRows)); \ VerifyNoOtherInvocations(OverloadedMethod(timMock, notifyChange, void(const QModelIndex &, const QModelIndex &, bool, bool, bool))); \ VerifyNoOtherInvocations(OverloadedMethod(timMock, notifyChange, void(const QModelIndex &, const QModelIndex &, const QVector &))); \ RESET(timMock); #define CHECK_MOVE(times) \ Verify(Method(timMock, _beginRemoveRows) + Method(timMock, _endRemoveRows) + Method(timMock, _beginInsertRows) + Method(timMock, _endInsertRows)) \ .Exactly(times); \ NO_OTHERS(); #define CHECK_INSERT(times) \ Verify(Method(timMock, _beginInsertRows) + Method(timMock, _endInsertRows)).Exactly(times); \ NO_OTHERS(); #define CHECK_REMOVE(times) \ Verify(Method(timMock, _beginRemoveRows) + Method(timMock, _endRemoveRows)).Exactly(times); \ NO_OTHERS(); #define CHECK_RESIZE(times) \ Verify(OverloadedMethod(timMock, notifyChange, void(const QModelIndex &, const QModelIndex &, bool, bool, bool))).Exactly(times); \ NO_OTHERS(); #define CHECK_UPDATE(role) \ Verify(OverloadedMethod(timMock, notifyChange, void(const QModelIndex &, const QModelIndex &, int)) \ - .Matching([](const QModelIndex &, const QModelIndex &, int c) { return c == role; })) \ + .Matching([](const QModelIndex &, const QModelIndex &, int c) { return c == role; })) \ .Exactly(1); \ NO_OTHERS(); QString createProducer(Mlt::Profile &prof, std::string color, std::shared_ptr binModel, int length = 20, bool limited = true); QString createProducerWithSound(Mlt::Profile &prof, std::shared_ptr binModel);