File indexing completed on 2024-04-21 04:51:29

0001 /*
0002     SPDX-FileCopyrightText: 2008 Jean-Baptiste Mardelle <jb@kdenlive.org>
0003 
0004     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #pragma once
0008 
0009 #include "definitions.h"
0010 #include "ui_missingclips_ui.h"
0011 
0012 #include <QDir>
0013 #include <QDomElement>
0014 #include <QUrl>
0015 
0016 class DocumentChecker : public QObject
0017 {
0018     Q_OBJECT
0019 
0020 public:
0021     enum MissingStatus { Fixed, Reload, Missing, MissingButProxy, Placeholder, Remove };
0022     enum MissingType { Clip, Proxy, Luma, AssetFile, TitleImage, TitleFont, Effect, Transition, CircularRef };
0023     struct DocumentResource
0024     {
0025         MissingStatus status = MissingStatus::Missing;
0026         MissingType type;
0027         QString originalFilePath;
0028         QString newFilePath;
0029         QString clipId;
0030         QString hash;
0031         QString fileSize;
0032         ClipType::ProducerType clipType;
0033     };
0034 
0035     explicit DocumentChecker(QUrl url, const QDomDocument &doc);
0036     ~DocumentChecker() override;
0037     /**
0038      * @brief checks for problems with the project
0039      * Checks for missing proxies, wrong duration clips, missing fonts, missing images, missing source clips, missing effects, missing transitions
0040      * @returns whether error have been found
0041      */
0042     bool hasErrorInProject();
0043     static QString fixLutFile(const QString &file);
0044     static QString fixLumaPath(const QString &file);
0045     static QString searchLuma(const QDir &dir, const QString &file);
0046 
0047     static QString readableNameForClipType(ClipType::ProducerType type);
0048     static QString readableNameForMissingType(MissingType type);
0049     static QString readableNameForMissingStatus(MissingStatus type);
0050 
0051     static QString searchPathRecursively(const QDir &dir, const QString &fileName, ClipType::ProducerType type = ClipType::Unknown);
0052     static QString searchFileRecursively(const QDir &dir, const QString &matchSize, const QString &matchHash, const QString &fileName);
0053     static QString searchDirRecursively(const QDir &dir, const QString &matchHash, const QString &fullName);
0054 
0055     bool resolveProblemsWithGUI();
0056     /* @brief Get a count of missing items in each category */
0057     QMap<DocumentChecker::MissingType, int> getCheckResults();
0058 
0059     std::vector<DocumentResource> resourceItems() { return m_items; }
0060 
0061 private:
0062     QUrl m_url;
0063     QDomDocument m_doc;
0064     QString m_documentid;
0065     QString m_root;
0066     QPair<QString, QString> m_rootReplacement;
0067 
0068     QDomNodeList m_binEntries;
0069     std::vector<DocumentResource> m_items;
0070 
0071     QStringList m_safeImages;
0072     QStringList m_safeFonts;
0073 
0074     QStringList m_binIds;
0075     QStringList m_warnings;
0076 
0077     QString ensureAbsolutePath(QString filepath);
0078 
0079     /** @brief Returns list of transitions ids / tag containing luma files */
0080     const QMap<QString, QString> getLumaPairs() const;
0081     /** @brief Returns list of filters ids / tag containing asset files */
0082     const QMap<QString, QString> getAssetPairs() const;
0083 
0084     /** @brief Check if the producer has an id. If not (should not happen, but...) try to recover it
0085      *  @returns true if the producer has been changed (id recovered), false if it was either already okay or could not be recovered
0086      */
0087     bool ensureProducerHasId(QDomElement &producer, const QDomNodeList &entries);
0088     /** @brief Check if the producer represents an "invalid" placeholder (project saved with missing source). If such a placeholder is detected, it tries to
0089      * recover the original clip.
0090      *  @returns true if the producer has been changed (recovered), false if it was either already okay or could not be recovered
0091      */
0092     bool ensureProducerIsNotPlaceholder(QDomElement &producer);
0093 
0094     /** @brief Check for various missing elements */
0095     QString getMissingProducers(QDomElement &e, const QDomNodeList &entries, const QString &storageFolder);
0096     /** @brief Check if images and fonts in this clip exists, returns a list of images that do exist so we don't check twice. */
0097     void checkMissingImagesAndFonts(const QStringList &images, const QStringList &fonts, const QString &id);
0098     /** @brief If project path changed, try to relocate its resources */
0099     const QString relocateResource(QString sourceResource);
0100 
0101     static ClipType::ProducerType getClipType(const QString &service, const QString &resource);
0102     QString getProducerResource(const QDomElement &producer);
0103     static QString getKdenliveClipId(const QDomElement &producer);
0104     static QStringList getAssetsFilesByMltTag(const QDomDocument &doc, const QString &tagName, const QMap<QString, QString> &searchPairs);
0105     static QStringList getAssetsServiceIds(const QDomDocument &doc, const QString &tagName);
0106 
0107     QStringList getInfoMessages();
0108 
0109     static bool isMltBuildInLuma(const QString &lumaName);
0110     static bool isSlideshow(const QString &resource);
0111     bool isSequenceWithSpeedEffect(const QDomElement &producer);
0112     static bool isProfileHD(const QDomDocument &doc);
0113 
0114     void fixMissingItem(const DocumentChecker::DocumentResource &resource, const QDomNodeList &producers, const QDomNodeList &chains, const QDomNodeList &trans,
0115                         const QDomNodeList &filters);
0116 
0117     bool itemsContain(MissingType type, const QString &path = QString(), MissingStatus status = MissingStatus::Missing);
0118     int itemIndexByClipId(const QString &clipId);
0119 
0120     void fixTitleImage(QDomElement &e, const QString &oldPath, const QString &newPath);
0121     void fixTitleFont(const QDomNodeList &producers, const QString &oldFont, const QString &newFont);
0122     void fixAssetResource(const QDomNodeList &assets, const QMap<QString, QString> &searchPairs, const QString &oldPath, const QString &newPath);
0123     static void removeAssetsById(QDomDocument &doc, const QString &tagName, const QStringList &idsToDelete);
0124     /** @brief Update a filter's tag and id with a new name */
0125     static void fixAssetsById(QDomDocument &doc, const QString &tagName, const QString &oldId, const QString &newId);
0126     void usePlaceholderForClip(const QDomNodeList &items, const QString &clipId);
0127     void removeClip(const QDomNodeList &producers, const QDomNodeList &chains, const QDomNodeList &playlists, const QString &clipId);
0128     void fixClip(const QDomNodeList &items, const QString &clipId, const QString &newPath);
0129 
0130     void fixProxyClip(const QDomNodeList &items, const QString &id, const QString &oldUrl, const QString &newUrl);
0131     void removeProxy(const QDomNodeList &items, const QString &clipId, bool recreate);
0132     /** @brief Remove _missingsourcec flag in fixed clips */
0133     void fixMissingSource(const QString &id, const QDomNodeList &producers, const QDomNodeList &chains);
0134 
0135     QStringList fixSequences(QDomElement &e, const QDomNodeList &producers, const QStringList &tractorIds);
0136 };
0137 
0138 QDebug operator<<(QDebug qd, const DocumentChecker::DocumentResource &item);