File indexing completed on 2024-12-08 04:25:57

0001 /*
0002     SPDX-FileCopyrightText: 2017 Nicolas Carion
0003     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 #pragma once
0007 
0008 #include "definitions.h"
0009 #include "klocalizedstring.h"
0010 #include <QAbstractListModel>
0011 #include <QDomElement>
0012 #include <QJsonDocument>
0013 #include <unordered_map>
0014 
0015 #include <memory>
0016 #include <mlt++/MltProperties.h>
0017 
0018 class KeyframeModelList;
0019 
0020 typedef QVector<QPair<QString, QVariant>> paramVector;
0021 
0022 enum class ParamType {
0023     Double,
0024     List,               // Value can be chosen from a list of pre-defined ones
0025     ListWithDependency, // Value can be chosen from a list of pre-defined ones. Some values might not be available due to missing dependencies
0026     UrlList,            // File can be chosen from a list of pre-defined ones or a custom file can be used (like url)
0027     Bool,
0028     Switch,
0029     MultiSwitch,
0030     AnimatedRect, // Animated rects have X, Y, width, height, and opacity (in [0,1])
0031     Geometry,
0032     KeyframeParam,
0033     Color,
0034     FixedColor, // Non animated color
0035     ColorWheel,
0036     Position,
0037     Curve,
0038     Bezier_spline,
0039     Roto_spline,
0040     Wipe,
0041     Url,
0042     Keywords,
0043     Fontfamily,
0044     Filterjob,
0045     Readonly,
0046     Hidden
0047 };
0048 Q_DECLARE_METATYPE(ParamType)
0049 
0050 /** @class AssetParameterModel
0051     @brief This class is the model for a list of parameters.
0052    The behaviour of a transition or an effect is typically  controlled by several parameters. This class exposes this parameters as a list that can be rendered
0053    using the relevant widgets.
0054    Note that internally parameters are not sorted in any ways, because some effects like sox need a precise order
0055     */
0056 class AssetParameterModel : public QAbstractListModel, public enable_shared_from_this_virtual<AssetParameterModel>
0057 {
0058     Q_OBJECT
0059 
0060     friend class KeyframeModelList;
0061     friend class KeyframeModel;
0062 
0063 public:
0064     /**
0065      *
0066      * @param asset
0067      * @param assetXml XML to parse, from project file
0068      * @param assetId
0069      * @param ownerId
0070      * @param originalDecimalPoint If a decimal point other than “.” was used, try to replace all occurrences by a “.”
0071      * so numbers are parsed correctly.
0072      * @param parent
0073      */
0074     explicit AssetParameterModel(std::unique_ptr<Mlt::Properties> asset, const QDomElement &assetXml, const QString &assetId, ObjectId ownerId,
0075                                  const QString &originalDecimalPoint = QString(), QObject *parent = nullptr);
0076     ~AssetParameterModel() override;
0077     enum DataRoles {
0078         NameRole = Qt::UserRole + 1,
0079         TypeRole,
0080         CommentRole,
0081         AlternateNameRole,
0082         MinRole,
0083         VisualMinRole,
0084         VisualMaxRole,
0085         MaxRole,
0086         DefaultRole,
0087         SuffixRole,
0088         DecimalsRole,
0089         OddRole,
0090         ValueRole,
0091         AlphaRole,
0092         ListValuesRole,
0093         ListNamesRole,
0094         ListDependenciesRole,
0095         NewStuffRole,
0096         ModeRole,
0097         FactorRole,
0098         FilterRole,
0099         FilterJobParamsRole,
0100         FilterProgressRole,
0101         FilterParamsRole,
0102         FilterConsumerParamsRole,
0103         ScaleRole,
0104         OpacityRole,
0105         RelativePosRole,
0106         // The filter in/out should always be 0 - full length
0107         RequiresInOut,
0108         ToTimePosRole,
0109         // Don't display this param in timeline keyframes
0110         ShowInTimelineRole,
0111         InRole,
0112         OutRole,
0113         ParentInRole,
0114         ParentPositionRole,
0115         ParentDurationRole,
0116         HideKeyframesFirstRole,
0117         List1Role,
0118         List2Role,
0119         Enum1Role,
0120         Enum2Role,
0121         Enum3Role,
0122         Enum4Role,
0123         Enum5Role,
0124         Enum6Role,
0125         Enum7Role,
0126         Enum8Role,
0127         Enum9Role,
0128         Enum10Role,
0129         Enum11Role,
0130         Enum12Role,
0131         Enum13Role,
0132         Enum14Role,
0133         Enum15Role,
0134         Enum16Role
0135     };
0136 
0137     /** @brief Returns true if @param type is animated */
0138     static bool isAnimated(ParamType type);
0139 
0140     /** @brief Returns the id of the asset represented by this object */
0141     QString getAssetId() const;
0142     const QString getAssetMltId();
0143     void setActive(bool active);
0144     bool isActive() const;
0145 
0146     /** @brief Set the parameter with given name to the given value
0147      */
0148     Q_INVOKABLE void setParameter(const QString &name, const QString &paramValue, bool update = true, const QModelIndex &paramIndex = QModelIndex());
0149     void setParameter(const QString &name, int value, bool update = true);
0150 
0151     /** @brief Return all the parameters as pairs (parameter name, parameter value) */
0152     QVector<QPair<QString, QVariant>> getAllParameters() const;
0153     /** @brief Get a parameter value from its name */
0154     const QVariant getParamFromName(const QString &paramName);
0155     /** @brief Get a parameter index from its name */
0156     const QModelIndex getParamIndexFromName(const QString &paramName);
0157     /** @brief Returns a json definition of the effect with all param values
0158      *  @param selection only export keyframes matching the selected index, or all keyframes if empty
0159      *  @param includeFixed if true, also export the fixed (non user editable) parameters for this effect
0160      */
0161     QJsonDocument toJson(QVector<int> selection = {}, bool includeFixed = true) const;
0162     /** @brief Returns the interpolated value at the given position with all param values as json*/
0163     QJsonDocument valueAsJson(int pos, bool includeFixed = true) const;
0164 
0165     void savePreset(const QString &presetFile, const QString &presetName);
0166     void deletePreset(const QString &presetFile, const QString &presetName);
0167     const QStringList getPresetList(const QString &presetFile) const;
0168     const QVector<QPair<QString, QVariant>> loadPreset(const QString &presetFile, const QString &presetName);
0169 
0170     /* Which monitor is attached to this asset (clip/project)
0171      */
0172     Kdenlive::MonitorId monitorId;
0173 
0174     QVariant data(const QModelIndex &index, int role) const override;
0175     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0176 
0177     /** @brief Returns the id of the actual object associated with this asset */
0178     ObjectId getOwnerId() const;
0179 
0180     /** @brief Returns the keyframe model associated with this asset
0181        Return empty ptr if there is no keyframable parameter in the asset or if prepareKeyframes was not called
0182      */
0183     Q_INVOKABLE std::shared_ptr<KeyframeModelList> getKeyframeModel();
0184 
0185     /** @brief Must be called before using the keyframes of this model */
0186     void prepareKeyframes(int in = -1, int out = -1);
0187     void resetAsset(std::unique_ptr<Mlt::Properties> asset);
0188     /** @brief Returns true if the effect has more than one keyframe */
0189     bool hasMoreThanOneKeyframe() const;
0190     int time_to_frames(const QString &time) const;
0191     void passProperties(Mlt::Properties &target);
0192     /** @brief Returns a list of the parameter names that are keyframable, along with param type and opacity use */
0193     QMap<QString, std::pair<ParamType, bool>> getKeyframableParameters() const;
0194 
0195     /** @brief Returns the current value of an effect parameter */
0196     const QString getParam(const QString &paramName);
0197     /** @brief Returns the current asset */
0198     Mlt::Properties *getAsset();
0199     /** @brief Returns a frame time as click time (00:00:00.000) */
0200     const QString framesToTime(int t) const;
0201 
0202 public Q_SLOTS:
0203     /** @brief Sets the value of a list of parameters
0204        @param params contains the pairs (parameter name, parameter value)
0205      */
0206     void setParameters(const paramVector &params, bool update = true);
0207     /** @brief Sets the value of a list of parameters. If the parameters have keyframes, ensuring all keyframable params get the keyframes
0208        @param params contains the pairs (parameter name, parameter value)
0209      */
0210     void setParametersFromTask(const paramVector &params);
0211     /** @brief Set a filter job's progress */
0212     void setProgress(int progress);
0213 
0214 protected:
0215     /** @brief Helper function to retrieve the type of a parameter given the string corresponding to it*/
0216     static ParamType paramTypeFromStr(const QString &type);
0217 
0218     static QString getDefaultKeyframes(int start, const QString &defaultValue, bool linearOnly);
0219 
0220     /** @brief Helper function to get an attribute from a dom element, given its name.
0221        The function additionally parses following keywords:
0222        - %width and %height that are replaced with profile's height and width.
0223        If keywords are found, mathematical operations are supported for double type params. For example "%width -1" is a valid value.
0224     */
0225     QVariant parseAttribute(const ObjectId &owner, const QString &attribute, const QDomElement &element, QVariant defaultValue = QVariant()) const;
0226     QVariant parseSubAttributes(const QString &attribute, const QDomElement &element) const;
0227 
0228     /** @brief Helper function to register one more parameter that is keyframable.
0229        @param index is the index corresponding to this parameter
0230     */
0231     void addKeyframeParam(const QModelIndex &index, int in, int out);
0232 
0233     struct ParamRow
0234     {
0235         ParamType type;
0236         QDomElement xml;
0237         QVariant value;
0238         QString name;
0239     };
0240 
0241     QString m_assetId;
0242     ObjectId m_ownerId;
0243     bool m_active;
0244     /** @brief Keep track of parameter order, important for sox */
0245     std::vector<QString> m_paramOrder;
0246     /** @brief Store all parameters by name */
0247     std::unordered_map<QString, ParamRow> m_params;
0248     /** @brief We store values of fixed parameters aside */
0249     std::unordered_map<QString, QVariant> m_fixedParams;
0250     /** @brief We store the params name in order of parsing. The order is important (cf some effects like sox) */
0251     QVector<QString> m_rows;
0252 
0253     std::unique_ptr<Mlt::Properties> m_asset;
0254 
0255     std::shared_ptr<KeyframeModelList> m_keyframes;
0256     QVector<int> m_selectedKeyframes;
0257     int m_activeKeyframe;
0258     /** @brief if true, keyframe tools will be hidden by default */
0259     bool m_hideKeyframesByDefault;
0260     /** @brief if true, the effect's in/out will always be synced to clip in/out */
0261     bool m_requiresInOut;
0262     /** @brief true if this is an audio effect, used to prevent unnecessary monitor refresh / timeline invalidate */
0263     bool m_isAudio;
0264     /** @brief Store a filter's job progress */
0265     int m_filterProgress;
0266 
0267     /** @brief Set the parameter with given name to the given value. This should be called when first
0268      *  building an effect in the constructor, so that we don't call shared_from_this
0269      */
0270     void internalSetParameter(const QString name, const QString paramValue, const QModelIndex &paramIndex = QModelIndex());
0271 
0272 Q_SIGNALS:
0273     void modelChanged();
0274     /** @brief inform child effects (in case of bin effect with timeline producers)
0275      *  that a change occurred and a param update is needed **/
0276     void updateChildren(const QStringList &names);
0277     void compositionTrackChanged();
0278     void replugEffect(std::shared_ptr<AssetParameterModel> asset);
0279     void rebuildEffect(std::shared_ptr<AssetParameterModel> asset);
0280     void enabledChange(bool);
0281     void hideKeyframesChange(bool);
0282     void showEffectZone(ObjectId id, QPair<int, int> inOut, bool checked);
0283 };