File indexing completed on 2023-11-26 04:48:47

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