[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kservice] /: KPluginInfo: use KPluginMetaData instead of a QVariantMap for storage
From:       Alex Richardson <arichardson.kde () gmail ! com>
Date:       2014-11-11 11:20:28
Message-ID: E1Xo9Uq-0003ta-Vk () scm ! kde ! org
[Download RAW message or body]

Git commit 0442befd7d3e7e396e0ee369ac877042bc2422ef by Alex Richardson.
Committed on 05/09/2014 at 00:40.
Pushed by arichardson into branch 'master'.

KPluginInfo: use KPluginMetaData instead of a QVariantMap for storage

This means that KPluginInfo can now simply reuse the QJsonObject
returned by QPluginLoader.metaData() (by storing it in a
KPluginMetaData object instead of having to convert the JSON to a
QVariantMap first.

Additionally this allows very efficient conversion between KPluginInfo
and KPluginMetaData.

REVIEW: 120198

M  +9    -2    autotests/kplugininfotest.cpp
M  +126  -120  src/services/kplugininfo.cpp
M  +11   -0    src/services/kplugininfo.h

http://commits.kde.org/kservice/0442befd7d3e7e396e0ee369ac877042bc2422ef

diff --git a/autotests/kplugininfotest.cpp b/autotests/kplugininfotest.cpp
index 9d4ee04..5a996c3 100644
--- a/autotests/kplugininfotest.cpp
+++ b/autotests/kplugininfotest.cpp
@@ -96,7 +96,7 @@ private Q_SLOTS:
         QCOMPARE(info.isHidden(), false);
         QCOMPARE(info.isPluginEnabled(), false);
         QCOMPARE(info.isPluginEnabledByDefault(), true);
-        QCOMPARE(info.libraryPath(), QStringLiteral("fakeplugin"));
+        QCOMPARE(info.libraryPath(), \
QFileInfo(QStringLiteral("fakeplugin")).absoluteFilePath());  \
QCOMPARE(info.license(), QStringLiteral("LGPL"));  QCOMPARE(info.pluginName(), \
QStringLiteral("fakeplugin"));  QCOMPARE(info.serviceTypes(), QStringList() << \
"KService/NSA"); @@ -189,10 +189,17 @@ private Q_SLOTS:
         KPluginInfo infoGerman = KPluginInfo::fromMetaData(meta);
         QLocale::setDefault(QLocale::c());
 
+        // translations work correctly here since they are not fixed at load time
+        QCOMPARE(info.name(), QStringLiteral("NSA Plugin"));
+        QCOMPARE(infoGerman.name(), QStringLiteral("NSA Plugin"));
         QCOMPARE(info.comment(), QStringLiteral("Test Plugin Spy"));
+        QCOMPARE(infoGerman.comment(), QStringLiteral("Test Plugin Spy"));
+        QLocale::setDefault(QLocale(QLocale::German, QLocale::Germany));
+        QCOMPARE(info.comment(), QStringLiteral("Test-Spionagemodul"));
         QCOMPARE(infoGerman.comment(), QStringLiteral("Test-Spionagemodul"));
-        QCOMPARE(info.name(), QStringLiteral("NSA Plugin"));
+        QCOMPARE(info.name(), QStringLiteral("NSA-Modul"));
         QCOMPARE(infoGerman.name(), QStringLiteral("NSA-Modul"));
+        QLocale::setDefault(QLocale::c());
 
         QCOMPARE(info.author(), QStringLiteral("Sebastian Kügler"));
         QCOMPARE(info.category(), QStringLiteral("Examples"));
diff --git a/src/services/kplugininfo.cpp b/src/services/kplugininfo.cpp
index 54593e5..3915d75 100644
--- a/src/services/kplugininfo.cpp
+++ b/src/services/kplugininfo.cpp
@@ -62,30 +62,91 @@ static const char s_xKDEServiceTypes[] = "X-KDE-ServiceTypes";
 static const char s_enabledbyDefaultKey[] = "X-KDE-PluginInfo-EnabledByDefault";
 static const char s_enabledKey[] = "Enabled";
 
+// these keys are used in the json metadata
+static const char s_jsonDescriptionKey[] = "Description";
+static const char s_jsonAuthorsKey[] = "Authors";
+static const char s_jsonEmailKey[] = "Email";
+static const char s_jsonCategoryKey[] = "Category";
+static const char s_jsonDependenciesKey[] = "Dependencies";
+static const char s_jsonEnabledByDefaultKey[] = "EnabledByDefault";
+static const char s_jsonLicenseKey[] = "License";
+static const char s_jsonIdKey[] = "Id";
+static const char s_jsonVersionKey[] = "Version";
+static const char s_jsonWebsiteKey[] = "Website";
+static const char s_jsonKPluginKey[] = "KPlugin";
+
 class KPluginInfoPrivate : public QSharedData
 {
 public:
     KPluginInfoPrivate()
         : hidden(false)
-        , enabledbydefault(false)
         , pluginenabled(false)
         , kcmservicesCached(false)
     {}
 
     QString entryPath; // the filename of the file containing all the info
-    QString libraryPath;
 
     bool hidden : 1;
-    bool enabledbydefault : 1;
     bool pluginenabled : 1;
     mutable bool kcmservicesCached : 1;
 
-    QVariantMap metaData;
+    KPluginMetaData metaData;
     KConfigGroup config;
     KService::Ptr service;
     mutable QList<KService::Ptr> kcmservices;
 };
 
+// maps the KService, QVariant and KDesktopFile keys to the new KPluginMetaData keys
+template<typename T, typename Func>
+static QJsonObject mapToJsonKPluginKey(const QString &name, const QString \
&description, +        const QStringList &dependencies, const QStringList \
&serviceTypes, const T &data, Func accessor) +{
+    /* Metadata structure is as follows:
+     "KPlugin": {
+        "Name": "Date and Time",
+        "Description": "Date and time by timezone",
+        "Icon": "preferences-system-time",
+        "Authors": { "Name": "Aaron Seigo", "Email": "aseigo@kde.org" },
+        "Category": "Date and Time",
+        "Dependencies": [],
+        "EnabledByDefault": "true",
+        "License": "LGPL",
+        "Id": "time",
+        "Version": "1.0",
+        "Website": "http://plasma.kde.org/",
+        "ServiceTypes": ["Plasma/DataEngine"]
+     }
+     */
+    QJsonObject kplugin;
+    kplugin[s_nameKey] = name;
+    kplugin[s_jsonDescriptionKey] = description;
+    kplugin[s_iconKey] = accessor(data, s_iconKey);
+    QJsonObject authors;
+    authors[s_nameKey] = accessor(data, s_authorKey);
+    authors[s_jsonEmailKey] = accessor(data, s_emailKey);
+    kplugin[s_jsonAuthorsKey] = authors;
+    kplugin[s_jsonCategoryKey] = accessor(data, s_categoryKey);
+    const bool enabledByDefault = accessor(data, \
s_enabledbyDefaultKey).compare("true", Qt::CaseInsensitive) == 0; +    \
kplugin[s_jsonEnabledByDefaultKey] = enabledByDefault; +    kplugin[s_jsonLicenseKey] \
= accessor(data, s_licenseKey); +    kplugin[s_jsonIdKey] = accessor(data, \
s_pluginNameKey); +    kplugin[s_jsonVersionKey] = accessor(data, s_versionKey);
+    kplugin[s_jsonWebsiteKey] = accessor(data, s_websiteKey);
+    kplugin[s_serviceTypesKey] = QJsonArray::fromStringList(serviceTypes);
+    kplugin[s_jsonDependenciesKey] = QJsonArray::fromStringList(dependencies);
+    return kplugin;
+}
+
+KPluginInfo::KPluginInfo(const KPluginMetaData &md)
+    :d(new KPluginInfoPrivate)
+{
+    if (!md.isValid()) {
+        d.reset();
+        return;
+    }
+    d->metaData = md;
+}
+
 KPluginInfo::KPluginInfo(const QString &filename /*, \
QStandardPaths::StandardLocation resource*/)  : d(new KPluginInfoPrivate)
 {
@@ -104,29 +165,23 @@ KPluginInfo::KPluginInfo(const QString &filename /*, \
QStandardPaths::StandardLoc  return;
     }
 
-    d->metaData.insert(s_nameKey, file.readName());
-    d->metaData.insert(s_commentKey, file.readComment());
-    d->metaData.insert(s_iconKey, cg.readEntryUntranslated(s_iconKey));
-    d->metaData.insert(s_authorKey, cg.readEntryUntranslated(s_authorKey));
-    d->metaData.insert(s_emailKey, cg.readEntryUntranslated(s_emailKey));
-    d->metaData.insert(s_pluginNameKey, cg.readEntryUntranslated(s_pluginNameKey));
-    d->metaData.insert(s_versionKey, cg.readEntryUntranslated(s_versionKey));
-    d->metaData.insert(s_websiteKey, cg.readEntryUntranslated(s_websiteKey));
-    d->metaData.insert(s_categoryKey, cg.readEntryUntranslated(s_categoryKey));
-    d->metaData.insert(s_licenseKey, cg.readEntryUntranslated(s_licenseKey));
-    d->metaData.insert(s_dependenciesKey, cg.readEntry(s_dependenciesKey, \
                QStringList()));
-    d->metaData.insert(s_enabledbyDefaultKey, \
                cg.readEntryUntranslated(s_enabledbyDefaultKey));
-    d->metaData.insert(s_serviceTypesKey, \
                cg.readEntryUntranslated(s_serviceTypesKey));
-    d->metaData.insert(s_xKDEServiceTypes, \
                cg.readEntryUntranslated(s_xKDEServiceTypes));
-    d->enabledbydefault = cg.readEntry(s_enabledbyDefaultKey, false);
-    d->libraryPath = cg.readEntry(s_libraryKey);
+    QStringList serviceTypes = cg.readEntry(s_xKDEServiceTypes, QStringList());
+    if (serviceTypes.isEmpty()) {
+        serviceTypes = cg.readEntry(s_serviceTypesKey, QStringList());
+    }
+    QJsonObject json;
+    QJsonObject kplugin = mapToJsonKPluginKey(file.readName(), file.readComment(),
+            cg.readEntry(s_dependenciesKey, QStringList()), serviceTypes, cg,
+            [](const KConfigGroup &cg, const char *key) { return \
cg.readEntryUntranslated(key); }); +    json[s_jsonKPluginKey] = kplugin;
+
+    d->metaData = KPluginMetaData(json, cg.readEntry(s_libraryKey));
 }
 
 KPluginInfo::KPluginInfo(const QVariantList &args, const QString &libraryPath)
     : d(new KPluginInfoPrivate)
 {
     static const QString metaData = QStringLiteral("MetaData");
-    d->libraryPath = libraryPath;
     d->entryPath = QFileInfo(libraryPath).absoluteFilePath();
 
     foreach (const QVariant &v, args) {
@@ -134,17 +189,32 @@ KPluginInfo::KPluginInfo(const QVariantList &args, const \
QString &libraryPath)  const QVariantMap &m = v.toMap();
             const QVariant &_metadata = m.value(metaData);
             if (_metadata.canConvert<QVariantMap>()) {
-                d->metaData = _metadata.value<QVariantMap>();
+                const QVariantMap &map = _metadata.toMap();
+                if (map.value(s_hiddenKey).toBool()) {
+                    d->hidden = true;
+                    break;
+                }
+
+                QStringList serviceTypes = \
map.value(s_xKDEServiceTypes).toStringList(); +                if \
(serviceTypes.isEmpty()) { +                    serviceTypes = \
map.value(s_serviceTypesKey).toStringList(); +                }
+                QJsonObject json = QJsonObject::fromVariantMap(map);
+                if (!json.value(s_jsonKPluginKey).isObject()) {
+                    // if the converted JSON object does not have a "KPlugin" key \
yet it means +                    // that we are converting from a .desktop style \
variant map +                    QString name = \
KPluginMetaData::readTranslatedString(json, s_nameKey); +                    QString \
description = KPluginMetaData::readTranslatedString(json, s_commentKey); +            \
QJsonObject kplugin = mapToJsonKPluginKey(name, description, +                        \
map.value(s_dependenciesKey, QStringList()).toStringList(), serviceTypes, json, +     \
[](const QJsonObject &o, const char *key) { return o.value(key).toString(); }); +     \
json[s_jsonKPluginKey] = kplugin; +                }
+                d->metaData = KPluginMetaData(json, libraryPath);
                 break;
             }
         }
     }
-
-    d->hidden = d->metaData.value(s_hiddenKey).toBool();
-    if (d->hidden) {
-        return;
-    }
-    d->enabledbydefault = d->metaData.value(s_enabledbyDefaultKey).toBool();
 }
 
 #ifndef KSERVICE_NO_DEPRECATED
@@ -157,28 +227,19 @@ KPluginInfo::KPluginInfo(const KService::Ptr service)
     }
     d->service = service;
     d->entryPath = service->entryPath();
-    d->libraryPath = service->library();
 
     if (service->isDeleted()) {
         d->hidden = true;
         return;
     }
 
-    d->metaData.insert(s_nameKey, service->name());
-    d->metaData.insert(s_commentKey, service->comment());
-    d->metaData.insert(s_iconKey, service->icon());
-    d->metaData.insert(s_authorKey, service->property(s_authorKey));
-    d->metaData.insert(s_emailKey, service->property(s_emailKey));
-    d->metaData.insert(s_pluginNameKey, service->property(s_pluginNameKey));
-    d->metaData.insert(s_versionKey, service->property(s_versionKey));
-    d->metaData.insert(s_websiteKey, service->property(s_websiteKey));
-    d->metaData.insert(s_categoryKey, service->property(s_categoryKey));
-    d->metaData.insert(s_licenseKey, service->property(s_licenseKey));
-    d->metaData.insert(s_dependenciesKey, service->property(s_dependenciesKey));
-    d->metaData.insert(s_xKDEServiceTypes, service->serviceTypes());
-    QVariant tmp = service->property(s_enabledbyDefaultKey);
-    d->metaData.insert(s_enabledbyDefaultKey, tmp.toBool());
-    d->enabledbydefault = d->metaData.value(s_enabledbyDefaultKey).toBool();
+    QJsonObject json;
+    QJsonObject kplugin = mapToJsonKPluginKey(service->name(), service->comment(),
+            service->property(s_dependenciesKey).toStringList(), \
service->serviceTypes(), service, +            [](const KService::Ptr service, const \
char *key) { return service->property(key).toString(); }); +    \
json[s_jsonKPluginKey] = kplugin; +
+    d->metaData = KPluginMetaData(json, service->library());
 }
 #endif
 
@@ -301,25 +362,25 @@ bool KPluginInfo::isPluginEnabledByDefault() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
     //qDebug() << Q_FUNC_INFO;
-    return d->enabledbydefault;
+    return d->metaData.isEnabledByDefault();
 }
 
 QString KPluginInfo::name() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    return d->metaData.value(s_nameKey).toString();
+    return d->metaData.name();
 }
 
 QString KPluginInfo::comment() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    return d->metaData.value(s_commentKey).toString();
+    return d->metaData.description();
 }
 
 QString KPluginInfo::icon() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    return d->metaData.value(s_iconKey).toString();
+    return d->metaData.iconName();
 }
 
 QString KPluginInfo::entryPath() const
@@ -331,49 +392,51 @@ QString KPluginInfo::entryPath() const
 QString KPluginInfo::author() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    return d->metaData.value(s_authorKey).toString();
+    const QList<KAboutPerson> &authors = d->metaData.authors();
+    return authors.isEmpty() ? QString() : authors[0].name();
 }
 
 QString KPluginInfo::email() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    return d->metaData.value(s_emailKey).toString();
+    const QList<KAboutPerson> &authors = d->metaData.authors();
+    return authors.isEmpty() ? QString() : authors[0].emailAddress();
 }
 
 QString KPluginInfo::category() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    return d->metaData.value(s_categoryKey).toString();
+    return d->metaData.category();
 }
 
 QString KPluginInfo::pluginName() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    return d->metaData.value(s_pluginNameKey).toString();
+    return d->metaData.pluginId();
 }
 
 QString KPluginInfo::libraryPath() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    return d->libraryPath;
+    return d->metaData.fileName();
 }
 
 QString KPluginInfo::version() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    return d->metaData.value(s_versionKey).toString();
+    return d->metaData.version();
 }
 
 QString KPluginInfo::website() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    return d->metaData.value(s_websiteKey).toString();
+    return d->metaData.website();
 }
 
 QString KPluginInfo::license() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    return d->metaData.value(s_licenseKey).toString();
+    return d->metaData.license();
 }
 
 #if 0
@@ -387,17 +450,13 @@ KAboutLicense KPluginInfo::fullLicense() const
 QStringList KPluginInfo::dependencies() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    return d->metaData.value(s_dependenciesKey).toStringList();
+    return d->metaData.dependencies();
 }
 
 QStringList KPluginInfo::serviceTypes() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    QStringList serviceTypes = d->metaData.value(s_xKDEServiceTypes).toStringList();
-    if (serviceTypes.isEmpty()) {
-        serviceTypes = d->metaData.value(s_serviceTypesKey).toStringList();
-    }
-    return serviceTypes;
+    return d->metaData.serviceTypes();
 }
 
 KService::Ptr KPluginInfo::service() const
@@ -438,12 +497,12 @@ QVariant KPluginInfo::property(const QString &key) const
     if (d->service) {
         return d->service->property(key);
     }
-    return d->metaData.value(key);
+    return d->metaData.rawData().value(key).toVariant();
 }
 
 QVariantMap KPluginInfo::properties() const
 {
-    return d->metaData;
+    return d->metaData.rawData().toVariantMap();
 }
 
 void KPluginInfo::save(KConfigGroup config)
@@ -489,67 +548,14 @@ uint qHash(const KPluginInfo &p)
 
 KPluginInfo KPluginInfo::fromMetaData(const KPluginMetaData &md)
 {
-    QVariantMap metaData = md.rawData().toVariantMap();
-    const QList<KAboutPerson> &authors = md.authors();
-    if (!authors.isEmpty()) {
-        metaData[s_authorKey] = authors[0].name();
-        metaData[s_emailKey] = authors[0].emailAddress();
-    }
-    metaData[s_categoryKey] = md.category();
-    metaData[s_commentKey] = md.description();
-    metaData[s_dependenciesKey] = md.dependencies();
-    metaData[s_enabledbyDefaultKey] = md.isEnabledByDefault();
-    metaData[s_iconKey] = md.iconName();
-    metaData[s_licenseKey] = md.license();
-    metaData[s_nameKey] = md.name();
-    metaData[s_pluginNameKey] = md.pluginId();
-    metaData[s_xKDEServiceTypes] = md.serviceTypes();
-    metaData[s_versionKey] = md.version();
-    metaData[s_websiteKey] = md.website();
-    QVariantMap result;
-    result[QStringLiteral("MetaData")] = metaData;
-    return KPluginInfo(QVariantList() << result, md.fileName());
+    KPluginInfo ret;
+    return KPluginInfo(md);
 }
 
 KPluginMetaData KPluginInfo::toMetaData() const
 {
     KPLUGININFO_ISVALID_ASSERTION;
-    QJsonObject metadata = QJsonObject::fromVariantMap(d->metaData);
-    QJsonObject kplugin;
-    /* Metadata structure is as follows:
-     "KPlugin": {
-        "Name": "Date and Time",
-        "Description": "Date and time by timezone",
-        "Icon": "preferences-system-time",
-        "Authors": { "Name": "Aaron Seigo", "Email": "aseigo@kde.org" },
-        "Category": "Date and Time",
-        "Dependencies": [],
-        "EnabledByDefault": "true",
-        "License": "LGPL",
-        "Id": "time",
-        "Version": "1.0",
-        "Website": "http://plasma.kde.org/",
-        "ServiceTypes": ["Plasma/DataEngine"]
-     }
-     */
-    const QString nameStr = QStringLiteral("Name");
-    kplugin[nameStr] = name();
-    kplugin[QStringLiteral("Description")] = comment();
-    kplugin[QStringLiteral("Icon")] = icon();
-    QJsonObject authors;
-    authors[nameStr] = author();
-    authors[QStringLiteral("Email")] = email();
-    kplugin[QStringLiteral("Authors")] = authors;
-    kplugin[QStringLiteral("Category")] = category();
-    kplugin[QStringLiteral("Dependencies")] = \
                QJsonArray::fromStringList(dependencies());
-    kplugin[QStringLiteral("EnabledByDefault")] = isPluginEnabledByDefault();
-    kplugin[QStringLiteral("License")] = license();
-    kplugin[QStringLiteral("Id")] = pluginName();
-    kplugin[QStringLiteral("Version")] = version();
-    kplugin[QStringLiteral("Website")] = website();
-    kplugin[QStringLiteral("ServiceTypes")] = \
                QJsonArray::fromStringList(serviceTypes());
-    metadata[QStringLiteral("KPlugin")] = kplugin;
-    return KPluginMetaData(metadata, d->libraryPath);
+    return d->metaData;
 }
 
 KPluginMetaData KPluginInfo::toMetaData(const KPluginInfo& info)
diff --git a/src/services/kplugininfo.h b/src/services/kplugininfo.h
index 871d6a2..7b98576 100644
--- a/src/services/kplugininfo.h
+++ b/src/services/kplugininfo.h
@@ -159,6 +159,17 @@ public:
      */
     explicit KPluginInfo(const QVariantList &args, const QString &libraryPath = \
QString());  
+
+    /**
+     * Read plugin info from a KPluginMetaData object.
+     *
+     * @param md The KPluginMetaData to read the information from
+     * @see K_PLUGIN_FACTORY_WITH_JSON()
+     * @see KPluginLoader
+     * @since 5.5
+     */
+    explicit KPluginInfo(const KPluginMetaData &md);
+
     /**
      * Creates an invalid plugin.
      *


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic