File indexing completed on 2024-07-14 04:45:33

0001 /*
0002 SPDX-FileCopyrightText: 2014 Till Theato <root@ttill.de>
0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 #pragma once
0007 
0008 #include "kdenlivecore_export.h"
0009 #include <KRecentFilesAction>
0010 #include <QDir>
0011 #include <QObject>
0012 #include <QTime>
0013 #include <QTimer>
0014 #include <QUrl>
0015 #include <QElapsedTimer>
0016 
0017 #include "timeline2/model/timelineitemmodel.hpp"
0018 
0019 #include <memory>
0020 #include <unordered_map>
0021 #include <unordered_set>
0022 
0023 class KAutoSaveFile;
0024 class KJob;
0025 class KdenliveDoc;
0026 class MarkerListModel;
0027 class NotesPlugin;
0028 class Project;
0029 class QAction;
0030 class QProgressDialog;
0031 class QUrl;
0032 class DocUndoStack;
0033 class TimelineWidget;
0034 
0035 /** @class ProjectManager
0036     @brief Takes care of interaction with projects.
0037  */
0038 class /*KDENLIVECORE_EXPORT*/ ProjectManager : public QObject
0039 {
0040     Q_OBJECT
0041 
0042 public:
0043     friend class RenderRequest;
0044     /** @brief Sets up actions to interact for project interaction (undo, redo, open, save, ...) and creates an empty project. */
0045     explicit ProjectManager(QObject *parent = nullptr);
0046     ~ProjectManager() override;
0047 
0048     /** @brief Returns a pointer to the currently opened project. A project should always be open.
0049         The method is virtual to allow mocking
0050      */
0051     virtual KdenliveDoc *current();
0052 
0053     /** @brief Store command line args for later opening. */
0054     void init(const QUrl &projectUrl, const QString &clipList);
0055 
0056     void doOpenFile(const QUrl &url, KAutoSaveFile *stale, bool isBackup = false);
0057     void doOpenFileHeadless(const QUrl &url);
0058     KRecentFilesAction *recentFilesAction();
0059     void prepareSave();
0060     /** @brief Disable all bin effects in current project
0061      *  @param disable if true, all project bin effects will be disabled
0062      *  @param refreshMonitor if false, monitors will not be refreshed
0063      */
0064     void disableBinEffects(bool disable, bool refreshMonitor = true);
0065     /** @brief Returns current project's xml scene */
0066     QString projectSceneList(const QString &outputFolder, const QString &overlayData = QString());
0067     /** @brief returns a default hd profile depending on timezone*/
0068     static QString getDefaultProjectFormat();
0069     void saveZone(const QStringList &info, const QDir &dir);
0070     /** @brief Move project data files to new url */
0071     void moveProjectData(const QString &src, const QString &dest);
0072     /** @brief Retrieve current project's notes */
0073     QString documentNotes() const;
0074 
0075     /** @brief Retrieve the current Guide Model
0076         The method is virtual to allow mocking
0077      */
0078     virtual std::shared_ptr<MarkerListModel> getGuideModel();
0079 
0080     /** @brief Return the current undo stack
0081         The method is virtual to allow mocking
0082     */
0083     virtual std::shared_ptr<DocUndoStack> undoStack();
0084 
0085     virtual const QDir cacheDir(bool audio, bool *ok) const;
0086 
0087     /** @brief This will create a backup file with fps appended to project name,
0088      *  and save the project with an updated profile info, then reopen it.
0089      */
0090     void saveWithUpdatedProfile(const QString &updatedProfile);
0091 
0092     /** @brief Get the number of tracks in this project (video, audio).
0093      */
0094     QPair<int, int> avTracksCount();
0095 
0096     /** @brief Add requested audio tracks number to project.
0097      */
0098     void addAudioTracks(int tracksCount);
0099     /** @brief This method is only there for tests, do not use in real app.
0100      */
0101     void testSetActiveDocument(KdenliveDoc *doc, std::shared_ptr<TimelineItemModel> timeline = nullptr);
0102     /** @brief This method is only there for tests, do not use in real app.
0103      */
0104     bool testSaveFileAs(const QString &outputFileName);
0105     /** @brief Retrieve the current timeline (mostly used for testing.
0106      */
0107     std::shared_ptr<TimelineItemModel> getTimeline();
0108     /** @brief Initialize a new timeline's default properties.
0109      */
0110     void initSequenceProperties(const QUuid &uuid, std::pair<int, int> tracks);
0111     /** @brief Open a timeline clip in a tab.
0112      *  @returns true if the timeline was not previously opened
0113      */
0114     bool openTimeline(const QString &id, const QUuid &uuid, int position = -1, bool duplicate = false,
0115                       std::shared_ptr<TimelineItemModel> existingModel = nullptr);
0116     /** @brief Set a property on timeline uuid
0117      */
0118     void setTimelinePropery(QUuid uuid, const QString &prop, const QString &val);
0119     /** @brief Get the count of timelines in this project
0120      */
0121     int getTimelinesCount() const;
0122 
0123     void activateDocument(const QUuid &uuid);
0124     /** @brief Close a timeline tab through its uuid
0125      */
0126     bool closeTimeline(const QUuid &uuid, bool onDeletion = false, bool clearUndo = true);
0127     /** @brief Update a timeline sequence before saving or extracting xml
0128      */
0129     void syncTimeline(const QUuid &uuid, bool refresh = false);
0130     void doSyncTimeline(std::shared_ptr<TimelineItemModel> model, bool refresh);
0131     void setActiveTimeline(const QUuid &uuid);
0132     /** @brief Replace all instance of a @param sourceId clip with another @param replacementId in the active timline sequence
0133      * @param replaceAudio if true, only the audio clips will be replaced. if false, only the video parts.
0134      */
0135     void replaceTimelineInstances(const QString &sourceId, const QString &replacementId, bool replaceAudio, bool replaceVideo);
0136 
0137 public Q_SLOTS:
0138     void newFile(QString profileName, bool showProjectSettings = true);
0139     void newFile(bool showProjectSettings = true);
0140     /** @brief Shows file open dialog. */
0141     void openFile();
0142     void openLastFile();
0143     /** @brief Load files / clips passed on the command line. */
0144     void slotLoadOnOpen();
0145 
0146     void slotLoadHeadless(const QUrl &projectUrl);
0147 
0148     /** @brief Checks whether a URL is available to save to.
0149      * @return Whether the file was saved. */
0150     bool saveFile();
0151 
0152     /** @brief Shows a save file dialog for saving the project.
0153      * @param saveACopy Default is false. If true, the file title of the dialog is set to "Save Copy…"
0154      * @return Whether the file was saved. */
0155     bool saveFileAs(bool saveACopy = false);
0156 
0157     /** @brief Set properties to match outputFileName and save the document.
0158      * Creates an autosave version of the output file too (only if not in copymode), at
0159      * ~/.kde/data/stalefiles/kdenlive/ \n
0160      * that will be actually written in KdenliveDoc::slotAutoSave()
0161      * @param outputFileName The URL to save to / The document's URL.
0162      * @param saveACopy Default is false. If true, the file will be saved but isn’t opened afterwards. Besides no autosave version will be created
0163      * @return Whether we had success. */
0164     bool saveFileAs(const QString &outputFileName, bool saveOverExistingFile = true, bool saveACopy = false);
0165 
0166     /** @brief Close currently opened document. Returns false if something went wrong (cannot save modifications, ...). */
0167     bool closeCurrentDocument(bool saveChanges = true, bool quit = false);
0168 
0169     /** @brief Prepares opening @param url.
0170      *
0171      * Checks if already open and whether backup exists */
0172     void openFile(const QUrl &url);
0173 
0174     /** @brief Start autosave timer */
0175     void slotStartAutoSave();
0176 
0177     /** @brief Update project and monitors profiles */
0178     void slotResetProfiles(bool reloadThumbs);
0179 
0180     /** @brief Rebuild consumers after a property change */
0181     void slotResetConsumers(bool fullReset);
0182 
0183     /** @brief Dis/enable all timeline effects */
0184     void slotDisableTimelineEffects(bool disable);
0185 
0186     /** @brief Mute/Unmute or Hide/Show current timeline track */
0187     void slotSwitchTrackDisabled();
0188     /** @brief Un/Lock current timeline track */
0189     void slotSwitchTrackLock();
0190     void slotSwitchAllTrackLock();
0191 
0192     /** @brief Make current timeline track active/inactive*/
0193     void slotSwitchTrackActive();
0194     /** @brief Toggle the active/inactive state of all tracks*/
0195     void slotSwitchAllTrackActive();
0196     /** @brief Make all tracks active or inactive */
0197     void slotMakeAllTrackActive();
0198     /** @brief Restore current clip target tracks */
0199     void slotRestoreTargetTracks();
0200 
0201     /** @brief Un/Set current track as target */
0202     void slotSwitchTrackTarget();
0203 
0204     /** @brief Set the text for current project's notes */
0205     void setDocumentNotes(const QString &notes);
0206 
0207     /** @brief Project's duration changed, adjust monitor, etc. */
0208     void adjustProjectDuration(int duration);
0209     /** @brief Add an asset in timeline (effect, transition). */
0210     void activateAsset(const QVariantMap &effectData);
0211     /** @brief insert current timeline timecode in notes widget and focus widget to allow entering quick note */
0212     void slotAddProjectNote();
0213     /** @brief insert license text in notes widget and focus widget to allow entering quick note. Virtual to allow Mocking */
0214     virtual void slotAddTextNote(const QString &text);
0215     /** @brief Open a timeline with a reference to a track / position. */
0216     void seekTimeline(const QString &frameAndTrack);
0217     /** @brief Create a sequence clip from timeline selection. */
0218     void slotCreateSequenceFromSelection();
0219 
0220 private Q_SLOTS:
0221     void slotRevert();
0222     /** @brief A timeline sequence duration changed, update our properties. */
0223     void updateSequenceDuration(const QUuid &uuid);
0224     /** @brief Open the project's backupdialog. */
0225     bool slotOpenBackup(const QUrl &url = QUrl());
0226     /** @brief Start autosaving the document. */
0227     void slotAutoSave();
0228     /** @brief Report progress of folder move operation. */
0229     void slotMoveProgress(KJob *, unsigned long progress);
0230     void slotMoveFinished(KJob *job);
0231 
0232 Q_SIGNALS:
0233     void docOpened(KdenliveDoc *document);
0234 
0235 protected:
0236     /** @brief Update the timeline according to the MLT XML */
0237     bool updateTimeline(bool createNewTab, const QString &chunks, const QString &dirty, const QDateTime &documentDate, bool enablePreview);
0238     KdenliveDoc *m_project{nullptr};
0239 
0240 private:
0241     /** @brief checks if autoback files exists, recovers from it if user says yes, returns true if files were recovered. */
0242     bool checkForBackupFile(const QUrl &url, bool newFile = false);
0243     /** @brief Update the sequence producer stored in the project model. */
0244     void updateSequenceProducer(const QUuid &uuid, std::shared_ptr<Mlt::Producer> prod);
0245 
0246     std::shared_ptr<TimelineItemModel> m_activeTimelineModel;
0247     QElapsedTimer m_lastSave;
0248     QTimer m_autoSaveTimer;
0249     QUrl m_startUrl;
0250     QString m_loadClipsOnOpen;
0251     QMap<QString, QString> m_replacementPattern;
0252 
0253     QAction *m_fileRevert;
0254     KRecentFilesAction *m_recentFilesAction;
0255     NotesPlugin *m_notesPlugin;
0256     void saveRecentFiles();
0257     /** @brief Something went wrong, stop loading file */
0258     void abortLoading();
0259     /** @brief Project loading failed, ask user if he wants to open a backup */
0260     void requestBackup(const QString &errorMessage);
0261     /** @brief WHen building a sequence producer, ensure we pass along all properties */
0262     void passSequenceProperties(const QUuid &uuid, std::shared_ptr<Mlt::Producer> prod, Mlt::Tractor tractor, std::shared_ptr<TimelineItemModel> timelineModel,
0263                                 TimelineWidget *timelineWidget);
0264     /** @brief Ensure sequences are correctly stored in our project model */
0265     void checkProjectIntegrity();
0266 };