aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/reference/modules/freedesktop-module.qdoc141
-rw-r--r--share/qbs/modules/freedesktop/FreeDesktop.qbs124
-rw-r--r--share/qbs/modules/freedesktop/freedesktop.js69
-rw-r--r--tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs25
-rw-r--r--tests/auto/blackbox/testdata/freedesktop/main.cpp4
-rw-r--r--tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml15
-rw-r--r--tests/auto/blackbox/testdata/freedesktop/myapp.desktop4
-rw-r--r--tests/auto/blackbox/testdata/freedesktop/myapp.png0
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp33
-rw-r--r--tests/auto/blackbox/tst_blackbox.h1
10 files changed, 416 insertions, 0 deletions
diff --git a/doc/reference/modules/freedesktop-module.qdoc b/doc/reference/modules/freedesktop-module.qdoc
new file mode 100644
index 000000000..48c95a0e0
--- /dev/null
+++ b/doc/reference/modules/freedesktop-module.qdoc
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Alberto Mardegan
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $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$
+**
+****************************************************************************/
+
+/*!
+ \contentspage index.html
+ \qmltype freedesktop
+ \inqmlmodule QbsModules
+ \since Qbs 1.16
+
+ \brief Provides support for some freedesktop.org specifications.
+
+ The \c freedesktop module contains properties and rules for building and working with
+ applications compliant to freedesktop.org specifications on UNIX platforms.
+ The areas in which this module can be of use include:
+
+ \list
+ \li Creation or post-processing of
+ \l{https://specifications.freedesktop.org/desktop-entry-spec/latest/}{\c{.desktop}
+ files}
+ \li Installation of \l{https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html}{AppStream} metadata
+ \li Defining the location for
+ \l{https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#directory_layout}
+ {application icons}
+ \endlist
+
+ This module is available on all platforms but is currently only useful on UNIX platforms.
+
+ \section2 Example usage
+ \target example-freedesktop
+
+ \code
+ Application {
+ ...
+ Depends { name: "freedesktop" }
+
+ Group {
+ files: [
+ ...
+
+ // Declare the desktop and appstream files
+ "data/my-app.desktop",
+ "data/my-app.metainfo.xml",
+ ]
+ }
+
+ // Add/change some fields in the desktop file
+ freedesktop.desktopKeys: ({
+ 'Exec': FileInfo.joinPaths(qbs.installPrefix,
+ product.installDir,
+ product.targetName) + ' --argument',
+ 'X-Application-Version': product.version,
+ })
+
+ // Declare the application icon
+ Group {
+ files: "icons/my-application.svg"
+ fileTags: "freedesktop.appIcon"
+ }
+ }
+ \endcode
+
+ \section2 Relevant File Tags
+ \target filetags-freedesktop
+
+ \table
+ \header
+ \li Tag
+ \li Auto-tagged File Names
+ \li Since
+ \li Description
+ \row
+ \li \c{"freedesktop.desktopfile_source"}
+ \li \c{*.desktop}
+ \li 1.16
+ \li A source file with this tag is a \c{.desktop} file or fragment that
+ will be merged into the application's final \c{.desktop} file.
+ \row
+ \li \c{"freedesktop.desktopfile"}
+ \li -
+ \li 1.16
+ \li Attached to the output artifacts of the rule that produces the
+ merged \c{.desktop} file.
+ \row
+ \li \c{"freedesktop.appstream"}
+ \li \c{*.metainfo.xml}, \c{*.appdata.xml}
+ \li 1.16
+ \li Source files with this tag are AppStream metadata files which will
+ be installed under \l{qbs::}{installPrefix}\c{/share/metainfo}
+ \row
+ \li \c{"freedesktop.appIcon"}
+ \li -
+ \li 1.16
+ \li Source files with this tag are application icons and will be
+ installed under \l{qbs::}{installPrefix}\c{/share/icons/hicolor/scalable/apps}
+ \endtable
+*/
+
+/*!
+ \qmlproperty string freedesktop::name
+
+ The display name of the application which will be stored in the \c{.desktop} file.
+
+ \defaultvalue \l{Product::name}{product.name}
+*/
+
+/*!
+ \qmlproperty var freedesktop::desktopKeys
+
+ A dictionary of key-value pairs to add to the application's \c{.desktop}
+ file.
+
+ The contents of this property will be aggregated with the values from any
+ \c{.desktop} file. If this property and any \c{.desktop} files contain the
+ same key, this property will take precedence.
+
+ \nodefaultvalue
+*/
diff --git a/share/qbs/modules/freedesktop/FreeDesktop.qbs b/share/qbs/modules/freedesktop/FreeDesktop.qbs
new file mode 100644
index 000000000..bb2ba79f4
--- /dev/null
+++ b/share/qbs/modules/freedesktop/FreeDesktop.qbs
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Alberto Mardegan <mardy@users.sourceforge.net>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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 http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+import qbs
+import qbs.ModUtils
+import qbs.TextFile
+import "freedesktop.js" as Fdo
+
+Module {
+ id: fdoModule
+
+ property string name: product.name
+
+ property var desktopKeys
+
+ readonly property var defaultDesktopKeys: {
+ return {
+ 'Type': 'Application',
+ 'Name': product.freedesktop.name,
+ 'Exec': product.targetName,
+ 'Terminal': 'false',
+ 'Version': '1.1',
+ }
+ }
+ property bool _fdoSupported: qbs.targetOS.contains("unix") && !qbs.targetOS.contains("darwin")
+
+ additionalProductTypes: "freedesktop.desktopfile"
+
+ FileTagger {
+ patterns: [ "*.desktop" ]
+ fileTags: [ "freedesktop.desktopfile_source" ]
+ }
+
+ Rule {
+ condition: _fdoSupported
+
+ inputs: [ "freedesktop.desktopfile_source" ]
+ outputFileTags: [ "freedesktop.desktopfile" ]
+
+ Artifact {
+ fileTags: [ "freedesktop.desktopfile" ]
+ filePath: input.fileName
+ }
+
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = input.fileName + "->" + output.fileName;
+ cmd.highlight = "codegen";
+ cmd.sourceCode = function() {
+ var aggregateDesktopKeys = Fdo.parseDesktopFile(input.filePath);
+ var desktopKeys = ModUtils.moduleProperty(product, "desktopKeys") || {}
+ var mainSection = aggregateDesktopKeys['Desktop Entry'];
+ for (key in desktopKeys) {
+ if (desktopKeys.hasOwnProperty(key)) {
+ mainSection[key] = desktopKeys[key];
+ }
+ }
+
+ var defaultValues = product.freedesktop.defaultDesktopKeys
+ for (key in defaultValues) {
+ if (!(key in mainSection)) {
+ mainSection[key] = defaultValues[key];
+ }
+ }
+
+ Fdo.dumpDesktopFile(output.filePath, aggregateDesktopKeys);
+ }
+ return [cmd];
+ }
+ }
+
+ Group {
+ condition: fdoModule._fdoSupported
+ fileTagsFilter: [ "freedesktop.desktopfile" ]
+ qbs.install: true
+ qbs.installDir: "share/applications"
+ }
+
+ Group {
+ condition: fdoModule._fdoSupported
+ fileTagsFilter: [ "freedesktop.appIcon" ]
+ qbs.install: true
+ qbs.installDir: "share/icons/hicolor/scalable/apps"
+ }
+
+ FileTagger {
+ patterns: [ "*.metainfo.xml", "*.appdata.xml" ]
+ fileTags: [ "freedesktop.appstream" ]
+ }
+
+ Group {
+ condition: fdoModule._fdoSupported
+ fileTagsFilter: [ "freedesktop.appstream" ]
+ qbs.install: true
+ qbs.installDir: "share/metainfo"
+ }
+}
diff --git a/share/qbs/modules/freedesktop/freedesktop.js b/share/qbs/modules/freedesktop/freedesktop.js
new file mode 100644
index 000000000..d3c60b191
--- /dev/null
+++ b/share/qbs/modules/freedesktop/freedesktop.js
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Alberto Mardegan <mardy@users.sourceforge.net>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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 http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+var TextFile = require("qbs.TextFile");
+
+function parseDesktopFile(filePath) {
+ var file = new TextFile(filePath);
+ var fileValues = {};
+ var currentSection = {};
+ var sectionRex = /\[(.+)\]/g;
+ while (!file.atEof()) {
+ var line = file.readLine().trim();
+ if (line.length == 0) continue;
+ if (line[0] == '#') continue;
+ var match = sectionRex.exec(line);
+ if (match) {
+ var currentSectionName = match[1];
+ fileValues[currentSectionName] = {};
+ currentSection = fileValues[currentSectionName];
+ continue;
+ }
+ var parts = line.split('=', 2);
+ currentSection[parts[0]] = parts[1]
+ }
+ file.close();
+ return fileValues
+}
+
+function dumpDesktopFile(filePath, keys) {
+ var file = new TextFile(filePath, TextFile.WriteOnly);
+ for (var sectionName in keys) {
+ file.writeLine('[' + sectionName + ']');
+ var section = keys[sectionName];
+ for (var key in section) {
+ var line = key + '=' + section[key];
+ file.writeLine(line);
+ }
+ // Write an empty line between sections (and before EOF)
+ file.writeLine('');
+ }
+ file.close();
+}
diff --git a/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs b/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs
new file mode 100644
index 000000000..60c3d304f
--- /dev/null
+++ b/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs
@@ -0,0 +1,25 @@
+import qbs 1.0
+
+Project {
+ CppApplication {
+ name: "main"
+ install: true
+ files: [
+ "main.cpp",
+ "myapp.desktop",
+ "myapp.appdata.xml",
+ ]
+
+ Depends { name: "freedesktop" }
+
+ freedesktop.name: "My App"
+ freedesktop.desktopKeys: ({
+ 'Icon': "myapp.png"
+ })
+
+ Group {
+ files: "myapp.png"
+ fileTags: "freedesktop.appIcon"
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/freedesktop/main.cpp b/tests/auto/blackbox/testdata/freedesktop/main.cpp
new file mode 100644
index 000000000..905869dfa
--- /dev/null
+++ b/tests/auto/blackbox/testdata/freedesktop/main.cpp
@@ -0,0 +1,4 @@
+int main()
+{
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml b/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml
new file mode 100644
index 000000000..3cf0a5641
--- /dev/null
+++ b/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<component type="desktop">
+ <id>myapp.desktop</id>
+ <metadata_license>CC0</metadata_license>
+ <name>MyApp</name>
+ <summary>The coolest app ever</summary>
+
+ <description>
+ <p>This is a cool application.</p>
+ </description>
+
+ <url type="homepage">https://software.house/myapp</url>
+ <project_license>GPL-2.0+</project_license>
+ <developer_name>Coding Wizard</developer_name>
+</component>
diff --git a/tests/auto/blackbox/testdata/freedesktop/myapp.desktop b/tests/auto/blackbox/testdata/freedesktop/myapp.desktop
new file mode 100644
index 000000000..dac3014c3
--- /dev/null
+++ b/tests/auto/blackbox/testdata/freedesktop/myapp.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+GenericName=Image Editor
+Comment=Create images and edit photographs
+Icon=overridden.png
diff --git a/tests/auto/blackbox/testdata/freedesktop/myapp.png b/tests/auto/blackbox/testdata/freedesktop/myapp.png
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/freedesktop/myapp.png
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index 66b4f8675..876d6239e 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -3771,6 +3771,39 @@ void TestBlackbox::fileTagsFilterMerging()
QVERIFY2(QFile::exists(otherOutput), qPrintable(otherOutput));
}
+void TestBlackbox::freedesktop()
+{
+ if (!HostOsInfo::isAnyUnixHost() || HostOsInfo::isMacosHost())
+ QSKIP("only applies on Unix");
+
+ QDir::setCurrent(testDataDir + "/freedesktop");
+ QCOMPARE(runQbs(), 0);
+
+ // Check desktop file
+ QString desktopFilePath =
+ defaultInstallRoot + "/usr/local/share/applications/myapp.desktop";
+ QVERIFY(QFile::exists(desktopFilePath));
+ QFile desktopFile(desktopFilePath);
+ QVERIFY2(desktopFile.open(QIODevice::ReadOnly), qPrintable(desktopFile.errorString()));
+ QByteArrayList lines = desktopFile.readAll().split('\n');
+ // Automatically filled line:
+ QVERIFY(lines.contains("Exec=main"));
+ // Name specified in `freedesktop.name` property
+ QVERIFY(lines.contains("Name=My App"));
+ // Overridden line:
+ QVERIFY(lines.contains("Icon=myapp.png"));
+ // Untouched line:
+ QVERIFY(lines.contains("Terminal=false"));
+
+ // Check AppStream file
+ QVERIFY(QFile::exists(defaultInstallRoot +
+ "/usr/local/share/metainfo/myapp.appdata.xml"));
+
+ // Check icon file
+ QVERIFY(QFile::exists(defaultInstallRoot +
+ "/usr/local/share/icons/hicolor/scalable/apps/myapp.png"));
+}
+
void TestBlackbox::installedTransformerOutput()
{
QDir::setCurrent(testDataDir + "/installed-transformer-output");
diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h
index f9a3d5c7c..eb9e06dd6 100644
--- a/tests/auto/blackbox/tst_blackbox.h
+++ b/tests/auto/blackbox/tst_blackbox.h
@@ -117,6 +117,7 @@ private slots:
void externalLibs();
void fileDependencies();
void fileTagsFilterMerging();
+ void freedesktop();
void generatedArtifactAsInputToDynamicRule();
void generateLinkerMapFile();
void generator();