Commit 88c56c11 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Automatically convert old custom effects to new type (and make a backup copy in the legacy folder)

Going to Settings > Run Config Wizard will launch the update process
Related to #188
parent f960577d
Pipeline #3752 passed with stage
in 23 minutes and 10 seconds
......@@ -22,6 +22,7 @@
#include "profiles/profilemodel.hpp"
#include "profiles/profilerepository.hpp"
#include "profilesdialog.h"
#include "effects/effectsrepository.hpp"
#include "utils/thememanager.h"
#ifdef USE_V4L
......@@ -108,6 +109,24 @@ Wizard::Wizard(bool autoClose, bool appImageCheck, QWidget *parent)
if (autoClose) {
// This is a first run instance, check HW encoders
testHwEncoders();
} else {
QPair<QStringList, QStringList> conversion = EffectsRepository::get()->fixDeprecatedEffects();
if (conversion.first.count() > 0) {
QLabel *lab = new QLabel(this);
lab->setText(i18n("Converting old custom effects successful:"));
m_startLayout->addWidget(lab);
QListWidget *list = new QListWidget(this);
m_startLayout->addWidget(list);
list->addItems(conversion.first);
}
if (conversion.second.count() > 0) {
QLabel *lab = new QLabel(this);
lab->setText(i18n("Converting old custom effects failed:"));
m_startLayout->addWidget(lab);
QListWidget *list = new QListWidget(this);
m_startLayout->addWidget(list);
list->addItems(conversion.second);
}
}
if (!m_errors.isEmpty() || !m_warnings.isEmpty() || (!m_infos.isEmpty() && !appImageCheck)) {
QLabel *lab = new QLabel(this);
......
......@@ -204,3 +204,132 @@ QPair<QString, QString> EffectsRepository::reloadCustom(const QString &path)
}
return result;
}
QPair <QStringList, QStringList> EffectsRepository::fixDeprecatedEffects()
{
QString customAssetDir = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("effects"), QStandardPaths::LocateDirectory);
QPair <QStringList, QStringList> results;
QDir current_dir(customAssetDir);
QStringList filter;
filter << QStringLiteral("*.xml");
QStringList fileList = current_dir.entryList(filter, QDir::Files);
QStringList failed;
for (const auto &file : fileList) {
QString path = current_dir.absoluteFilePath(file);
QPair <QString, QString> fixResult = fixCustomAssetFile(path);
if (!fixResult.first.isEmpty()) {
results.first << fixResult.first;
} else if (!fixResult.second.isEmpty()) {
results.second << fixResult.second;
}
}
return results;
}
QPair <QString, QString> EffectsRepository::fixCustomAssetFile(const QString &path)
{
QPair <QString, QString> results;
QFile file(path);
QDomDocument doc;
doc.setContent(&file, false);
file.close();
QDomElement base = doc.documentElement();
if (base.tagName() == QLatin1String("effectgroup")) {
// Groups not implemented
return results;
}
QDomNodeList effects = doc.elementsByTagName(QStringLiteral("effect"));
int nbr_effect = effects.count();
if (nbr_effect == 0) {
qDebug() << "+++++++++++++\nEffect broken: " << path << "\n+++++++++++";
results.second = path;
return results;
}
bool effectAdjusted = false;
for (int i = 0; i < nbr_effect; ++i) {
QDomNode currentNode = effects.item(i);
if (currentNode.isNull()) {
continue;
}
QDomElement currentEffect = currentNode.toElement();
Info result;
bool ok = parseInfoFromXml(currentEffect, result);
if (!ok) {
continue;
}
if (currentEffect.hasAttribute(QLatin1String("kdenlive_info"))) {
// This is a pre 19.x custom effect, adjust param values
// First backup effect in legacy folder
QDir dir(QFileInfo(path).absoluteDir());
if (!dir.mkpath(QStringLiteral("legacy"))) {
// Cannot create the legacy folder, abort
qDebug()<<" = = = Could not create legacy folder in : "<<dir.absolutePath();
results.second = path;
return results;
}
currentEffect.removeAttribute(QLatin1String("kdenlive_info"));
effectAdjusted = true;
QDomNodeList params = currentEffect.elementsByTagName(QLatin1String("parameter"));
for (int j = 0; j < params.count(); ++j) {
QDomNode node = params.item(j);
if (node.isNull()) {
continue;
}
QDomElement param = node.toElement();
if (param.hasAttribute(QLatin1String("factor")) && (param.attribute(QLatin1String("type")) == QLatin1String("simplekeyframe") || param.attribute(QLatin1String("type")) == QLatin1String("animated"))) {
// This is an old style effect, adjust current and default values
QString currentValue;
if (!param.hasAttribute(QLatin1String("value"))) {
currentValue = param.attribute(QLatin1String("keyframes"));
} else {
currentValue = param.attribute(QLatin1String("value"));
}
ok = false;
int factor = param.attribute(QLatin1String("factor")).toInt(&ok);
if (ok) {
double defaultVal = param.attribute(QLatin1String("default")).toDouble() / factor;
param.setAttribute(QLatin1String("default"), QString::number(defaultVal));
qDebug()<<" = = \nadjusting default to: "<<defaultVal;
if (currentValue.contains(QLatin1Char('='))) {
QStringList valueStr = currentValue.split(QLatin1Char(';'));
QStringList resultStr;
for (const QString &val : valueStr) {
if (val.contains(QLatin1Char('='))) {
QString frame = val.section(QLatin1Char('='), 0, 0);
QString frameVal = val.section(QLatin1Char('='), 1);
double v = frameVal.toDouble() / factor;
resultStr << QString("%1=%2").arg(frame).arg(v);
} else {
double v = val.toDouble() / factor;
resultStr << QString::number(v);
}
}
param.setAttribute(QLatin1String("value"), resultStr.join(QLatin1Char(';')));
qDebug()<<"=== ADJUSTED VAL: "<<resultStr.join(QLatin1Char(';'));
}
}
}
}
}
result.xml = currentEffect;
}
if (effectAdjusted) {
QDir dir(QFileInfo(path).absoluteDir());
dir.cd(QStringLiteral("legacy"));
if (!file.copy(dir.absoluteFilePath(QFileInfo(file).fileName()))) {
// Cannot copy the backup file
qDebug()<<" = = = Could not copy file in : "<<dir.absoluteFilePath(QFileInfo(file).fileName());
results.second = path;
return results;
}
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
QTextStream out(&file);
out << doc.toString();
}
file.close();
results.first = path;
}
return results;
}
......@@ -54,6 +54,10 @@ public:
/* @brief Returns whether this belongs to main effects */
bool isPreferred(const QString &effectId) const;
/* @brief Check custom effects (older custom effects need an update to default and current values
* returns a list of effects that were incorrectly converted */
QPair<QStringList, QStringList> fixDeprecatedEffects();
protected:
// Constructor is protected because class is a Singleton
EffectsRepository();
......@@ -78,6 +82,8 @@ protected:
/* @brief Returns the metadata associated with the given asset*/
Mlt::Properties *getMetadata(const QString &assetId) override;
QPair <QString, QString> fixCustomAssetFile(const QString &path);
static std::unique_ptr<EffectsRepository> instance;
static std::once_flag m_onceFlag; // flag to create the repository only once;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment