]> git.sesse.net Git - kdenlive/blobdiff - src/documentvalidator.cpp
Merge branch 'master' into next
[kdenlive] / src / documentvalidator.cpp
index ce1c83ab03e8e72c990c7e54488a890b8dc4f99e..a31c18a841cf29688b6d1b06a38267fdf5c709fb 100644 (file)
@@ -69,16 +69,15 @@ bool DocumentValidator::validate(const double currentVersion)
     }
     
     documentLocale.setNumberOptions(QLocale::OmitGroupSeparator);
-    if (documentLocale != QLocale()) {
+    if (documentLocale.decimalPoint() != QLocale().decimalPoint()) {
+        // If loading an older MLT file without LC_NUMERIC, set locale to C which was previously the default
+        if (!mlt.hasAttribute("LC_NUMERIC")) setlocale(LC_NUMERIC, "C");
+
         QLocale::setDefault(documentLocale);
         // locale conversion might need to be redone
         initEffects::parseEffectFiles();
     }
 
-    // TODO: remove after string freeze
-    if (0)
-        KMessageBox::sorry(kapp->activeWindow(), i18n("The document you are opening uses a different locale (%1) than your system. You can only open and render it, no editing is supported unless you change your system's locale.", mlt.attribute("LC_NUMERIC")), i18n("Read only project"));
-
     // Upgrade the document to the latest version
     if (!upgrade(documentLocale.toDouble(kdenliveDoc.attribute("version")), currentVersion))
         return false;
@@ -1031,26 +1030,36 @@ bool DocumentValidator::isModified() const
 
 void DocumentValidator::updateEffects()
 {
-    // WARNING: order by findDirs will determine which js file to use (in case multiple for the same filter exist)
+    // WARNING: order by findDirs will determine which js file to use (in case multiple scripts for the same filter exist)
     QMap <QString, KUrl> paths;
+#if QT_VERSION >= 0x040700
     QMap <QString, QScriptProgram> scripts;
+#else
+    QMap <QString, QString> scripts;
+#endif
     QStringList directories = KGlobal::dirs()->findDirs("appdata", "effects/update");
     foreach (const QString &directoryName, directories) {
         QDir directory(directoryName);
         QStringList fileList = directory.entryList(QStringList() << "*.js", QDir::Files);
         foreach (const QString &fileName, fileList) {
             QString identifier = fileName;
+            // remove extension (".js")
             identifier.chop(3);
-            identifier.replace('_', '.');
             paths.insert(identifier, KUrl(directoryName + fileName));
         }
     }
 
     QDomNodeList effects = m_doc.elementsByTagName("filter");
-
-    for(int i = 0; i < effects.count(); ++i) {
+    int max = effects.count();
+    QStringList safeEffects;
+    for(int i = 0; i < max; ++i) {
         QDomElement effect = effects.at(i).toElement();
         QString effectId = EffectsList::property(effect, "kdenlive_id");
+        if (safeEffects.contains(effectId)) {
+            // Do not check the same effect twice if it is at the correct version
+            // (assume we don't have different versions of the same effect in a project file)
+            continue;
+        }
         QString effectTag = EffectsList::property(effect, "tag");
         QString effectVersionStr = EffectsList::property(effect, "version");
         double effectVersion = effectVersionStr.isNull() ? -1 : effectVersionStr.toDouble();
@@ -1074,29 +1083,82 @@ void DocumentValidator::updateEffects()
                     if (!scriptFile.open(QIODevice::ReadOnly)) {
                         continue;
                     }
+#if QT_VERSION >= 0x040700
                     QScriptProgram scriptProgram(scriptFile.readAll());
+#else
+                    QString scriptProgram = scriptFile.readAll();
+#endif
                     scriptFile.close();
                     scripts.insert(effectId, scriptProgram);
                 }
 
-                QDomDocument scriptDoc;
-                scriptDoc.appendChild(scriptDoc.importNode(effect, true));
-
                 QScriptEngine scriptEngine;
                 scriptEngine.importExtension("qt.core");
                 scriptEngine.importExtension("qt.xml");
                 scriptEngine.evaluate(scripts.value(effectId));
-                QString effectString = scriptEngine.globalObject().property("update").call(QScriptValue(), QScriptValueList()  << serviceVersion << effectVersion << scriptDoc.toString()).toString();
-
-                if (!effectString.isEmpty()) {
-                    scriptDoc.setContent(effectString);
-                    QDomNode updatedEffect = effect.ownerDocument().importNode(scriptDoc.documentElement(), true);
-                    effect.parentNode().replaceChild(updatedEffect, effect);
-                    // TODO: set version to avoid dependency on latest MLT
-                    m_modified = true;
+                QScriptValue updateRules = scriptEngine.globalObject().property("update");
+                if (!updateRules.isValid())
+                    continue;
+                if (updateRules.isFunction()) {
+                    QDomDocument scriptDoc;
+                    scriptDoc.appendChild(scriptDoc.importNode(effect, true));
+
+                    QString effectString = updateRules.call(QScriptValue(), QScriptValueList()  << serviceVersion << effectVersion << scriptDoc.toString()).toString();
+
+                    if (!effectString.isEmpty() && !scriptEngine.hasUncaughtException()) {
+                        scriptDoc.setContent(effectString);
+                        QDomNode updatedEffect = effect.ownerDocument().importNode(scriptDoc.documentElement(), true);
+                        effect.parentNode().replaceChild(updatedEffect, effect);
+                        m_modified = true;
+                    }
+                } else {
+                    m_modified = updateEffectParameters(effect.childNodes(), &updateRules, serviceVersion, effectVersion);
+                }
+
+                // set version number since MLT won't change it (only initially set it)
+                QDomElement versionElem = effect.firstChildElement("version");
+                if (EffectsList::property(effect, "version").isNull()) {
+                    versionElem = effect.ownerDocument().createTextNode(QLocale().toString(serviceVersion)).toElement();
+                    versionElem.setTagName("property");
+                    versionElem.setAttribute("name", "version");
+                    effect.appendChild(versionElem);
+                } else {
+                    EffectsList::setProperty(effect, "version", QLocale().toString(serviceVersion));
                 }
             }
+            else safeEffects.append(effectId);
         }
     }
 }
 
+bool DocumentValidator::updateEffectParameters(QDomNodeList parameters, const QScriptValue* updateRules, const double serviceVersion, const double effectVersion)
+{
+    bool updated = false;
+    bool isDowngrade = serviceVersion < effectVersion;
+    for (int i = 0; i < parameters.count(); ++i) {
+        QDomElement parameter = parameters.at(i).toElement();
+        QScriptValue rules = updateRules->property(parameter.attribute("name"));
+        if (rules.isValid() && rules.isArray()) {
+            int rulesCount = rules.property("length").toInt32();
+            if (isDowngrade) {
+                // start with the highest version and downgrade step by step
+                for (int j = rulesCount - 1; j >= 0; --j) {
+                    double version = rules.property(j).property(0).toNumber();
+                    if (version <= effectVersion && version > serviceVersion) {
+                        parameter.firstChild().setNodeValue(rules.property(j).property(1).call(QScriptValue(), QScriptValueList() << parameter.text() << isDowngrade).toString());
+                        updated = true;
+                    }
+                }
+            } else {
+                for (int j = 0; j < rulesCount; ++j) {
+                    double version = rules.property(j).property(0).toNumber();
+                    if (version > effectVersion && version <= serviceVersion) {
+                        parameter.firstChild().setNodeValue(rules.property(j).property(1).call(QScriptValue(), QScriptValueList() << parameter.text() << isDowngrade).toString());
+                        updated = true;
+                    }
+                }
+            }
+        }
+    }
+    return updated;
+}