From 5ff941fc5fe24a7cd968afd32bb1a2752d823ff8 Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Sat, 5 Mar 2016 03:17:43 +0100 Subject: [PATCH] First pieces of .desktop file parser --- source/data-cache.d | 1 - source/handlers/desktopparser.d | 114 +++++++++++++++++++++++++++++++- source/hint.d | 4 +- source/result.d | 32 ++++++++- 4 files changed, 145 insertions(+), 6 deletions(-) diff --git a/source/data-cache.d b/source/data-cache.d index f8b7e95..62c38a3 100644 --- a/source/data-cache.d +++ b/source/data-cache.d @@ -37,7 +37,6 @@ public: this () { - writeln ("HELLO THERE!"); } ~this () diff --git a/source/handlers/desktopparser.d b/source/handlers/desktopparser.d index f619763..e1335bd 100644 --- a/source/handlers/desktopparser.d +++ b/source/handlers/desktopparser.d @@ -17,4 +17,116 @@ * along with this software. If not, see . */ - module ag.handler.desktopparser; +module ag.handler.desktopparser; + +import std.path : baseName; +import std.uni : toLower; +import std.string : format; +import std.algorithm : startsWith; +import glib.KeyFile; +import appstream.Component; + +import ag.result; + + +immutable DESKTOP_GROUP = "Desktop Entry"; + +private string getLocaleFromKey (string key) +{ + return "C"; +} + +private string getValue (KeyFile kf, string key) +{ + string val; + try { + val = kf.getString (DESKTOP_GROUP, key); + } catch { + val = null; + } + + return val; +} + +bool parseDesktopFile (GeneratorResult res, string fname, string data, bool ignore_nodisplay = false) +{ + auto df = new KeyFile (); + try { + df.loadFromData (data, -1, GKeyFileFlags.NONE); + } catch (Exception e) { + // there was an error + res.addHint ("desktop-file-read-error", e.msg); + return false; + } + + try { + // check if we should ignore this .desktop file + auto dtype = df.getString (DESKTOP_GROUP, "Type"); + if (dtype.toLower () != "application") { + // ignore this file, it isn't describing an application + return false; + } + } catch {} + + try { + auto nodisplay = df.getString (DESKTOP_GROUP, "NoDisplay"); + if ((!ignore_nodisplay) && (nodisplay.toLower () == "true")) { + // we ignore this .desktop file, shouldn't be displayed + return false; + } + } catch {} + + try { + auto asignore = df.getString (DESKTOP_GROUP, "X-AppStream-Ignore"); + if (asignore.toLower () == "true") { + // this .desktop file should be excluded from AppStream metadata + return false; + } + } catch { + // we don't care if non-essential tags are missing. + // if they are not there, the file should be processed. + } + + /* check this is a valid desktop file */ + if (!df.hasGroup (DESKTOP_GROUP)) { + res.addHint ("desktop-file-error", format ("Desktop file '%s' is not a valid desktop file.", fname)); + return false; + } + + // make sure we have a valid component to work on + auto cpt = res.getComponent (fname); + if (cpt is null) { + auto fname_base = baseName (fname); + cpt = new Component (); + cpt.setId (fname_base); + cpt.setKind (ComponentKind.DESKTOP); + res.addComponent (cpt); + } + + size_t dummy; + auto keys = df.getKeys (DESKTOP_GROUP, dummy); + foreach (string key; keys) { + if (key.startsWith ("Name")) { + auto locale = getLocaleFromKey (key); + cpt.setName (getValue (df, key), locale); + } + } + + return true; +} + +unittest +{ + import std.stdio; + + auto data = """ +[Desktop Entry] +Name=FooBar +Name[de_DE]=FooBär +Summary=A foo-ish bar. +"""; + + auto res = new GeneratorResult (); + auto ret = parseDesktopFile (res, "foobar.desktop", data, false); + assert (ret == true); +} diff --git a/source/hint.d b/source/hint.d index b5d17be..bf53dcd 100644 --- a/source/hint.d +++ b/source/hint.d @@ -27,11 +27,13 @@ class GeneratorHint { private: + string tag; public: - this () + this (string tag) { + this.tag = tag; } } diff --git a/source/result.d b/source/result.d index 90a1a24..4d47165 100644 --- a/source/result.d +++ b/source/result.d @@ -21,16 +21,19 @@ module ag.result; import std.stdio; import std.string; -import ag.hint; +import std.array : empty; import appstream.Component; +import ag.hint; + class GeneratorResult { private: - Component cpts[]; - GeneratorHint hints[]; + Component[string] cpts; + string[Component] cptGID; + GeneratorHint[] hints; public: @@ -42,4 +45,27 @@ public: { return cpts.length == 0; } + + Component getComponent (string id) + { + auto ptr = (id in cpts); + if (ptr is null) + return null; + return *ptr; + } + + void addComponent (Component cpt) + { + string cid = cpt.getId (); + if (cid.empty) + throw new Exception ("Can not add component without ID to results set."); + + cpts[cid] = cpt; + } + + void addHint (string tag, string msg) + { + auto hint = new GeneratorHint (tag); + hints ~= hint; + } }