summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@qt.io>2022-03-03 23:59:50 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-03-21 18:50:05 +0000
commit751bd656094764cdee1ad6d1d74fa9b306c231c1 (patch)
treed80420032a6fd3fc5deb3628e1524487ae39ddab
parent6a8133d41446c7ccbb7467e87190d2d68ae542c0 (diff)
downloadqtapplicationmanager-751bd656094764cdee1ad6d1d74fa9b306c231c1.tar.gz
Untangle the icon/name/description/categories mess
The documentation and the implementation disagreed quite heavily in regards to the icon, name, description and categories fields in the manifest for the package, each application and each intent. The implementation now follows the existing documentation, but also relaxing the requirements of icon and name being required for packages. Also, it was confusing that applications could not override these properties from the package like intents can do, so they also got these properties. Finally, everything is now correctly exposed to QML, with legacy wrappers in place to not break old code. In addition, the completely outdated applicationinfo unit-test was rewritten to test all the current field combinations. Change-Id: Ie5ad84bc6b771d6702b1994d1c8ae9f0204643b9 Reviewed-by: Bernd Weimer <bernd.weimer@qt.io> Reviewed-by: Dominik Holland <dominik.holland@qt.io> (cherry picked from commit 3af34ee549f6514a3396b196edc6b8415c8db3af) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--doc/manifest.qdoc43
-rw-r--r--doc/migration-guide-6.3.qdoc44
-rw-r--r--qmltypes/QtApplicationManager/SystemUI/plugins.qmltypes15
-rw-r--r--src/application-lib/applicationinfo.cpp42
-rw-r--r--src/application-lib/applicationinfo.h15
-rw-r--r--src/application-lib/intentinfo.cpp12
-rw-r--r--src/application-lib/intentinfo.h4
-rw-r--r--src/application-lib/packageinfo.cpp29
-rw-r--r--src/application-lib/packageinfo.h5
-rw-r--r--src/application-lib/yamlpackagescanner.cpp24
-rw-r--r--src/common-lib/utilities.cpp16
-rw-r--r--src/common-lib/utilities.h3
-rw-r--r--src/intent-server-lib/intent.cpp95
-rw-r--r--src/intent-server-lib/intent.h9
-rw-r--r--src/intent-server-lib/intentserver.cpp5
-rw-r--r--src/intent-server-lib/intentserver.h3
-rw-r--r--src/manager-lib/application.cpp107
-rw-r--r--src/manager-lib/application.h18
-rw-r--r--src/manager-lib/installationtask.cpp2
-rw-r--r--src/manager-lib/intentaminterface.cpp28
-rw-r--r--src/manager-lib/intentaminterface.h3
-rw-r--r--src/manager-lib/package.cpp33
-rw-r--r--tests/auto/applicationinfo/CMakeLists.txt13
-rw-r--r--tests/auto/applicationinfo/data/full/info.yaml118
-rw-r--r--tests/auto/applicationinfo/data/inherit/info.yaml28
-rw-r--r--tests/auto/applicationinfo/data/legacy/info.yaml (renamed from tests/data/manifests/com.pelagicore.test/info.yaml)11
-rw-r--r--tests/auto/applicationinfo/data/minimal/info.yaml8
-rw-r--r--tests/auto/applicationinfo/tst_applicationinfo.cpp456
-rw-r--r--tests/auto/main/tst_main.cpp12
-rw-r--r--tests/auto/packager-tool/tst_packager-tool.cpp1
-rw-r--r--tests/data/manifests/com.pelagicore.json-legacy/info.yaml19
31 files changed, 923 insertions, 298 deletions
diff --git a/doc/manifest.qdoc b/doc/manifest.qdoc
index db6ceb7d..113ec207 100644
--- a/doc/manifest.qdoc
+++ b/doc/manifest.qdoc
@@ -125,14 +125,15 @@ The fields within the \c info.yaml manifest data (second YAML document) are as f
\li \c name
\target package-name-map
\li object
- \li \e Required. An object containing language (\c string) to display name (\c string)
+ \li An optional object containing language (\c string) to display name (\c string)
mappings. The language identifiers need to adhere to the standard POSIX locale definition.
- For more information, see \l{QLocale}. At least one mapping needs to be present. However,
- it is good practice to supply the English (\c en) mapping, at least, as a fallback.
+ For more information, see \l{QLocale}. It is good practice to supply at least the English
+ (\c en) mapping, as a fallback. If not supplying any mapping at all, the name will be the
+ same as the \c id.
\row
\li \c description
\li object
- \li \e An optional object containing language (\c string) to descriptive name (\c string)
+ \li An optional object containing language (\c string) to descriptive name (\c string)
mappings. This field uses the same syntax as the \c name field.
\row
\li \c categories
@@ -256,6 +257,28 @@ The fields used for each item within the \c applications list are as follows:
\li If provided, it is used as the automotive DLT application description, which allows to
augment the short DLT application ID with a more verbose description. If not explicitly
provided, a default description is used.
+\row
+ \li \c name
+ \li object
+ \li The name of the application. It will default to the \c name field in the global package
+ section, but it can be overwritten for each application by specifying this field.
+\row
+ \li \c icon
+ \li string
+ \li The icon of the application. It will default to the \c icon field in the global package
+ section, but it can be overwritten for each application by specifying this field.
+\row
+ \li \c description
+ \li object
+ \li The description of the application. It will default to the \c description field in the
+ global package section, but it can be overwritten for each application by specifying this
+ field.
+\row
+ \li \c categories
+ \li object
+ \li The list of categories for this application. It will default to the \c categories field in
+ the global package section, but it can be overwritten for each application by specifying
+ this field.
\endtable
\target manifest-intent
@@ -301,23 +324,23 @@ The fields used for each item within the \c intents list are as follows:
\row
\li \c name
\li object
- \li The name of the intent. It will default to the \c name field in the global section, but it
- can be overridden for each intent by specifying this field.
+ \li The name of the intent. It will default to the \c name field in the global package section,
+ but it can be overwritten for each intent by specifying this field.
\row
\li \c icon
\li string
- \li The icon of the intent. It will default to the \c icon field in the global section, but it
- can be overridden for each intent by specifying this field.
+ \li The icon of the intent. It will default to the \c icon field in the global package section,
+ but it can be overwritten for each intent by specifying this field.
\row
\li \c description
\li object
\li The description of the intent. It will default to the \c description field in the global
- section, but it can be overridden for each intent by specifying this field.
+ package section, but it can be overwritten for each intent by specifying this field.
\row
\li \c categories
\li object
\li The list of categories for this intent. It will default to the \c categories field in the
- global section, but it can be overridden for each intent by specifying this field.
+ global package section, but it can be overwritten for each intent by specifying this field.
\endtable
diff --git a/doc/migration-guide-6.3.qdoc b/doc/migration-guide-6.3.qdoc
new file mode 100644
index 00000000..6d70211e
--- /dev/null
+++ b/doc/migration-guide-6.3.qdoc
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\page migration-guide-6.3.html
+\ingroup qtappman
+\ingroup qtappman-highlights
+\title Migrating code from 6.2 to 6.3
+\brief Discusses factors for moving from the 6.2 to the 6.3 release of the Application Manager.
+
+Qt Application Manager 6.3 cleaned up the APIs and manifest definitions concerning the Package,
+Application and Intent fields for \c icon, \c name and \c description.
+All three support the same API now, with the package's fields acting as a fallback for both the
+application and intent objects.
+Due to a clash between the property \c name and the function \c name in ApplicationObject,
+user code that called the \c{Application.name(language)} function before, now needs to replace
+this with \c{Application.names[language]}.
+
+*/
diff --git a/qmltypes/QtApplicationManager/SystemUI/plugins.qmltypes b/qmltypes/QtApplicationManager/SystemUI/plugins.qmltypes
index 89bc3d52..aa4d5e8c 100644
--- a/qmltypes/QtApplicationManager/SystemUI/plugins.qmltypes
+++ b/qmltypes/QtApplicationManager/SystemUI/plugins.qmltypes
@@ -107,6 +107,8 @@ Module {
Property { name: "icon"; type: "QUrl"; isReadonly: true }
Property { name: "name"; type: "string"; isReadonly: true }
Property { name: "names"; type: "QVariantMap"; isReadonly: true }
+ Property { name: "description"; type: "string"; isReadonly: true }
+ Property { name: "descriptions"; type: "QVariantMap"; isReadonly: true }
Property { name: "categories"; type: "QStringList"; isReadonly: true }
}
Component {
@@ -461,6 +463,12 @@ Module {
prototype: "QObject"
isCreatable: false
Property { name: "id"; type: "string"; isReadonly: true }
+ Property { name: "name"; type: "string"; isReadonly: true }
+ Property { name: "names"; type: "QVariantMap"; isReadonly: true }
+ Property { name: "description"; type: "string"; isReadonly: true }
+ Property { name: "descriptions"; type: "QVariantMap"; isReadonly: true }
+ Property { name: "categories"; type: "QStringList"; isReadonly: true }
+ Property { name: "icon"; type: "QUrl"; isReadonly: true }
Property { name: "runtimeName"; type: "string"; isReadonly: true }
Property { name: "runtimeParameters"; type: "QVariantMap"; isReadonly: true }
Property { name: "capabilities"; type: "QStringList"; isReadonly: true }
@@ -473,11 +481,9 @@ Module {
Property { name: "codeDir"; type: "string"; isReadonly: true }
Property { name: "runState"; type: "RunState"; isReadonly: true }
Property { name: "package"; type: "Package"; isPointer: true; isReadonly: true }
- Property { name: "icon"; type: "QUrl"; isReadonly: true }
Property { name: "builtIn"; type: "bool"; isReadonly: true }
Property { name: "alias"; type: "bool"; isReadonly: true }
Property { name: "nonAliased"; type: "Application"; isPointer: true; isReadonly: true }
- Property { name: "categories"; type: "QStringList"; isReadonly: true }
Property { name: "version"; type: "string"; isReadonly: true }
Property { name: "state"; type: "State"; isReadonly: true }
Property { name: "blocked"; type: "bool"; isReadonly: true }
@@ -536,11 +542,6 @@ Module {
Method {
name: "stop"
}
- Method {
- name: "name"
- type: "string"
- Parameter { name: "language"; type: "string"; }
- }
}
Component {
name: "NotificationManager"
diff --git a/src/application-lib/applicationinfo.cpp b/src/application-lib/applicationinfo.cpp
index af60949c..73507967 100644
--- a/src/application-lib/applicationinfo.cpp
+++ b/src/application-lib/applicationinfo.cpp
@@ -82,7 +82,7 @@ QVariantMap ApplicationInfo::allAppProperties() const
}
-const quint32 ApplicationInfo::DataStreamVersion = 3;
+const quint32 ApplicationInfo::DataStreamVersion = 4;
void ApplicationInfo::writeToDataStream(QDataStream &ds) const
@@ -100,7 +100,11 @@ void ApplicationInfo::writeToDataStream(QDataStream &ds) const
<< m_capabilities
<< m_openGLConfiguration
<< m_dltConfiguration
- << m_supportedMimeTypes;
+ << m_supportedMimeTypes
+ << m_categories
+ << m_names
+ << m_descriptions
+ << m_icon;
}
ApplicationInfo *ApplicationInfo::readFromDataStream(PackageInfo *pkg, QDataStream &ds)
@@ -120,7 +124,11 @@ ApplicationInfo *ApplicationInfo::readFromDataStream(PackageInfo *pkg, QDataStre
>> app->m_capabilities
>> app->m_openGLConfiguration
>> app->m_dltConfiguration
- >> app->m_supportedMimeTypes;
+ >> app->m_supportedMimeTypes
+ >> app->m_categories
+ >> app->m_names
+ >> app->m_descriptions
+ >> app->m_icon;
uniqueCounter = qMax(uniqueCounter, app->m_uniqueNumber);
app->m_capabilities.sort();
@@ -141,13 +149,13 @@ QVariantMap ApplicationInfo::toVariantMap() const
{
QVariantMap displayName;
- auto names = packageInfo()->names();
- for (auto it = names.constBegin(); it != names.constEnd(); ++it)
+ const auto n = names();
+ for (auto it = n.constBegin(); it != n.constEnd(); ++it)
displayName.insert(it.key(), it.value());
map[qSL("displayName")] = displayName;
}
- map[qSL("displayIcon")] = packageInfo()->icon();
+ map[qSL("displayIcon")] = icon();
map[qSL("applicationProperties")] = m_allAppProperties;
map[qSL("codeFilePath")] = m_codeFilePath;
map[qSL("runtimeName")] = m_runtimeName;
@@ -155,7 +163,7 @@ QVariantMap ApplicationInfo::toVariantMap() const
map[qSL("capabilities")] = m_capabilities;
map[qSL("mimeTypes")] = m_supportedMimeTypes;
- map[qSL("categories")] = packageInfo()->categories();
+ map[qSL("categories")] = categories();
map[qSL("version")] = packageInfo()->version();
map[qSL("baseDir")] = packageInfo()->baseDir().absolutePath();
map[qSL("codeDir")] = map[qSL("baseDir")]; // 5.12 backward compatibility
@@ -217,4 +225,24 @@ QVariantMap ApplicationInfo::dltConfiguration() const
return m_dltConfiguration;
}
+QStringList ApplicationInfo::categories() const
+{
+ return m_categories.isEmpty() ? m_packageInfo->categories() : m_categories;
+}
+
+QMap<QString, QString> ApplicationInfo::names() const
+{
+ return m_names.isEmpty() ? m_packageInfo->names() : m_names;
+}
+
+QMap<QString, QString> ApplicationInfo::descriptions() const
+{
+ return m_descriptions.isEmpty() ? m_packageInfo->descriptions() : m_descriptions;
+}
+
+QString ApplicationInfo::icon() const
+{
+ return m_icon.isEmpty() ? m_packageInfo->icon() : m_icon;
+}
+
QT_END_NAMESPACE_AM
diff --git a/src/application-lib/applicationinfo.h b/src/application-lib/applicationinfo.h
index 284bb577..b3cbf125 100644
--- a/src/application-lib/applicationinfo.h
+++ b/src/application-lib/applicationinfo.h
@@ -71,13 +71,19 @@ public:
bool supportsApplicationInterface() const;
QVariantMap dltConfiguration() const;
+ QStringList categories() const;
+
+ QMap<QString, QString> names() const;
+ QMap<QString, QString> descriptions() const;
+ QString icon() const;
+
void writeToDataStream(QDataStream &ds) const;
static ApplicationInfo *readFromDataStream(PackageInfo *pkg, QDataStream &ds);
private:
void read(QDataStream &ds);
- // static part from info.json
+ // static part from the manifest
PackageInfo *m_packageInfo;
QString m_id;
@@ -86,7 +92,7 @@ private:
QVariantMap m_sysAppProperties;
QVariantMap m_allAppProperties;
- QString m_codeFilePath; // relative to info.json location
+ QString m_codeFilePath; // relative to the manifest's location
QString m_runtimeName;
QVariantMap m_runtimeParameters;
bool m_supportsApplicationInterface = false;
@@ -96,6 +102,11 @@ private:
QString m_documentUrl; // deprecated
QVariantMap m_dltConfiguration;
+ QStringList m_categories;
+ QMap<QString, QString> m_names; // language -> name
+ QMap<QString, QString> m_descriptions; // language -> description
+ QString m_icon; // relative to the manifest's location
+
friend class ApplicationManager; // needed to update installation status
friend class PackageDatabase; // needed to create ApplicationInfo objects
friend class InstallationTask; // needed to set m_uid and m_builtin during the installation
diff --git a/src/application-lib/intentinfo.cpp b/src/application-lib/intentinfo.cpp
index 0d7eb578..86d61ec3 100644
--- a/src/application-lib/intentinfo.cpp
+++ b/src/application-lib/intentinfo.cpp
@@ -78,19 +78,9 @@ QMap<QString, QString> IntentInfo::names() const
return m_names.isEmpty() ? m_packageInfo->names() : m_names;
}
-QString IntentInfo::name(const QString &language) const
-{
- return m_names.isEmpty() ? m_packageInfo->name(language) : m_names.value(language);
-}
-
QMap<QString, QString> IntentInfo::descriptions() const
{
- return m_descriptions;
-}
-
-QString IntentInfo::description(const QString &language) const
-{
- return m_descriptions.value(language);
+ return m_descriptions.isEmpty() ? m_packageInfo->descriptions() : m_descriptions;
}
QString IntentInfo::icon() const
diff --git a/src/application-lib/intentinfo.h b/src/application-lib/intentinfo.h
index 7feb0c3e..20e460be 100644
--- a/src/application-lib/intentinfo.h
+++ b/src/application-lib/intentinfo.h
@@ -67,9 +67,7 @@ public:
QStringList categories() const;
QMap<QString, QString> names() const;
- QString name(const QString &language) const;
QMap<QString, QString> descriptions() const;
- QString description(const QString &language) const;
QString icon() const;
void writeToDataStream(QDataStream &ds) const;
@@ -86,7 +84,7 @@ private:
QStringList m_categories;
QMap<QString, QString> m_names; // language -> name
QMap<QString, QString> m_descriptions; // language -> description
- QString m_icon; // relative to info.json location
+ QString m_icon; // relative to the manifest's location
friend class YamlPackageScanner;
Q_DISABLE_COPY(IntentInfo)
diff --git a/src/application-lib/packageinfo.cpp b/src/application-lib/packageinfo.cpp
index d097291c..0af26b58 100644
--- a/src/application-lib/packageinfo.cpp
+++ b/src/application-lib/packageinfo.cpp
@@ -82,21 +82,11 @@ QMap<QString, QString> PackageInfo::names() const
return m_names;
}
-QString PackageInfo::name(const QString &language) const
-{
- return m_names.value(language);
-}
-
QMap<QString, QString> PackageInfo::descriptions() const
{
return m_descriptions;
}
-QString PackageInfo::description(const QString &language) const
-{
- return m_descriptions.value(language);
-}
-
QString PackageInfo::icon() const
{
return m_icon;
@@ -282,25 +272,6 @@ bool PackageInfo::isValidApplicationId(const QString &appId, QString *errorStrin
}
}
-bool PackageInfo::isValidIcon(const QString &icon, QString *errorString)
-{
- try {
- if (icon.isEmpty())
- throw Exception("empty path");
-
- QFileInfo fileInfo(icon);
-
- if (fileInfo.fileName() != icon)
- throw Exception("'%1' is not a valid file name").arg(icon);
-
- return true;
- } catch (const Exception &e) {
- if (errorString)
- *errorString = e.errorString();
- return false;
- }
-}
-
QString PackageInfo::manifestPath() const
{
return m_baseDir.filePath(m_manifestName);
diff --git a/src/application-lib/packageinfo.h b/src/application-lib/packageinfo.h
index 21b7a791..a8f85e90 100644
--- a/src/application-lib/packageinfo.h
+++ b/src/application-lib/packageinfo.h
@@ -62,9 +62,7 @@ public:
QString id() const;
QMap<QString, QString> names() const;
- QString name(const QString &language) const;
QMap<QString, QString> descriptions() const;
- QString description(const QString &language) const;
QString icon() const;
QStringList categories() const;
@@ -86,7 +84,6 @@ public:
static PackageInfo *readFromDataStream(QDataStream &ds);
static bool isValidApplicationId(const QString &appId, QString *errorString = nullptr);
- static bool isValidIcon(const QString &icon, QString *errorString = nullptr);
QString manifestPath() const;
@@ -100,7 +97,7 @@ private:
QMap<QString, QString> m_names; // language -> name
QMap<QString, QString> m_descriptions; // language -> description
QStringList m_categories;
- QString m_icon; // relative to info.json location
+ QString m_icon; // relative to the manifest's location
QString m_version;
bool m_builtIn = false; // system package - not removable
uint m_uid = uint(-1); // unix user id - move to installationReport
diff --git a/src/application-lib/yamlpackagescanner.cpp b/src/application-lib/yamlpackagescanner.cpp
index 03790656..c6a2da5b 100644
--- a/src/application-lib/yamlpackagescanner.cpp
+++ b/src/application-lib/yamlpackagescanner.cpp
@@ -98,16 +98,13 @@ PackageInfo *YamlPackageScanner::scan(QIODevice *source, const QString &fileName
if (legacyAppInfo)
legacyAppInfo->m_id = pkgInfo->id();
});
- fields.emplace_back("icon", true, YamlParser::Scalar, [&pkgInfo](YamlParser *p) {
+ fields.emplace_back("icon", false, YamlParser::Scalar, [&pkgInfo](YamlParser *p) {
pkgInfo->m_icon = p->parseString();
});
- fields.emplace_back("name", true, YamlParser::Map, [&pkgInfo](YamlParser *p) {
+ fields.emplace_back("name", false, YamlParser::Map, [&pkgInfo](YamlParser *p) {
auto nameMap = p->parseMap();
for (auto it = nameMap.constBegin(); it != nameMap.constEnd(); ++it)
pkgInfo->m_names.insert(it.key(), it.value().toString());
-
- if (pkgInfo->m_names.isEmpty())
- throw YamlParserException(p, "the 'name' field must not be empty");
});
if (!legacy) {
fields.emplace_back("description", false, YamlParser::Map, [&pkgInfo](YamlParser *p) {
@@ -208,6 +205,23 @@ PackageInfo *YamlPackageScanner::scan(QIODevice *source, const QString &fileName
throw YamlParserException(p, "found two applications with the same id %1").arg(id);
appInfo->m_id = id;
});
+ appFields.emplace_back("icon", false, YamlParser::Scalar, [&appInfo](YamlParser *p) {
+ appInfo->m_icon = p->parseString();
+ });
+ appFields.emplace_back("name", false, YamlParser::Map, [&appInfo](YamlParser *p) {
+ const auto nameMap = p->parseMap();
+ for (auto it = nameMap.constBegin(); it != nameMap.constEnd(); ++it)
+ appInfo->m_names.insert(it.key(), it.value().toString());
+ });
+ appFields.emplace_back("description", false, YamlParser::Map, [&appInfo](YamlParser *p) {
+ const auto descriptionMap = p->parseMap();
+ for (auto it = descriptionMap.constBegin(); it != descriptionMap.constEnd(); ++it)
+ appInfo->m_descriptions.insert(it.key(), it.value().toString());
+ });
+ appFields.emplace_back("categories", false, YamlParser::Scalar | YamlParser::List, [&appInfo](YamlParser *p) {
+ appInfo->m_categories = p->parseStringOrStringList();
+ appInfo->m_categories.sort();
+ });
appFields.emplace_back("code", true, YamlParser::Scalar, [&appInfo](YamlParser *p) {
appInfo->m_codeFilePath = p->parseString();
});
diff --git a/src/common-lib/utilities.cpp b/src/common-lib/utilities.cpp
index 811365d4..b5b5b4e5 100644
--- a/src/common-lib/utilities.cpp
+++ b/src/common-lib/utilities.cpp
@@ -337,4 +337,20 @@ void recursiveMergeVariantMap(QVariantMap &into, const QVariantMap &from)
recursiveMergeMap(&into, from);
}
+QString translateFromMap(const QMap<QString, QString> &languageToName, const QString &defaultName)
+{
+ if (!languageToName.isEmpty()) {
+ QString name = languageToName.value(QLocale::system().name()); //TODO: language changes
+ if (name.isNull())
+ name = languageToName.value(qSL("en"));
+ if (name.isNull())
+ name = languageToName.value(qSL("en_US"));
+ if (name.isNull())
+ name = languageToName.first();
+ return name;
+ } else {
+ return defaultName;
+ }
+}
+
QT_END_NAMESPACE_AM
diff --git a/src/common-lib/utilities.h b/src/common-lib/utilities.h
index 14f71b31..63d83858 100644
--- a/src/common-lib/utilities.h
+++ b/src/common-lib/utilities.h
@@ -75,6 +75,9 @@ inline QUrl filePathToUrl(const QString &path, const QString &baseDir)
: QUrl::fromUserInput(path, baseDir, QUrl::AssumeLocalFile);
}
+// Used in {Package,Application,Intent}::name()
+QString translateFromMap(const QMap<QString, QString> &languageToName, const QString &defaultName = {});
+
inline QString urlToLocalFilePath(const QUrl &url)
{
if (url.isLocalFile())
diff --git a/src/intent-server-lib/intent.cpp b/src/intent-server-lib/intent.cpp
index 651176d6..aa5809d3 100644
--- a/src/intent-server-lib/intent.cpp
+++ b/src/intent-server-lib/intent.cpp
@@ -30,6 +30,7 @@
****************************************************************************/
#include "intent.h"
+#include "utilities.h"
#include <QRegularExpression>
#include <QVariant>
@@ -112,6 +113,61 @@ QT_BEGIN_NAMESPACE_AM
receive by setting a parameterMatch on this \c mimeType parameter, e.g.
\c{{ mimeType: "^image/.*\.png$" }}
*/
+/*!
+ \qmlproperty url IntentObject::icon
+ \readonly
+
+ The URL of the intent's icon - can be used as the source property of an \l Image.
+ If the intent does not specify an \c icon, this will return the same as the containing
+ PackageObject::icon.
+*/
+/*!
+ \qmlproperty string IntentObject::name
+ \readonly
+
+ Returns the localized name of the intent - as provided in the info.yaml file - in the currently
+ active locale.
+
+ This is a convenience property, that takes the mapping returned by the \l names property,
+ and then tries to return the value for these keys if available: first the current locale's id,
+ then \c en_US, then \c en and lastly the first available key.
+
+ If no mapping is available, this will return the \l intentId.
+*/
+/*!
+ \qmlproperty var IntentObject::names
+ \readonly
+
+ Returns an object with all the language code to localized name mappings as provided in the
+ intent's info.yaml file. If the intent does not specify a \c names object, this will
+ return the same as the containing PackageObject::names.
+*/
+/*!
+ \qmlproperty string IntentObject::description
+ \readonly
+
+ Returns the localized description of the intent - as provided in the info.yaml file - in the
+ currently active locale.
+
+ This property uses the same algorithm as the \l name property, but for the description.
+*/
+/*!
+ \qmlproperty var IntentObject::descriptions
+ \readonly
+
+ Returns an object with all the language code to localized description mappings as provided in
+ the intent's info.yaml file. If the intent does not specify a \c descriptions object,
+ this will return the same as the containing PackageObject::descriptions.
+*/
+/*!
+ \qmlproperty list<string> IntentObject::categories
+ \readonly
+
+ A list of category names the intent should be associated with. This is mainly for displaying
+ the intent within a fixed set of categories in the System UI.
+ If the intent does not specify a \c categories list, this will return the same as the
+ containing PackageObject::categories.
+*/
Intent::Intent()
@@ -120,18 +176,19 @@ Intent::Intent()
Intent::Intent(const QString &id, const QString &packageId, const QString &applicationId,
const QStringList &capabilities, Intent::Visibility visibility,
const QVariantMap &parameterMatch, const QMap<QString, QString> &names,
- const QUrl &icon, const QStringList &categories)
+ const QMap<QString, QString> &descriptions, const QUrl &icon,
+ const QStringList &categories)
: m_intentId(id)
, m_visibility(visibility)
, m_requiredCapabilities(capabilities)
, m_parameterMatch(parameterMatch)
, m_packageId(packageId)
, m_applicationId(applicationId)
+ , m_names(names)
+ , m_descriptions(descriptions)
, m_categories(categories)
, m_icon(icon)
{
- for (auto it = names.cbegin(); it != names.cend(); ++it)
- m_names.insert(it.key(), it.value());
}
QString Intent::intentId() const
@@ -213,24 +270,28 @@ QUrl Intent::icon() const
QString Intent::name() const
{
- QVariant name;
- if (!m_names.isEmpty()) {
- name = m_names.value(QLocale::system().name()); //TODO: language changes
- if (name.isNull())
- name = m_names.value(qSL("en"));
- if (name.isNull())
- name = m_names.value(qSL("en_US"));
- if (name.isNull())
- name = *m_names.constBegin();
- } else {
- name = intentId();
- }
- return name.toString();
+ return translateFromMap(m_names, intentId());
}
QVariantMap Intent::names() const
{
- return m_names;
+ QVariantMap vm;
+ for (auto it = m_names.cbegin(); it != m_names.cend(); ++it)
+ vm.insert(it.key(), it.value());
+ return vm;
+}
+
+QString Intent::description() const
+{
+ return translateFromMap(m_descriptions);
+}
+
+QVariantMap Intent::descriptions() const
+{
+ QVariantMap vm;
+ for (auto it = m_descriptions.cbegin(); it != m_descriptions.cend(); ++it)
+ vm.insert(it.key(), it.value());
+ return vm;
}
QStringList Intent::categories() const
diff --git a/src/intent-server-lib/intent.h b/src/intent-server-lib/intent.h
index fcd25969..e6c73da9 100644
--- a/src/intent-server-lib/intent.h
+++ b/src/intent-server-lib/intent.h
@@ -55,6 +55,8 @@ class Intent : public QObject
Q_PROPERTY(QUrl icon READ icon CONSTANT)
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QVariantMap names READ names CONSTANT)
+ Q_PROPERTY(QString description READ description CONSTANT)
+ Q_PROPERTY(QVariantMap descriptions READ descriptions CONSTANT)
Q_PROPERTY(QStringList categories READ categories CONSTANT)
public:
@@ -87,7 +89,8 @@ private:
Intent(const QString &intentId, const QString &packageId, const QString &applicationId,
const QStringList &capabilities, Intent::Visibility visibility,
const QVariantMap &parameterMatch, const QMap<QString, QString> &names,
- const QUrl &icon, const QStringList &categories);
+ const QMap<QString, QString> &descriptions, const QUrl &icon,
+ const QStringList &categories);
QString m_intentId;
Visibility m_visibility = Private;
@@ -97,12 +100,14 @@ private:
QString m_packageId;
QString m_applicationId;
- QVariantMap m_names; // language -> name
+ QMap<QString, QString> m_names; // language -> name
+ QMap<QString, QString> m_descriptions; // language -> description
QStringList m_categories;
QUrl m_icon;
friend class IntentServer;
friend class IntentServerHandler;
+ friend class TestPackageLoader; // for auto tests only
};
QT_END_NAMESPACE_AM
diff --git a/src/intent-server-lib/intentserver.cpp b/src/intent-server-lib/intentserver.cpp
index a55862b3..f8377579 100644
--- a/src/intent-server-lib/intentserver.cpp
+++ b/src/intent-server-lib/intentserver.cpp
@@ -235,7 +235,8 @@ Intent *IntentServer::addIntent(const QString &id, const QString &packageId,
const QString &handlingApplicationId,
const QStringList &capabilities, Intent::Visibility visibility,
const QVariantMap &parameterMatch, const QMap<QString, QString> &names,
- const QUrl &icon, const QStringList &categories)
+ const QMap<QString, QString> &descriptions, const QUrl &icon,
+ const QStringList &categories)
{
try {
if (id.isEmpty())
@@ -257,7 +258,7 @@ Intent *IntentServer::addIntent(const QString &id, const QString &packageId,
}
auto intent = new Intent(id, packageId, handlingApplicationId, capabilities, visibility,
- parameterMatch, names, icon, categories);
+ parameterMatch, names, descriptions, icon, categories);
QQmlEngine::setObjectOwnership(intent, QQmlEngine::CppOwnership);
beginInsertRows(QModelIndex(), rowCount(), rowCount());
diff --git a/src/intent-server-lib/intentserver.h b/src/intent-server-lib/intentserver.h
index ddadc6dd..873dfc7e 100644
--- a/src/intent-server-lib/intentserver.h
+++ b/src/intent-server-lib/intentserver.h
@@ -72,7 +72,8 @@ public:
Intent *addIntent(const QString &id, const QString &packageId, const QString &handlingApplicationId,
const QStringList &capabilities, Intent::Visibility visibility,
const QVariantMap &parameterMatch, const QMap<QString, QString> &names,
- const QUrl &icon, const QStringList &categories);
+ const QMap<QString, QString> &descriptions, const QUrl &icon,
+ const QStringList &categories);
void removeIntent(Intent *intent);
diff --git a/src/manager-lib/application.cpp b/src/manager-lib/application.cpp
index a09e5a70..a995ec33 100644
--- a/src/manager-lib/application.cpp
+++ b/src/manager-lib/application.cpp
@@ -35,6 +35,7 @@
#include "package.h"
#include "exception.h"
#include "logging.h"
+#include "utilities.h"
#include <QDebug>
@@ -199,14 +200,6 @@
\sa ApplicationManager::stopApplication
*/
-
-/*!
- \qmlproperty url ApplicationObject::icon
- \readonly
- \qmlobsolete
-
- Use PackageObject::icon
-*/
/*!
\qmlproperty bool ApplicationObject::builtIn
\readonly
@@ -235,13 +228,6 @@
Always returns the ApplicationObject itself.
*/
/*!
- \qmlproperty list<string> ApplicationObject::categories
- \readonly
- \qmlobsolete
-
- Use PackageObject::categories.
-*/
-/*!
\qmlproperty string ApplicationObject::version
\readonly
\qmlobsolete
@@ -263,12 +249,66 @@
Use PackageObject::version.
*/
/*!
- \qmlmethod string ApplicationObject::name(string language)
+ \qmlproperty enumeration ApplicationObject::state
+ \readonly
\qmlobsolete
- Use the PackageObject::names property.
+ Use PackageObject::state.
+*/
+/*!
+ \qmlproperty url ApplicationObject::icon
+ \readonly
- Returns the name of the application in the given \a language.
+ The URL of the application's icon - can be used as the source property of an \l Image.
+ If the application does not specify an \c icon, this will return the same as the containing
+ PackageObject::icon.
+*/
+/*!
+ \qmlproperty string ApplicationObject::name
+ \readonly
+
+ Returns the localized name of the application - as provided in the info.yaml file - in the currently
+ active locale.
+
+ This is a convenience property, that takes the mapping returned by the \l names property,
+ and then tries to return the value for these keys if available: first the current locale's id,
+ then \c en_US, then \c en and lastly the first available key.
+
+ If no mapping is available, this will return the \l id.
+*/
+/*!
+ \qmlproperty var ApplicationObject::names
+ \readonly
+
+ Returns an object with all the language code to localized name mappings as provided in the
+ application's info.yaml file. If the application does not specify a \c names object, this will
+ return the same as the containing PackageObject::names.
+*/
+/*!
+ \qmlproperty string ApplicationObject::description
+ \readonly
+
+ Returns the localized description of the application - as provided in the info.yaml file - in the
+ currently active locale.
+
+ This property uses the same algorithm as the \l name property, but for the description.
+*/
+/*!
+ \qmlproperty var ApplicationObject::descriptions
+ \readonly
+
+ Returns an object with all the language code to localized description mappings as provided in
+ the applications's info.yaml file. If the application does not specify a \c descriptions object,
+ this will return the same as the containing PackageObject::descriptions.
+*/
+/*!
+ \qmlproperty list<string> ApplicationObject::categories
+ \readonly
+
+ A list of category names the application should be associated with. This is mainly for
+ displaying the application within a fixed set of categories in the System UI.
+ If the application does not specify a \c categories list, this will return the same as
+ the containing PackageObject::categories.
*/
QT_BEGIN_NAMESPACE_AM
@@ -370,12 +410,15 @@ QStringList Application::capabilities() const
QStringList Application::categories() const
{
- return package()->categories();
+ return m_info->categories();
}
QUrl Application::icon() const
{
- return package()->icon();
+ if (info()->icon().isEmpty())
+ return QUrl();
+
+ return QUrl::fromLocalFile(packageInfo()->baseDir().absoluteFilePath(info()->icon()));
}
QStringList Application::supportedMimeTypes() const
@@ -390,12 +433,30 @@ QString Application::documentUrl() const
QString Application::name() const
{
- return package()->name();
+ return translateFromMap(m_info->names(), id());
+}
+
+QVariantMap Application::names() const
+{
+ QVariantMap vm;
+ const auto map = m_info->names();
+ for (auto it = map.cbegin(); it != map.cend(); ++it)
+ vm.insert(it.key(), it.value());
+ return vm;
+}
+
+QString Application::description() const
+{
+ return translateFromMap(m_info->descriptions());
}
-QString Application::name(const QString &language) const
+QVariantMap Application::descriptions() const
{
- return package()->names().value(language).toString();
+ QVariantMap vm;
+ const auto map = m_info->descriptions();
+ for (auto it = map.cbegin(); it != map.cend(); ++it)
+ vm.insert(it.key(), it.value());
+ return vm;
}
bool Application::isBlocked() const
diff --git a/src/manager-lib/application.h b/src/manager-lib/application.h
index 6e42cfb8..4e44be53 100644
--- a/src/manager-lib/application.h
+++ b/src/manager-lib/application.h
@@ -62,6 +62,12 @@ class Application : public QObject
Q_CLASSINFO("AM-QmlType", "QtApplicationManager.SystemUI/ApplicationObject 2.0 UNCREATABLE")
Q_PROPERTY(QString id READ id CONSTANT)
+ Q_PROPERTY(QString name READ name NOTIFY bulkChange)
+ Q_PROPERTY(QVariantMap names READ names NOTIFY bulkChange)
+ Q_PROPERTY(QString description READ description NOTIFY bulkChange)
+ Q_PROPERTY(QVariantMap descriptions READ descriptions NOTIFY bulkChange)
+ Q_PROPERTY(QStringList categories READ categories NOTIFY bulkChange)
+ Q_PROPERTY(QUrl icon READ icon NOTIFY bulkChange)
Q_PROPERTY(QString runtimeName READ runtimeName CONSTANT)
Q_PROPERTY(QVariantMap runtimeParameters READ runtimeParameters CONSTANT)
Q_PROPERTY(QStringList capabilities READ capabilities CONSTANT)
@@ -76,11 +82,9 @@ class Application : public QObject
Q_PROPERTY(Package *package READ package CONSTANT)
// legacy, forwarded to Package
- Q_PROPERTY(QUrl icon READ icon NOTIFY bulkChange)
Q_PROPERTY(bool builtIn READ isBuiltIn CONSTANT)
Q_PROPERTY(bool alias READ isAlias CONSTANT)
Q_PROPERTY(Application *nonAliased READ nonAliased CONSTANT)
- Q_PROPERTY(QStringList categories READ categories CONSTANT)
Q_PROPERTY(QString version READ version CONSTANT)
Q_PROPERTY(State state READ state NOTIFY stateChanged)
Q_PROPERTY(bool blocked READ isBlocked NOTIFY blockedChanged)
@@ -111,16 +115,18 @@ public:
// legacy compatibility
bool isAlias() const { return false; }
Application *nonAliased() { return this; }
- QStringList categories() const;
- QUrl icon() const;
QString documentUrl() const;
QStringList supportedMimeTypes() const;
- QString name() const;
- Q_INVOKABLE QString name(const QString &language) const;
bool isBlocked() const;
// Properties that mainly forward content from ApplicationInfo
QString id() const;
+ QUrl icon() const;
+ QStringList categories() const;
+ QString name() const;
+ QVariantMap names() const;
+ QString description() const;
+ QVariantMap descriptions() const;
bool isBuiltIn() const;
QString runtimeName() const;
QVariantMap runtimeParameters() const;
diff --git a/src/manager-lib/installationtask.cpp b/src/manager-lib/installationtask.cpp
index 32a18817..cd4efc5c 100644
--- a/src/manager-lib/installationtask.cpp
+++ b/src/manager-lib/installationtask.cpp
@@ -177,7 +177,7 @@ void InstallationTask::execute()
throw Exception(m_extractor->errorCode(), m_extractor->errorString());
if (!m_foundInfo || !m_foundIcon)
- throw Exception(Error::Package, "package did not contain a valid info.json and icon file");
+ throw Exception(Error::Package, "package did not contain a valid info.yaml and icon file");
QList<QByteArray> chainOfTrust = m_pm->caCertificates();
diff --git a/src/manager-lib/intentaminterface.cpp b/src/manager-lib/intentaminterface.cpp
index 7932d3e5..7a06a968 100644
--- a/src/manager-lib/intentaminterface.cpp
+++ b/src/manager-lib/intentaminterface.cpp
@@ -127,6 +127,7 @@ IntentServer *IntentAMImplementation::createIntentServerAndClientInstance(Packag
intentInfo->visibility() == IntentInfo::Public ? Intent::Public
: Intent::Private,
intentInfo->parameterMatch(), intentInfo->names(),
+ intentInfo->descriptions(),
QUrl::fromLocalFile(package->info()->baseDir().absoluteFilePath(intentInfo->icon())),
intentInfo->categories())) {
throw Exception(Error::Intents, "could not add intent %1 for package %2")
@@ -653,6 +654,11 @@ QVariantMap IntentServerHandler::names() const
return m_intent->names();
}
+QVariantMap IntentServerHandler::descriptions() const
+{
+ return m_intent->descriptions();
+}
+
QStringList IntentServerHandler::categories() const
{
return m_intent->categories();
@@ -688,7 +694,20 @@ void IntentServerHandler::setNames(const QVariantMap &names)
qmlWarning(this) << "Cannot change the names property of an IntentServerHandler after creation.";
return;
}
- m_intent->m_names = names;
+ m_intent->m_names.clear();
+ for (auto it = names.cbegin(); it != names.cend(); ++it)
+ m_intent->m_names.insert(it.key(), it.value().toString());
+}
+
+void IntentServerHandler::setDescriptions(const QVariantMap &descriptions)
+{
+ if (isComponentCompleted()) {
+ qmlWarning(this) << "Cannot change the descriptions property of an IntentServerHandler after creation.";
+ return;
+ }
+ m_intent->m_descriptions.clear();
+ for (auto it = descriptions.cbegin(); it != descriptions.cend(); ++it)
+ m_intent->m_descriptions.insert(it.key(), it.value().toString());
}
void IntentServerHandler::setCategories(const QStringList &categories)
@@ -742,14 +761,17 @@ void IntentServerHandler::componentComplete()
const auto ids = intentIds();
for (const auto &intentId : ids) {
// convert from QVariantMap to QMap<QString, QString>
- QMap<QString, QString> names;
+ QMap<QString, QString> names, descriptions;
const auto qvm_names = m_intent->names();
+ const auto qvm_descriptions = m_intent->descriptions();
for (auto it = qvm_names.cbegin(); it != qvm_names.cend(); ++it)
names.insert(it.key(), it.value().toString());
+ for (auto it = qvm_descriptions.cbegin(); it != qvm_descriptions.cend(); ++it)
+ descriptions.insert(it.key(), it.value().toString());
auto intent = is->addIntent(intentId, sysUiId, sysUiId, m_intent->requiredCapabilities(),
m_intent->visibility(), m_intent->parameterMatch(), names,
- m_intent->icon(), m_intent->categories());
+ descriptions, m_intent->icon(), m_intent->categories());
if (intent)
m_registeredIntents << intent;
else
diff --git a/src/manager-lib/intentaminterface.h b/src/manager-lib/intentaminterface.h
index 99c5599e..d8fb5b0e 100644
--- a/src/manager-lib/intentaminterface.h
+++ b/src/manager-lib/intentaminterface.h
@@ -198,6 +198,7 @@ class IntentServerHandler : public IntentHandler
// handlers
Q_PROPERTY(QUrl icon READ icon WRITE setIcon)
Q_PROPERTY(QVariantMap names READ names WRITE setNames)
+ Q_PROPERTY(QVariantMap descriptions READ descriptions WRITE setDescriptions)
Q_PROPERTY(QStringList categories READ categories WRITE setCategories)
Q_PROPERTY(QT_PREPEND_NAMESPACE_AM(Intent)::Visibility visibility READ visibility WRITE setVisibility)
Q_PROPERTY(QStringList requiredCapabilities READ requiredCapabilities WRITE setRequiredCapabilities)
@@ -209,6 +210,7 @@ public:
QUrl icon() const;
QVariantMap names() const;
+ QVariantMap descriptions() const;
QStringList categories() const;
Intent::Visibility visibility() const;
QStringList requiredCapabilities() const;
@@ -217,6 +219,7 @@ public:
public slots:
void setIcon(const QUrl &icon);
void setNames(const QVariantMap &names);
+ void setDescriptions(const QVariantMap &descriptions);
void setCategories(const QStringList &categories);
void setVisibility(Intent::Visibility visibility);
void setRequiredCapabilities(const QStringList &requiredCapabilities);
diff --git a/src/manager-lib/package.cpp b/src/manager-lib/package.cpp
index 3b68b402..d3ab3fe2 100644
--- a/src/manager-lib/package.cpp
+++ b/src/manager-lib/package.cpp
@@ -35,6 +35,7 @@
#include "packageinfo.h"
#include "applicationinfo.h"
#include "application.h"
+#include "utilities.h"
/*!
\qmltype PackageObject
@@ -97,6 +98,11 @@
Returns the localized name of the package - as provided in the info.yaml file - in the currently
active locale.
+ This is a convenience property, that takes the mapping returned by the \l names property,
+ and then tries to return the value for these keys if available: first the current locale's id,
+ then \c en_US, then \c en and lastly the first available key.
+
+ If no mapping is available, this will return the \l id.
*/
/*!
\qmlproperty var PackageObject::names
@@ -112,6 +118,7 @@
Returns the localized description of the package - as provided in the info.yaml file - in the
currently active locale.
+ This property uses the same algorithm as the \l name property, but for the description.
*/
/*!
\qmlproperty var PackageObject::descriptions
@@ -187,19 +194,7 @@ QString Package::version() const
QString Package::name() const
{
- QString name;
- if (!info()->names().isEmpty()) {
- name = info()->name(QLocale::system().name()); //TODO: language changes
- if (name.isEmpty())
- name = info()->name(qSL("en"));
- if (name.isEmpty())
- name = info()->name(qSL("en_US"));
- if (name.isEmpty())
- name = *info()->names().constBegin();
- } else {
- name = id();
- }
- return name;
+ return translateFromMap(info()->names(), id());
}
QVariantMap Package::names() const
@@ -213,17 +208,7 @@ QVariantMap Package::names() const
QString Package::description() const
{
- QString description;
- if (!info()->descriptions().isEmpty()) {
- description = info()->description(QLocale::system().name()); //TODO: language changes
- if (description.isEmpty())
- description = info()->description(qSL("en"));
- if (description.isEmpty())
- description = info()->description(qSL("en_US"));
- if (description.isEmpty())
- description = *info()->descriptions().constBegin();
- }
- return description;
+ return translateFromMap(info()->descriptions());
}
QVariantMap Package::descriptions() const
diff --git a/tests/auto/applicationinfo/CMakeLists.txt b/tests/auto/applicationinfo/CMakeLists.txt
index 7c9320fe..fed2b365 100644
--- a/tests/auto/applicationinfo/CMakeLists.txt
+++ b/tests/auto/applicationinfo/CMakeLists.txt
@@ -3,13 +3,22 @@ qt_internal_add_test(tst_applicationinfo
SOURCES
../error-checking.h
tst_applicationinfo.cpp
- DEFINES
- AM_TESTDATA_DIR=\\\"${CMAKE_CURRENT_BINARY_DIR}/../../data/\\\"
PUBLIC_LIBRARIES
Qt::Network
Qt::AppManApplicationPrivate
Qt::AppManCommonPrivate
Qt::AppManManagerPrivate
+ Qt::AppManIntentServerPrivate
+)
+
+qt_internal_add_resource(tst_applicationinfo "yaml_testdata"
+ PREFIX
+ "/"
+ FILES
+ "data/legacy/info.yaml"
+ "data/minimal/info.yaml"
+ "data/inherit/info.yaml"
+ "data/full/info.yaml"
)
qt_internal_extend_target(tst_applicationinfo CONDITION TARGET Qt::DBus
diff --git a/tests/auto/applicationinfo/data/full/info.yaml b/tests/auto/applicationinfo/data/full/info.yaml
new file mode 100644
index 00000000..1ff2c7f5
--- /dev/null
+++ b/tests/auto/applicationinfo/data/full/info.yaml
@@ -0,0 +1,118 @@
+formatVersion: 1
+formatType: am-package
+---
+id: 'full'
+icon: 'full.png'
+version: 'v1'
+name:
+ en: 'pkg.name.en'
+ de: 'pkg.name.de'
+description:
+ en: 'pkg.desc.en'
+ de: 'pkg.desc.de'
+categories:
+ - pkg.cat.1
+ - pkg.cat.2
+applications:
+ - id: 'full.app.1'
+ code: 'app1.qml'
+ runtime: 'qml'
+ runtimeParameters:
+ loadDummyDate: true
+ importPaths: [ a, b ]
+ resources: [ c, d ]
+ pluginPaths: [ e, f ]
+ environmentVariables:
+ foo: bar
+ supportsApplicationInterface: yes
+ capabilities:
+ - app1.cap
+ opengl:
+ desktopProfile: core
+ esMajorVersion: 3
+ esMinorVersion: 2
+ applicationProperties:
+ protected:
+ custom.app1.key: 42
+ private:
+ not: visible
+ logging:
+ dlt:
+ id: app1.dlt.id
+ description: "app1.dlt.desc"
+ icon: 'app1.png'
+ name:
+ en: 'app1.name.en'
+ de: 'app1.name.de'
+ description:
+ en: 'app1.desc.en'
+ de: 'app1.desc.de'
+ categories:
+ - app1.cat.1
+ - app1.cat.2
+ - id: 'full.app.2'
+ code: 'app2.exe'
+ runtime: 'native'
+ runtimeParameters:
+ arguments: [ "-3", "-4" ]
+ environmentVariables:
+ bar: foo
+ supportsApplicationInterface: yes
+ capabilities:
+ - app2.cap.1
+ - app2.cap.2
+ opengl:
+ desktopProfile: compatibility
+ esMajorVersion: 2
+ esMinorVersion: 0
+ applicationProperties:
+ protected:
+ custom.app2.key: "custom.app2.value"
+ logging:
+ dlt:
+ id: app2.dlt.id
+ description: "app2.dlt.desc"
+ icon: 'app2.png'
+ name:
+ en: 'app2.name.en'
+ de: 'app2.name.de'
+ description:
+ en: 'app2.desc.en'
+ de: 'app2.desc.de'
+ categories:
+ - app2.cat.1
+ - app2.cat.2
+
+intents:
+- id: full.int.1
+ handlingApplicationId: full.app.1
+ visibility: private
+ requiredCapabilities: [ 'int1.cap.1', 'int1.cap.2' ]
+ parameterMatch:
+ mimeType: "^image/.*\\.png$"
+ icon: 'int1.png'
+ name:
+ en: 'int1.name.en'
+ de: 'int1.name.de'
+ description:
+ en: 'int1.desc.en'
+ de: 'int1.desc.de'
+ categories:
+ - int1.cat.1
+ - int1.cat.2
+- id: full.int.2
+ handlingApplicationId: full.app.2
+ visibility: public
+ requiredCapabilities: [ 'int2.cap.1', 'int2.cap.2' ]
+ parameterMatch:
+ test: "foo"
+ icon: 'int2.png'
+ name:
+ en: 'int2.name.en'
+ de: 'int2.name.de'
+ description:
+ en: 'int2.desc.en'
+ de: 'int2.desc.de'
+ categories:
+ - int2.cat.1
+ - int2.cat.2
diff --git a/tests/auto/applicationinfo/data/inherit/info.yaml b/tests/auto/applicationinfo/data/inherit/info.yaml
new file mode 100644
index 00000000..0c5fe3fd
--- /dev/null
+++ b/tests/auto/applicationinfo/data/inherit/info.yaml
@@ -0,0 +1,28 @@
+formatVersion: 1
+formatType: am-package
+---
+id: 'inherit'
+icon: 'pkg.png'
+name:
+ en: 'pkg.name.en'
+ de: 'pkg.name.de'
+description:
+ en: 'pkg.desc.en'
+ de: 'pkg.desc.de'
+categories:
+ - pkg.cat.1
+ - pkg.cat.2
+
+applications:
+ - id: 'inherit.app.1'
+ code: 'app1.qml'
+ runtime: 'qml'
+ - id: 'inherit.app.2'
+ code: 'app2.exe'
+ runtime: 'native'
+
+intents:
+- id: inherit.int.1
+ handlingApplicationId: inherit.app.1
+- id: inherit.int.2
+ handlingApplicationId: inherit.app.2
diff --git a/tests/data/manifests/com.pelagicore.test/info.yaml b/tests/auto/applicationinfo/data/legacy/info.yaml
index 0c4b3fd0..77272547 100644
--- a/tests/data/manifests/com.pelagicore.test/info.yaml
+++ b/tests/auto/applicationinfo/data/legacy/info.yaml
@@ -1,15 +1,15 @@
formatVersion: 1
formatType: am-application
---
-id: 'com.pelagicore.test'
-icon: 'icon.png'
-code: 'Test.qml'
+id: 'legacy'
+icon: 'icon.png'
+code: 'legacy.qml'
runtime: 'qml'
runtimeParameters:
loadDummyData: true
name:
- en: 'english'
- de: 'deutsch'
+ en: 'legacy.en'
+ de: 'legacy.de'
version: v1
@@ -24,4 +24,3 @@ capabilities:
categories:
- "foo"
- "bar"
-
diff --git a/tests/auto/applicationinfo/data/minimal/info.yaml b/tests/auto/applicationinfo/data/minimal/info.yaml
new file mode 100644
index 00000000..e7f2999b
--- /dev/null
+++ b/tests/auto/applicationinfo/data/minimal/info.yaml
@@ -0,0 +1,8 @@
+formatVersion: 1
+formatType: am-package
+---
+id: 'minimal'
+applications:
+ - id: 'minimal.app'
+ code: 'minimal.qml'
+ runtime: 'qml'
diff --git a/tests/auto/applicationinfo/tst_applicationinfo.cpp b/tests/auto/applicationinfo/tst_applicationinfo.cpp
index 0d8888ad..6dd42255 100644
--- a/tests/auto/applicationinfo/tst_applicationinfo.cpp
+++ b/tests/auto/applicationinfo/tst_applicationinfo.cpp
@@ -34,6 +34,9 @@
#include "global.h"
#include "application.h"
#include "applicationinfo.h"
+#include "intent.h"
+#include "intentinfo.h"
+#include "package.h"
#include "packageinfo.h"
#include "yamlpackagescanner.h"
#include "exception.h"
@@ -44,105 +47,374 @@ class tst_ApplicationInfo : public QObject
{
Q_OBJECT
-public:
- tst_ApplicationInfo();
-
private slots:
- void initTestCase();
- void cleanupTestCase();
- void application_data();
- void application();
+ void full();
+ void minimal();
+ void inherit();
+ void legacy();
void validApplicationId_data();
void validApplicationId();
- void validIcon_data();
- void validIcon();
-
-private:
- QVector<PackageInfo *> m_pkgs;
};
-tst_ApplicationInfo::tst_ApplicationInfo()
-{ }
+QT_BEGIN_NAMESPACE_AM
-
-void tst_ApplicationInfo::initTestCase()
+class TestPackageLoader
{
- if (!QDir(qL1S(AM_TESTDATA_DIR "/packages")).exists())
- QSKIP("No test packages available in the data/ directory");
-
- YamlPackageScanner scanner;
- QDir baseDir(qL1S(AM_TESTDATA_DIR "manifests"));
- const QStringList pkgDirNames = baseDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
- for (const QString &pkgDirName : pkgDirNames) {
- QDir dir = baseDir.absoluteFilePath(pkgDirName);
+public:
+ TestPackageLoader(const char *name)
+ : m_dataDir(qL1S(":/data"))
+ {
try {
- PackageInfo *pi = scanner.scan(dir.absoluteFilePath(qSL("info.yaml")));
- QVERIFY(pi);
- QCOMPARE(pkgDirName, pi->id());
- m_pkgs << pi;
- } catch (const std::exception &e) {
- QFAIL(e.what());
+ static YamlPackageScanner scanner;
+ QString path = QString::fromLatin1(name) % qL1S("/info.yaml");
+
+ m_pi = scanner.scan(m_dataDir.absoluteFilePath(path));
+ if (m_pi) {
+ m_p = new Package(m_pi);
+ const auto ais = m_pi->applications();
+ for (const auto &ai : ais) {
+ auto a = new Application(ai, m_p);
+ m_a << a;
+ m_p->addApplication(a);
+ }
+ const auto iis = m_pi->intents();
+ for (const auto &ii : iis) {
+ m_i << new Intent(ii->id(), m_pi->id(), ii->handlingApplicationId(),
+ ii->requiredCapabilities(),
+ ii->visibility() == IntentInfo::Public ? Intent::Public
+ : Intent::Private,
+ ii->parameterMatch(), ii->names(),
+ ii->descriptions(),
+ QUrl::fromLocalFile(m_pi->baseDir().absoluteFilePath(ii->icon())),
+ ii->categories());
+ }
+ }
+ } catch (const Exception &e) {
+ m_lastLoadFailure = e.errorString();
}
}
- QCOMPARE(m_pkgs.size(), 2);
-}
+ ~TestPackageLoader()
+ {
+ delete m_p;
+ qDeleteAll(m_i);
+ qDeleteAll(m_a);
+ delete m_pi;
+ }
-void tst_ApplicationInfo::cleanupTestCase()
+ PackageInfo *info() const { return m_pi; }
+ Package *package() const { return m_p; }
+ QVector<Intent *> intents() const { return m_i; }
+ QDir dataDir() const { return m_dataDir; }
+ QString lastLoadFailure() const { return m_lastLoadFailure; }
+
+private:
+ QDir m_dataDir;
+ QString m_lastLoadFailure;
+ PackageInfo *m_pi = nullptr;
+ Package *m_p = nullptr;
+ QVector<Application *> m_a;
+ QVector<Intent *> m_i;
+};
+
+QT_END_NAMESPACE_AM
+
+static QUrl qmlIcon(PackageInfo *pi, const QString &iconFile)
{
- qDeleteAll(m_pkgs);
+ return QUrl::fromLocalFile(pi->baseDir().absoluteFilePath(iconFile));
}
-void tst_ApplicationInfo::application_data()
+static QVariantMap qmlStringMap(const QMap<QString, QString> &sm)
{
- QTest::addColumn<QString>("id");
-
- QTest::newRow("normal") << "com.pelagicore.test";
- QTest::newRow("json") << "com.pelagicore.json-legacy";
+ QVariantMap vm;
+ for (auto it = sm.cbegin(); it != sm.cend(); ++it)
+ vm.insert(it.key(), it.value());
+ return vm;
}
-void tst_ApplicationInfo::application()
+
+void tst_ApplicationInfo::full()
{
- QFETCH(QString, id);
+ TestPackageLoader pl("full");
+ QVERIFY2(pl.info(), qPrintable(pl.lastLoadFailure()));
+
+ QCOMPARE(pl.info()->baseDir(), pl.dataDir().absoluteFilePath(pl.info()->id()));
+ QCOMPARE(pl.info()->id(), qL1S("full"));
+ QCOMPARE(pl.info()->icon(), qL1S("full.png"));
+ QCOMPARE(pl.info()->version(), qL1S("v1"));
+ QMap<QString, QString> names { { qL1S("en"), qL1S("pkg.name.en") }, { qL1S("de"), qL1S("pkg.name.de") } };
+ QCOMPARE(pl.info()->names(), names);
+ QMap<QString, QString> descs { { qL1S("en"), qL1S("pkg.desc.en") }, { qL1S("de"), qL1S("pkg.desc.de") } };
+ QCOMPARE(pl.info()->descriptions(), descs);
+ QStringList cats { qL1S("pkg.cat.1"), qL1S("pkg.cat.2") };
+ QCOMPARE(pl.info()->categories(), cats);
+ QCOMPARE(pl.info()->applications().size(), 2);
+ QCOMPARE(pl.info()->intents().size(), 2);
+
+ const ApplicationInfo *ai = pl.info()->applications().constFirst();
+
+ QCOMPARE(ai->id(), qSL("full.app.1"));
+ QCOMPARE(ai->icon(), qSL("app1.png"));
+ QMap<QString, QString> app1names { { qL1S("en"), qL1S("app1.name.en") }, { qL1S("de"), qL1S("app1.name.de") } };
+ QCOMPARE(ai->names(), app1names);
+ QMap<QString, QString> app1descs { { qL1S("en"), qL1S("app1.desc.en") }, { qL1S("de"), qL1S("app1.desc.de") } };
+ QCOMPARE(ai->descriptions(), app1descs);
+ QStringList app1cats { qL1S("app1.cat.1"), qL1S("app1.cat.2") };
+ QCOMPARE(ai->categories(), app1cats);
+ QCOMPARE(QFileInfo(ai->codeFilePath()).fileName(), qSL("app1.qml"));
+ QCOMPARE(ai->runtimeName(), qSL("qml"));
+ QCOMPARE(ai->runtimeParameters().size(), 5);
+ QCOMPARE(ai->supportsApplicationInterface(), true);
+ QCOMPARE(ai->capabilities(), QStringList { qSL("app1.cap") });
+ QVariantMap app1ogl { { qSL("desktopProfile"), qSL("core") }, { qSL("esMajorVersion"), 3 }, { qSL("esMinorVersion"), 2 }};
+ QCOMPARE(ai->openGLConfiguration(), app1ogl);
+ QVariantMap app1prop { { qSL("custom.app1.key"), 42 } };
+ QCOMPARE(ai->applicationProperties(), app1prop);
+ QVariantMap app1dlt { { qSL("id"), qSL("app1.dlt.id") }, { qSL("description"), qSL("app1.dlt.desc") } };
+ QCOMPARE(ai->dltConfiguration(), app1dlt);
+
+ ai = pl.info()->applications().constLast();
+
+ QCOMPARE(ai->id(), qSL("full.app.2"));
+ QCOMPARE(ai->icon(), qSL("app2.png"));
+ QMap<QString, QString> app2names { { qL1S("en"), qL1S("app2.name.en") }, { qL1S("de"), qL1S("app2.name.de") } };
+ QCOMPARE(ai->names(), app2names);
+ QMap<QString, QString> app2descs { { qL1S("en"), qL1S("app2.desc.en") }, { qL1S("de"), qL1S("app2.desc.de") } };
+ QCOMPARE(ai->descriptions(), app2descs);
+ QStringList app2cats { qL1S("app2.cat.1"), qL1S("app2.cat.2") };
+ QCOMPARE(ai->categories(), app2cats);
+ QCOMPARE(QFileInfo(ai->codeFilePath()).fileName(), qSL("app2.exe"));
+ QCOMPARE(ai->runtimeName(), qSL("native"));
+ QCOMPARE(ai->runtimeParameters().size(), 2);
+
+ IntentInfo *ii = pl.info()->intents().constFirst();
+
+ QCOMPARE(ii->id(), qSL("full.int.1"));
+ QCOMPARE(ii->icon(), qSL("int1.png"));
+ QMap<QString, QString> int1names { { qL1S("en"), qL1S("int1.name.en") }, { qL1S("de"), qL1S("int1.name.de") } };
+ QCOMPARE(ii->names(), int1names);
+ QMap<QString, QString> int1descs { { qL1S("en"), qL1S("int1.desc.en") }, { qL1S("de"), qL1S("int1.desc.de") } };
+ QCOMPARE(ii->descriptions(), int1descs);
+ QStringList int1cats { qL1S("int1.cat.1"), qL1S("int1.cat.2") };
+ QCOMPARE(ii->categories(), int1cats);
+ QCOMPARE(ii->handlingApplicationId(), pl.info()->applications().constFirst()->id());
+ QCOMPARE(ii->visibility(), IntentInfo::Private);
+ QStringList req1caps { qSL("int1.cap.1"), qSL("int1.cap.2") };
+ QCOMPARE(ii->requiredCapabilities(), req1caps);
+ QVariantMap param1match { { qSL("mimeType"), qSL("^image/.*\\.png$") } };
+ QCOMPARE(ii->parameterMatch(), param1match);
+
+ ii = pl.info()->intents().constLast();
+
+ QCOMPARE(ii->id(), qSL("full.int.2"));
+ QCOMPARE(ii->icon(), qSL("int2.png"));
+ QMap<QString, QString> int2names { { qL1S("en"), qL1S("int2.name.en") }, { qL1S("de"), qL1S("int2.name.de") } };
+ QCOMPARE(ii->names(), int2names);
+ QMap<QString, QString> int2descs { { qL1S("en"), qL1S("int2.desc.en") }, { qL1S("de"), qL1S("int2.desc.de") } };
+ QCOMPARE(ii->descriptions(), int2descs);
+ QStringList int2cats { qL1S("int2.cat.1"), qL1S("int2.cat.2") };
+ QCOMPARE(ii->categories(), int2cats);
+ QCOMPARE(ii->handlingApplicationId(), pl.info()->applications().constLast()->id());
+ QCOMPARE(ii->visibility(), IntentInfo::Public);
+ QStringList req2caps { qSL("int2.cap.1"), qSL("int2.cap.2") };
+ QCOMPARE(ii->requiredCapabilities(), req2caps);
+ QVariantMap param2match { { qSL("test"), qSL("foo") } };
+ QCOMPARE(ii->parameterMatch(), param2match);
+
+ // now the QML interface
+
+ Package *p = pl.package();
+
+ QVERIFY(p);
+ QCOMPARE(p->id(), pl.info()->id());
+ QCOMPARE(p->icon(), qmlIcon(pl.info(), pl.info()->icon()));
+ QCOMPARE(p->version(), pl.info()->version());
+ QVERIFY(p->names().values().contains(p->name()));
+ QCOMPARE(p->names(), qmlStringMap(pl.info()->names()));
+ QVERIFY(p->descriptions().values().contains(p->description()));
+ QCOMPARE(p->descriptions(), qmlStringMap(pl.info()->descriptions()));
+ QCOMPARE(p->categories(), pl.info()->categories());
+ QCOMPARE(p->applications().size(), pl.info()->applications().size());
+ QCOMPARE(pl.intents().size(), pl.info()->intents().size());
+
+ Application *a = qobject_cast<Application *>(p->applications().last());
+
+ QVERIFY(a);
+ QCOMPARE(a->id(), ai->id());
+ QCOMPARE(a->icon(), qmlIcon(pl.info(), ai->icon()));
+ QVERIFY(a->names().values().contains(a->name()));
+ QCOMPARE(a->names(), qmlStringMap(ai->names()));
+ QVERIFY(a->descriptions().values().contains(a->description()));
+ QCOMPARE(a->descriptions(), qmlStringMap(ai->descriptions()));
+ QCOMPARE(a->categories(), ai->categories());
+ QCOMPARE(a->supportedMimeTypes(), ai->supportedMimeTypes());
+ QCOMPARE(a->capabilities(), ai->capabilities());
+ QCOMPARE(a->runtimeName(), ai->runtimeName());
+ QCOMPARE(a->runtimeParameters(), ai->runtimeParameters());
+
+ Intent *i = pl.intents().last();
+
+ QVERIFY(i);
+ QCOMPARE(i->intentId(), ii->id());
+ QCOMPARE(i->icon(), qmlIcon(pl.info(), ii->icon()));
+ QVERIFY(i->names().values().contains(i->name()));
+ QCOMPARE(i->names(), qmlStringMap(ii->names()));
+ QVERIFY(i->descriptions().values().contains(i->description()));
+ QCOMPARE(i->descriptions(), qmlStringMap(ii->descriptions()));
+ QCOMPARE(i->categories(), ii->categories());
+ QCOMPARE(int(i->visibility()), int(ii->visibility()));
+ QCOMPARE(i->requiredCapabilities(), ii->requiredCapabilities());
+ QCOMPARE(i->parameterMatch(), ii->parameterMatch());
+}
- QString name = QString::fromLatin1(AM_TESTDATA_DIR "manifests/%1/info.yaml").arg(id);
+void tst_ApplicationInfo::minimal()
+{
+ TestPackageLoader pl("minimal");
+ QVERIFY2(pl.info(), qPrintable(pl.lastLoadFailure()));
+
+ QCOMPARE(pl.info()->baseDir(), pl.dataDir().absoluteFilePath(pl.info()->id()));
+ QCOMPARE(pl.info()->id(), qL1S("minimal"));
+ QCOMPARE(pl.info()->icon(), QString { });
+ QCOMPARE(pl.info()->version(), QString { });
+ QMap<QString, QString> emptyMap;
+ QCOMPARE(pl.info()->names(), emptyMap);
+ QCOMPARE(pl.info()->descriptions(), emptyMap);
+ QCOMPARE(pl.info()->categories(), QStringList { });
+ QCOMPARE(pl.info()->applications().size(), 1);
+ QCOMPARE(pl.info()->intents().size(), 0);
+
+ const ApplicationInfo *ai = pl.info()->applications().constFirst();
+
+ QCOMPARE(ai->id(), qSL("minimal.app"));
+ QCOMPARE(ai->icon(), pl.info()->icon());
+ QCOMPARE(ai->names(), pl.info()->names());
+ QCOMPARE(ai->descriptions(), pl.info()->descriptions());
+ QCOMPARE(ai->categories(), pl.info()->categories());
+ QCOMPARE(QFileInfo(ai->codeFilePath()).fileName(), qSL("minimal.qml"));
+ QCOMPARE(ai->runtimeName(), qSL("qml"));
+ QCOMPARE(ai->runtimeParameters().size(), 0);
+}
- YamlPackageScanner scanner;
- PackageInfo *pkg;
- try {
- pkg = scanner.scan(name);
- QVERIFY(pkg);
- } catch (const std::exception &e) {
- QFAIL(e.what());
- }
+void tst_ApplicationInfo::inherit()
+{
+ TestPackageLoader pl("inherit");
+ QVERIFY2(pl.info(), qPrintable(pl.lastLoadFailure()));
+
+ QCOMPARE(pl.info()->baseDir(), pl.dataDir().absoluteFilePath(pl.info()->id()));
+ QCOMPARE(pl.info()->id(), qL1S("inherit"));
+ QCOMPARE(pl.info()->icon(), qL1S("pkg.png"));
+ QCOMPARE(pl.info()->version(), QString { });
+ QMap<QString, QString> names { { qL1S("en"), qL1S("pkg.name.en") }, { qL1S("de"), qL1S("pkg.name.de") } };
+ QCOMPARE(pl.info()->names(), names);
+ QMap<QString, QString> descs { { qL1S("en"), qL1S("pkg.desc.en") }, { qL1S("de"), qL1S("pkg.desc.de") } };
+ QCOMPARE(pl.info()->descriptions(), descs);
+ QStringList cats { qL1S("pkg.cat.1"), qL1S("pkg.cat.2") };
+ QCOMPARE(pl.info()->categories(), cats);
+ QCOMPARE(pl.info()->applications().size(), 2);
+ QCOMPARE(pl.info()->intents().size(), 2);
+
+ const ApplicationInfo *ai = pl.info()->applications().constFirst();
+
+ QCOMPARE(ai->id(), qSL("inherit.app.1"));
+ QCOMPARE(ai->icon(), pl.info()->icon());
+ QCOMPARE(ai->names(), pl.info()->names());
+ QCOMPARE(ai->descriptions(), pl.info()->descriptions());
+ QCOMPARE(ai->categories(), pl.info()->categories());
+ QCOMPARE(QFileInfo(ai->codeFilePath()).fileName(), qSL("app1.qml"));
+ QCOMPARE(ai->runtimeName(), qSL("qml"));
+ QCOMPARE(ai->runtimeParameters().size(), 0);
+
+ ai = pl.info()->applications().constLast();
+
+ QCOMPARE(ai->id(), qSL("inherit.app.2"));
+ QCOMPARE(ai->icon(), pl.info()->icon());
+ QCOMPARE(ai->names(), pl.info()->names());
+ QCOMPARE(ai->descriptions(), pl.info()->descriptions());
+ QCOMPARE(ai->categories(), pl.info()->categories());
+ QCOMPARE(QFileInfo(ai->codeFilePath()).fileName(), qSL("app2.exe"));
+ QCOMPARE(ai->runtimeName(), qSL("native"));
+ QCOMPARE(ai->runtimeParameters().size(), 0);
+
+ IntentInfo *ii = pl.info()->intents().constFirst();
+
+ QCOMPARE(ii->id(), qSL("inherit.int.1"));
+ QCOMPARE(ii->icon(), pl.info()->icon());
+ QCOMPARE(ii->names(), pl.info()->names());
+ QCOMPARE(ii->descriptions(), pl.info()->descriptions());
+ QCOMPARE(ii->categories(), pl.info()->categories());
+ QCOMPARE(ii->handlingApplicationId(), pl.info()->applications().constFirst()->id());
+
+ ii = pl.info()->intents().constLast();
+
+ QCOMPARE(ii->id(), qSL("inherit.int.2"));
+ QCOMPARE(ii->icon(), pl.info()->icon());
+ QCOMPARE(ii->names(), pl.info()->names());
+ QCOMPARE(ii->descriptions(), pl.info()->descriptions());
+ QCOMPARE(ii->categories(), pl.info()->categories());
+ QCOMPARE(ii->handlingApplicationId(), pl.info()->applications().constLast()->id());
+
+ // now the QML interface
+
+ Package *p = pl.package();
+
+ QVERIFY(p);
+ QVERIFY(!p->name().isEmpty() && (p->name() != p->id()));
+ QCOMPARE(p->names(), qmlStringMap(pl.info()->names()));
+ QVERIFY(!p->description().isEmpty());
+ QCOMPARE(p->descriptions(), qmlStringMap(pl.info()->descriptions()));
+ QCOMPARE(p->categories(), pl.info()->categories());
+
+ Application *a = qobject_cast<Application *>(p->applications().first());
+
+ QVERIFY(a);
+ QCOMPARE(a->icon(), p->icon());
+ QCOMPARE(a->name(), p->name());
+ QCOMPARE(a->description(), p->description());
+ QCOMPARE(a->names(), p->names());
+ QCOMPARE(a->descriptions(), p->descriptions());
+
+ Intent *i = pl.intents().first();
+
+ QVERIFY(i);
+ QCOMPARE(i->icon(), p->icon());
+ QCOMPARE(i->name(), p->name());
+ QCOMPARE(i->description(), p->description());
+ QCOMPARE(i->names(), p->names());
+ QCOMPARE(i->descriptions(), p->descriptions());
+}
- QCOMPARE(pkg->id(), id);
- QCOMPARE(QFileInfo(pkg->icon()).fileName(), qSL("icon.png"));
- QCOMPARE(pkg->names().size(), 2);
- QCOMPARE(pkg->names().value(qSL("en")), qSL("english"));
- QCOMPARE(pkg->names().value(qSL("de")), qSL("deutsch"));
- QCOMPARE(pkg->name(qSL("en")), qSL("english"));
- QCOMPARE(pkg->isBuiltIn(), false);
- QCOMPARE(pkg->categories().size(), 2);
- QVERIFY(pkg->categories().startsWith(qSL("bar")));
- QVERIFY(pkg->categories().endsWith(qSL("foo")));
-
- ApplicationInfo *app = pkg->applications().size() == 1 ? pkg->applications().constFirst() : nullptr;
- QVERIFY(app);
- QCOMPARE(QFileInfo(app->codeFilePath()).fileName(), qSL("Test.qml"));
- QCOMPARE(app->runtimeName(), qSL("qml"));
- QCOMPARE(app->runtimeParameters().size(), 1);
- QCOMPARE(app->runtimeParameters().value(qSL("loadDummyData")).toBool(), true);
- QCOMPARE(app->capabilities().size(), 2);
- QVERIFY(app->capabilities().startsWith(qSL("cameraAccess")));
- QVERIFY(app->capabilities().endsWith(qSL("locationAccess")));
-
- // legacy
- QCOMPARE(app->supportedMimeTypes().size(), 2);
- QVERIFY(app->supportedMimeTypes().startsWith(qSL("text/plain")));
- QVERIFY(app->supportedMimeTypes().endsWith(qSL("x-scheme-handler/mailto")));
-
- delete pkg;
+void tst_ApplicationInfo::legacy()
+{
+ TestPackageLoader pl("legacy");
+ QVERIFY2(pl.info(), qPrintable(pl.lastLoadFailure()));
+
+ QCOMPARE(pl.info()->baseDir(), pl.dataDir().absoluteFilePath(pl.info()->id()));
+ QCOMPARE(pl.info()->id(), qL1S("legacy"));
+ QCOMPARE(pl.info()->icon(), qL1S("icon.png"));
+ QCOMPARE(pl.info()->version(), qL1S("v1"));
+ QMap<QString, QString> names { { qL1S("en"), qL1S("legacy.en") }, { qL1S("de"), qL1S("legacy.de") } };
+ QCOMPARE(pl.info()->names(), names);
+ QStringList cats { qL1S("bar"), qL1S("foo") };
+ QVERIFY(pl.info()->descriptions().isEmpty());
+ QCOMPARE(pl.info()->categories(), cats);
+ QCOMPARE(pl.info()->applications().size(), 1);
+ QCOMPARE(pl.info()->intents().size(), 0);
+
+ const ApplicationInfo *ai = pl.info()->applications().constFirst();
+
+ QCOMPARE(ai->id(), pl.info()->id());
+ QCOMPARE(ai->icon(), pl.info()->icon());
+ QCOMPARE(ai->names(), pl.info()->names());
+ QVERIFY(ai->descriptions().isEmpty());
+ QCOMPARE(ai->categories(), pl.info()->categories());
+ QStringList mimes { qL1S("text/plain"), qL1S("x-scheme-handler/mailto") };
+ QCOMPARE(ai->supportedMimeTypes(), mimes);
+ QStringList caps { qL1S("cameraAccess"), qL1S("locationAccess") };
+ QCOMPARE(ai->capabilities(), caps);
+ QCOMPARE(QFileInfo(ai->codeFilePath()).fileName(), qSL("legacy.qml"));
+ QCOMPARE(ai->runtimeName(), qSL("qml"));
+ QCOMPARE(ai->runtimeParameters().size(), 1);
+ QCOMPARE(ai->runtimeParameters().value(qSL("loadDummyData")).toBool(), true);
}
void tst_ApplicationInfo::validApplicationId_data()
@@ -184,36 +456,6 @@ void tst_ApplicationInfo::validApplicationId()
QVERIFY2(valid == result, qPrintable(errorString));
}
-void tst_ApplicationInfo::validIcon_data()
-{
- QTest::addColumn<QString>("icon");
- QTest::addColumn<bool>("isValid");
-
- // valid
- QTest::newRow("'icon.png' is valid") << "icon.png" << true;
- QTest::newRow("'foo.bar' is valid") << "foo.bar" << true;
- QTest::newRow("'foo' is valid") << "foo" << true;
-
- // invalid
- QTest::newRow("empty is invalid") << "" << false;
- QTest::newRow("'foo/icon.png' is invalid") << "foo/icon.png" << false;
- QTest::newRow("'../icon.png' is invalid") << "../icon.png" << false;
- QTest::newRow("'icon.png/' is invalid") << "icon.png/" << false;
- QTest::newRow("'/foo' is invalid") << "/foo" << false;
-}
-
-void tst_ApplicationInfo::validIcon()
-{
- QFETCH(QString, icon);
- QFETCH(bool, isValid);
-
- QString errorString;
- bool result = PackageInfo::isValidIcon(icon, &errorString);
-
- QCOMPARE(result, isValid);
-}
-
QTEST_APPLESS_MAIN(tst_ApplicationInfo)
#include "tst_applicationinfo.moc"
-
diff --git a/tests/auto/main/tst_main.cpp b/tests/auto/main/tst_main.cpp
index df52b32d..73f6b24d 100644
--- a/tests/auto/main/tst_main.cpp
+++ b/tests/auto/main/tst_main.cpp
@@ -216,10 +216,10 @@ void tst_Main::installAndRemoveUpdateForBuiltIn()
QCOMPARE(intents->count(), 2);
auto app1 = appMan->application(0);
- QCOMPARE(app1->name(qSL("en")), qSL("Hello Red"));
+ QCOMPARE(app1->names().value(qSL("en")), qSL("Hello Red"));
QCOMPARE(app1->id(), qSL("red1"));
auto app2 = appMan->application(1);
- QCOMPARE(app2->name(qSL("en")), qSL("Hello Red"));
+ QCOMPARE(app2->names().value(qSL("en")), qSL("Hello Red"));
QCOMPARE(app2->id(), qSL("red2"));
auto intent1 = intents->applicationIntent(qSL("red.intent1"), qSL("red1"));
@@ -248,7 +248,7 @@ void tst_Main::installAndRemoveUpdateForBuiltIn()
app1 = appMan->application(0);
// but with different contents
- QCOMPARE(app1->name(qSL("en")), qSL("Hello Updated Red"));
+ QCOMPARE(app1->names().value(qSL("en")), qSL("Hello Updated Red"));
intent1 = intents->applicationIntent(qSL("red.intent1"), qSL("red1"));
QVERIFY(!intent1);
@@ -260,7 +260,7 @@ void tst_Main::installAndRemoveUpdateForBuiltIn()
QCOMPARE(intents->count(), 2);
app1 = appMan->application(0);
- QCOMPARE(app1->name(qSL("en")), qSL("Hello Red"));
+ QCOMPARE(app1->names().value(qSL("en")), qSL("Hello Red"));
intent1 = intents->applicationIntent(qSL("red.intent1"), qSL("red1"));
QVERIFY(intent1);
QCOMPARE(intent1->intentId(), qSL("red.intent1"));
@@ -288,7 +288,7 @@ void tst_Main::updateForBuiltInAlreadyInstalled()
QCOMPARE(appMan->count(), 1);
auto app = appMan->application(0);
- QCOMPARE(app->name(qSL("en")), qSL("Hello Updated Red"));
+ QCOMPARE(app->names().value(qSL("en")), qSL("Hello Updated Red"));
}
/*
@@ -309,7 +309,7 @@ void tst_Main::loadDatabaseWithUpdatedBuiltInApp()
QCOMPARE(appMan->count(), 1);
auto app = appMan->application(0);
- QCOMPARE(app->name(qSL("en")), qSL("Hello Updated Red"));
+ QCOMPARE(app->names().value(qSL("en")), qSL("Hello Updated Red"));
}
void tst_Main::mainQmlFile_data()
diff --git a/tests/auto/packager-tool/tst_packager-tool.cpp b/tests/auto/packager-tool/tst_packager-tool.cpp
index 8dd5ae1a..1071c178 100644
--- a/tests/auto/packager-tool/tst_packager-tool.cpp
+++ b/tests/auto/packager-tool/tst_packager-tool.cpp
@@ -280,7 +280,6 @@ void tst_PackagerTool::brokenMetadata_data()
QTest::addColumn<QVariant>("yamlValue");
QTest::addColumn<QString>("errorString");
- QTest::newRow("missing-name") << "name" << QVariant() << "~.*Required fields are missing: name.*";
QTest::newRow("missing-runtime") << "runtime" << QVariant() << "~.*Required fields are missing: runtime";
QTest::newRow("missing-identifier") << "id" << QVariant() << "~.*Required fields are missing: id";
QTest::newRow("missing-code") << "code" << QVariant() << "~.*Required fields are missing: code";
diff --git a/tests/data/manifests/com.pelagicore.json-legacy/info.yaml b/tests/data/manifests/com.pelagicore.json-legacy/info.yaml
deleted file mode 100644
index 75002d1f..00000000
--- a/tests/data/manifests/com.pelagicore.json-legacy/info.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-formatVersion: 1
-formatType: am-application
----
-{
- "id": "com.pelagicore.json-legacy",
- "icon": "icon.png",
- "code": "Test.qml",
- "runtime": "qml",
- "runtimeParameters": {
- "loadDummyData": true
- },
- "name": { "en": "english", "de": "deutsch" },
-
- "mimeTypes": [ "x-scheme-handler/mailto", "text/plain" ],
-
- "capabilities": [ "cameraAccess", "locationAccess" ],
-
- "categories": [ "foo", "bar" ]
-}