diff options
Diffstat (limited to 'wayland/democompositor/apps')
-rw-r--r-- | wayland/democompositor/apps/README | 22 | ||||
-rw-r--r-- | wayland/democompositor/apps/appentry.cpp | 57 | ||||
-rw-r--r-- | wayland/democompositor/apps/appentry.h | 83 | ||||
-rw-r--r-- | wayland/democompositor/apps/applistmodel.cpp | 221 | ||||
-rw-r--r-- | wayland/democompositor/apps/applistmodel.h | 98 | ||||
-rw-r--r-- | wayland/democompositor/apps/applog.h | 55 | ||||
-rw-r--r-- | wayland/democompositor/apps/appparser.cpp | 170 | ||||
-rw-r--r-- | wayland/democompositor/apps/appparser.h | 62 | ||||
-rw-r--r-- | wayland/democompositor/apps/apps.pri | 11 |
9 files changed, 779 insertions, 0 deletions
diff --git a/wayland/democompositor/apps/README b/wayland/democompositor/apps/README new file mode 100644 index 0000000..2f6fd77 --- /dev/null +++ b/wayland/democompositor/apps/README @@ -0,0 +1,22 @@ +A directory holding a list of applications. There is one JSON file +per launchable application. The content is inspired by the "Desktop +Entry Specification" of freedesktop.org. + +Application files need to be installed into any of the paths that +will be listed for QStandardPaths::DataLocation/apps. In the +case of the democompositor this can be +/usr/share/democompositor/apps. + +The content of the files must follow: + +Name Description Required JSON type +Type Type of entry. Currently only Yes String + Application is supported. +Version The version of the specification + addressed. Currently version 1 Yes Number +Icon The icon to use for display Yes String +Name A user displayable name Yes String +Id Reverse-DNS as unique application Id Yes String +Exec Application to execute to launch Yes String +Path The directory to search for the app No String +X-* Extensions to the specification No Any diff --git a/wayland/democompositor/apps/appentry.cpp b/wayland/democompositor/apps/appentry.cpp new file mode 100644 index 0000000..ce94cad --- /dev/null +++ b/wayland/democompositor/apps/appentry.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "appentry.h" + +AppEntry AppEntry::empty() +{ + QString empty; + return AppEntry{empty, empty, empty, empty, empty, empty, QVariantMap()}; +} diff --git a/wayland/democompositor/apps/appentry.h b/wayland/democompositor/apps/appentry.h new file mode 100644 index 0000000..bddc552 --- /dev/null +++ b/wayland/democompositor/apps/appentry.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +#include <QtCore/QObject> +#include <QtCore/QString> +#include <QtCore/QVariantMap> + +/** + * A const representatation of an application entry. Members include + * executable name, path, icon and other information in the future. + */ +class AppEntry { + Q_GADGET + Q_PROPERTY(QString iconName MEMBER iconName CONSTANT) + Q_PROPERTY(QString appName MEMBER appName CONSTANT) + Q_PROPERTY(QString appId MEMBER appId CONSTANT) + Q_PROPERTY(QString executableName MEMBER executableName CONSTANT) + Q_PROPERTY(QString executablePath MEMBER executablePath CONSTANT) + Q_PROPERTY(QString sourceFileName MEMBER sourceFileName CONSTANT) + Q_PROPERTY(QVariantMap extensions MEMBER extensions CONSTANT) +public: + + QString iconName; + QString appName; + QString appId; + QString executableName; + QString executablePath; + QString sourceFileName; + QVariantMap extensions; + + static AppEntry empty(); +}; + +Q_DECLARE_METATYPE(AppEntry) diff --git a/wayland/democompositor/apps/applistmodel.cpp b/wayland/democompositor/apps/applistmodel.cpp new file mode 100644 index 0000000..dfcc378 --- /dev/null +++ b/wayland/democompositor/apps/applistmodel.cpp @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "applistmodel.h" +#include "appparser.h" +#include "applog.h" + +#include <QtCore/QDirIterator> +#include <QtCore/QFileSystemWatcher> + +static QHash<int, QByteArray> modelRoles() +{ + QHash<int, QByteArray> roles; + roles[AppListModel::App] = "appEntry"; + roles[AppListModel::IconName] = "iconName"; + roles[AppListModel::ApplicationName] = "applicationName"; + roles[AppListModel::ApplicationId] = "applicationId"; + roles[AppListModel::ExeuctableName] = "executableName"; + roles[AppListModel::ExecutablePath] = "executablePath"; + roles[AppListModel::SourceFileName] = "sourceFileName"; + return roles; +} + +QHash<int, QByteArray> AppListModel::m_roles = modelRoles(); + +int AppListModel::rowCount(const QModelIndex& index) const +{ + if (index.isValid()) + return 0; + return m_rows.count(); +} + +QVariant AppListModel::data(const QModelIndex& index, int role) const +{ + if (!index.isValid() || index.parent().isValid()) + return QVariant(); + + auto entry = m_rows[index.row()]; + + switch (role) { + case App: + return QVariant::fromValue(entry); + case IconName: + return entry.iconName; + case ApplicationName: + return entry.appName; + case ApplicationId: + return entry.appId; + case ExeuctableName: + return entry.executableName; + case ExecutablePath: + return entry.executablePath; + case SourceFileName: + return entry.sourceFileName; + default: + qCWarning(apps) << "Unhandled role" << role; + return QVariant(); + } +} + +QHash<int, QByteArray> AppListModel::roleNames() const +{ + return m_roles; +} + +/*! + * Returns true if the directory can be watched + * + * Parse all JSON application files from the given directory + * and monitor it for changes. + */ +bool AppListModel::addAndWatchDir(const QString& dirName) +{ + auto watcher = new QFileSystemWatcher(this); + connect(watcher, &QFileSystemWatcher::directoryChanged, this, &AppListModel::addDir); + auto res = watcher->addPath(dirName); + addDir(dirName); + + qCDebug(apps) << "addAndWatchDir" << dirName << "result: " << res; + return res; +} + +void AppListModel::addFile(const QString& fileName) +{ + beginResetModel(); + doAddFile(fileName); + endResetModel(); +} + +void AppListModel::addDir(const QString& dirName) +{ + QDirIterator dirIt(dirName, QDir::Files | QDir::NoDotAndDotDot | QDir::Readable); + + // We want to deal with the corner case of some files being + // removed. One option would have been to keep a marker bit + // inside the AppEntry but that might leak too much of the + // implementation to the outside. Let's keep a list of file + // names that came from the directory and remove items from + // the list as we re-parse them. Once we are done emit the + // signals. + QVector<QString> deletionCandidates = entriesWithPrefix(dirName); + + beginResetModel(); + while (dirIt.hasNext()) { + auto fileName = dirIt.next(); + if (!doAddFile(fileName)) + continue; + deletionCandidates.removeAll(fileName); + } + QVector<AppEntry> removedApps = removeEntries(deletionCandidates); + endResetModel(); + + // Announce the apps we removed after the model has been updated + for (const auto& app : removedApps) { + qCDebug(apps) << "Going to remove entry for " << app.sourceFileName; + emit appRemoved(app); + } +} + +bool AppListModel::doAddFile(const QString& fileName) +{ + bool ok; + auto newEntry = AppParser::parseFile(fileName, &ok); + if (!ok) + return false; + + for (int i = 0; i < m_rows.count(); ++i) { + if (m_rows[i].sourceFileName == fileName) { + m_rows[i] = newEntry; + return true; + } + } + + m_rows.push_back(newEntry); + return true; +} + +QVector<QString> AppListModel::entriesWithPrefix(const QString& prefix) const +{ + QVector<QString> entries; + + for (const AppEntry& entry : m_rows) + if (entry.sourceFileName.startsWith(prefix)) + entries.push_back(entry.sourceFileName); + return entries; +} + +QVector<AppEntry> AppListModel::removeEntries(const QVector<QString>& fileNames) +{ + QVector<AppEntry> removedEntries(fileNames.size()); + + // Rare but quadratic. The actual removal. + for (const auto &toRemoveFile: fileNames) { + for (int i = 0; i < m_rows.size(); ++i) { + if (m_rows[i].sourceFileName != toRemoveFile) + continue; + removedEntries.append(m_rows[i]); + m_rows.removeAt(i); + break; + } + } + + return removedEntries; +} + +QVariant AppListModel::findApplicationId(const QString& appId) const +{ + for (const auto& entry : m_rows) { + if (entry.appId == appId) + return QVariant::fromValue(entry); + } + + return QVariant(); +} diff --git a/wayland/democompositor/apps/applistmodel.h b/wayland/democompositor/apps/applistmodel.h new file mode 100644 index 0000000..f2e61cc --- /dev/null +++ b/wayland/democompositor/apps/applistmodel.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +#include "appentry.h" + +#include <QtCore/QAbstractListModel> +#include <QtCore/QVector> + +/** + * A model that holds all available applications and + * exports them to a QML scene + */ +class AppListModel : public QAbstractListModel { + Q_OBJECT +public: + + enum Roles { + App = Qt::UserRole, + IconName, + ApplicationName, + ApplicationId, + ExeuctableName, + ExecutablePath, + SourceFileName, + }; + + int rowCount(const QModelIndex& parent) const Q_DECL_OVERRIDE; + QVariant data(const QModelIndex& index, int role) const Q_DECL_OVERRIDE; + QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE; + + Q_INVOKABLE QVariant findApplicationId(const QString& appId) const; + +Q_SIGNALS: + void appRemoved(const AppEntry& appEntry); + +public Q_SLOTS: + bool addAndWatchDir(const QString& dirName); + + void addFile(const QString& fileName); + void addDir(const QString& dirName); + +private: + QVector<QString> entriesWithPrefix(const QString& prefix) const; + QVector<AppEntry> removeEntries(const QVector<QString>& sourceFileNames); + bool doAddFile(const QString& fileName); + + QVector<AppEntry> m_rows; + static QHash<int, QByteArray> m_roles; +}; diff --git a/wayland/democompositor/apps/applog.h b/wayland/democompositor/apps/applog.h new file mode 100644 index 0000000..b116530 --- /dev/null +++ b/wayland/democompositor/apps/applog.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +#include <QtCore/QLoggingCategory> + +Q_DECLARE_LOGGING_CATEGORY(apps) diff --git a/wayland/democompositor/apps/appparser.cpp b/wayland/democompositor/apps/appparser.cpp new file mode 100644 index 0000000..528cb8f --- /dev/null +++ b/wayland/democompositor/apps/appparser.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "appparser.h" +#include "applog.h" + +#include <QtCore/QFile> +#include <QtCore/QJsonDocument> +#include <QtCore/QJsonObject> + +Q_LOGGING_CATEGORY(apps, "launcher.apps") + + +static QString doReadString(const QJsonValue& value, bool *ok) +{ + if (value.type() != QJsonValue::String) { + *ok = false; + return QString(); + } + return value.toString(); +} + +static int doReadInt(const QJsonValue& value, bool *ok) +{ + if (value.type() != QJsonValue::Double) { + *ok = false; + return 0; + } + return value.toInt(); +} + +static QString readString(const QJsonObject& object, const QString& key, bool *ok) +{ + return doReadString(object.value(key), ok); +} + +static QString readStringOptional(const QJsonObject& object, const QString& key, bool *ok) +{ + auto item = object.value(key); + if (item.type() == QJsonValue::Undefined) + return QString(); + return doReadString(item, ok); +} + +static int readInt(const QJsonObject& object, const QString& key, bool *ok) +{ + return doReadInt(object.value(key), ok); +} + +static QVariantMap readExtensions(const QJsonObject& object, const QString& prefixKey) +{ + QVariantMap map; + + for (auto it = object.constBegin(); it != object.constEnd(); ++it) { + if (!it.key().startsWith(prefixKey)) + continue; + map[it.key()] = it.value().toVariant(); + } + return map; +} + +AppEntry AppParser::parseData(const QByteArray& content, const QString& fileName, bool *ok) +{ + *ok = true; + QJsonParseError error; + + QJsonDocument doc = QJsonDocument::fromJson(content, &error); + if (error.error != QJsonParseError::NoError) { + qCWarning(apps) << "Failed to parse json: " << error.errorString(); + *ok = false; + return AppEntry::empty(); + } + + if (!doc.isObject()) { + qCWarning(apps) << "Parsed document is not an object"; + *ok = false; + return AppEntry::empty(); + } + + auto root = doc.object(); + + QString type = readString(root, QStringLiteral("Type"), ok); + if (type != QStringLiteral("Application")) { + qCWarning(apps) << "Unknown type" << type; + *ok = false; + } + + int version = readInt(root, QStringLiteral("Version"), ok); + if (version != 1) { + qCWarning(apps) << "Version number should be 1... Consider to fix that" << version; + } + + QString iconName = readString(root, QStringLiteral("Icon"), ok); + QString appName = readString(root, QStringLiteral("Name"), ok); + QString appId = readString(root, QStringLiteral("Id"), ok); + QString executableName = readString(root, QStringLiteral("Exec"), ok); + QString executablePath = readStringOptional(root, QStringLiteral("Path"), ok); + QVariantMap extensions = readExtensions(root, QStringLiteral("X-")); + if (!*ok) + return AppEntry::empty(); + + return AppEntry{iconName, appName, appId, executableName, executablePath, fileName, extensions}; +} + +AppEntry AppParser::parseFile(const QString& fileName, bool *ok) +{ + qCDebug(apps) << "Trying to parse" << fileName; + + QFile file(fileName); + if (!file.open(QFile::ReadOnly)) { + qCWarning(apps) << "Failed to open" << fileName; + *ok = false; + return AppEntry::empty(); + } + + auto entry = parseData(file.readAll(), fileName, ok); + file.close(); + if (!*ok) { + qCWarning(apps) << "Failed to parse" << fileName; + return AppEntry::empty(); + } + return entry; +} diff --git a/wayland/democompositor/apps/appparser.h b/wayland/democompositor/apps/appparser.h new file mode 100644 index 0000000..a6711b4 --- /dev/null +++ b/wayland/democompositor/apps/appparser.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +#include "appentry.h" + +/** + * Parse a single application entry to an AppEntry. + */ +class AppParser { +public: + static AppEntry parseData(const QByteArray& content, const QString& fileName, bool *ok); + static AppEntry parseFile(const QString& fileName, bool *ok); +}; diff --git a/wayland/democompositor/apps/apps.pri b/wayland/democompositor/apps/apps.pri new file mode 100644 index 0000000..9b19060 --- /dev/null +++ b/wayland/democompositor/apps/apps.pri @@ -0,0 +1,11 @@ + +HEADERS += \ + apps/appentry.h \ + apps/applog.h \ + apps/applistmodel.h \ + apps/appparser.h + +SOURCES += \ + apps/appentry.cpp \ + apps/applistmodel.cpp \ + apps/appparser.cpp |