diff --git a/shell/scripting/scriptengine_v1.cpp b/shell/scripting/scriptengine_v1.cpp index e349c26a3..660c18b53 100644 --- a/shell/scripting/scriptengine_v1.cpp +++ b/shell/scripting/scriptengine_v1.cpp @@ -86,9 +86,35 @@ namespace { const QScriptValue &array; }; - #define SCRIPT_FOREACH(Variable, Array) \ + #define SCRIPT_ARRAY_FOREACH(Variable, Array) \ ScriptArray_forEach_Helper(Array) + [&] (const QScriptValue &Variable) + class ScriptObject_forEach_Helper { + public: + ScriptObject_forEach_Helper(const QScriptValue &object) + : object(object) + { + } + + // operator + is commonly used for these things + // to avoid having the lambda inside the parenthesis + template + void operator+ (Function function) const + { + QScriptValueIterator it(object); + while (it.hasNext()) { + it.next(); + function(it.name(), it.value()); + } + } + + private: + const QScriptValue &object; + }; + + #define SCRIPT_OBJECT_FOREACH(Key, Value, Array) \ + ScriptObject_forEach_Helper(Array) + [&] (const QString &Key, const QScriptValue &Value) + // Case insensitive comparison of two strings template inline bool matches(const QString &object, const StringType &string) @@ -264,27 +290,19 @@ QScriptValue ScriptEngine::V1::activities(QScriptContext *context, QScriptEngine template void loadSerializedConfigs(Object *object, const QScriptValue &configs) { - SCRIPT_FOREACH(config, configs) { + SCRIPT_OBJECT_FOREACH(escapedGroup, config, configs) { // If the config group is set, pass it on to the containment - auto currentConfigGroup = config.property("currentConfigGroup"); - if (currentConfigGroup.isArray()) { - QStringList groups; - SCRIPT_FOREACH(group, currentConfigGroup) { - groups << group.toString(); - }; - object->setCurrentConfigGroup(groups); - // qDebug() << "DESERIALIZATION: currentConfigGroup = " << groups; + QStringList groups = escapedGroup.split('/', QString::SkipEmptyParts); + for (QString &group: groups) { + group = QUrl::fromPercentEncoding(group.toUtf8()); } + qDebug() << "Config group" << groups; + object->setCurrentConfigGroup(groups); // Read other properties and set the configuration - QScriptValueIterator it(config); - while (it.hasNext()) { - it.next(); - if (it.name() == "currentConfigGroup") continue; - - object->writeConfig(it.name(), it.value().toVariant()); - // qDebug() << "DESERIALIZATION: writeConfig(...) " << it.name() << it.value().toVariant(); - } + SCRIPT_OBJECT_FOREACH(key, value, config) { + object->writeConfig(key, value.toVariant()); + }; }; } @@ -310,7 +328,7 @@ QScriptValue ScriptEngine::V1::loadSerializedLayout(QScriptContext *context, QSc // qDebug() << "DESKTOP DESERIALIZATION: Loading desktops..."; int count = 0; - SCRIPT_FOREACH(desktopData, data.property("desktops")) { + SCRIPT_ARRAY_FOREACH(desktopData, data.property("desktops")) { // If the template has more desktops than we do, ignore them if (count >= desktops.size()) return; @@ -325,7 +343,7 @@ QScriptValue ScriptEngine::V1::loadSerializedLayout(QScriptContext *context, QSc loadSerializedConfigs(desktop, desktopData.property("config")); // After the config, we want to load the applets - SCRIPT_FOREACH(appletData, desktopData.property("applets")) { + SCRIPT_ARRAY_FOREACH(appletData, desktopData.property("applets")) { // qDebug() << "DESKTOP DESERIALIZATION: Applet: " << appletData.toString(); // TODO: It would be nicer to be able to call addWidget directly @@ -352,7 +370,7 @@ QScriptValue ScriptEngine::V1::loadSerializedLayout(QScriptContext *context, QSc // qDebug() << "PANEL DESERIALIZATION: Loading panels..."; - SCRIPT_FOREACH(panelData, data.property("panels")) { + SCRIPT_ARRAY_FOREACH(panelData, data.property("panels")) { const auto panel = qobject_cast(env->createContainment( QStringLiteral("Panel"), QStringLiteral("org.kde.panel"))); @@ -366,7 +384,7 @@ QScriptValue ScriptEngine::V1::loadSerializedLayout(QScriptContext *context, QSc loadSerializedConfigs(panel, panelData.property("config")); // Now dealing with the applets - SCRIPT_FOREACH(appletData, panelData.property("applets")) { + SCRIPT_ARRAY_FOREACH(appletData, panelData.property("applets")) { // qDebug() << "PANEL DESERIALIZATION: Applet: " << appletData.toString(); // TODO: It would be nicer to be able to call addWidget directly diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp index cd64e34f8..81afbddcd 100644 --- a/shell/shellcorona.cpp +++ b/shell/shellcorona.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -316,11 +317,12 @@ void ShellCorona::setShell(const QString &shell) } -QJsonArray dumpconfigGroupJS(const KConfigGroup &rootGroup) +QJsonObject dumpconfigGroupJS(const KConfigGroup &rootGroup) { - QJsonArray result; + QJsonObject result; QStringList hierarchy; + QStringList escapedHierarchy; QList groups{rootGroup}; QSet visitedNodes; @@ -333,6 +335,10 @@ QJsonArray dumpconfigGroupJS(const KConfigGroup &rootGroup) QStringLiteral("plugin") }; + auto groupID = [&escapedHierarchy]() { + return '/' + escapedHierarchy.join('/'); + }; + // Perform a depth-first tree traversal for config groups while (!groups.isEmpty()) { KConfigGroup cg = groups.last(); @@ -341,27 +347,21 @@ QJsonArray dumpconfigGroupJS(const KConfigGroup &rootGroup) //FIXME: name is not enough hierarchy.clear(); + escapedHierarchy.clear(); while (parentCg.isValid() && parentCg.name() != rootGroup.name()) { - hierarchy.prepend(parentCg.name()); + const auto name = parentCg.name(); + hierarchy.prepend(name); + escapedHierarchy.prepend(QString::fromUtf8(QUrl::toPercentEncoding(name.toUtf8()))); parentCg = parentCg.parent(); } - visitedNodes.insert(hierarchy.join(QChar())); + visitedNodes.insert(groupID()); groups.pop_back(); QJsonObject configGroupJson; if (!cg.keyList().isEmpty()) { //TODO: this is conditional if applet or containment - if (hierarchy.length() > 0) { - QJsonArray currentConfigGroup; - - foreach (const QString &item, hierarchy) { - currentConfigGroup << item; - } - - configGroupJson.insert("currentConfigGroup", currentConfigGroup); - } const auto map = cg.entryMap(); auto i = map.cbegin(); @@ -375,14 +375,14 @@ QJsonArray dumpconfigGroupJS(const KConfigGroup &rootGroup) foreach (const QString &groupName, cg.groupList()) { if (groupName == QStringLiteral("Applets") || - visitedNodes.contains(hierarchy.join(QChar()) + groupName)) { + visitedNodes.contains(groupID() + '/' + groupName)) { continue; } groups << KConfigGroup(&cg, groupName); } if (!configGroupJson.isEmpty()) { - result << configGroupJson; + result.insert(groupID(), configGroupJson); } }