Add linkbase which will keep track of available .desktop files for application launch...
authorDana Jansens <danakj@orodu.net>
Mon, 20 Sep 2010 19:47:10 +0000 (15:47 -0400)
committerDana Jansens <danakj@orodu.net>
Sun, 16 Oct 2011 22:54:04 +0000 (18:54 -0400)
Makefile.am
obt/ddparse.c
obt/ddparse.h
obt/link.c
obt/link.h
obt/linkbase.c [new file with mode: 0644]
obt/linkbase.h [new file with mode: 0644]

index 426fe1ee28043d8809c42bbbf993d00822c0a6ce..11277b2a46b147d4b544788104feb463434bba3b 100644 (file)
@@ -148,6 +148,8 @@ obt_libobt_la_SOURCES = \
        obt/ddparse.c \
        obt/link.h \
        obt/link.c \
+       obt/linkbase.h \
+       obt/linkbase.c \
        obt/paths.h \
        obt/paths.c \
        obt/prop.h \
index 149134d85504a567a0259b8d66b9e22336283c16..9c4424f1fc3e3c64f9f6307c4b7c764e4d8cf3e5 100644 (file)
@@ -45,7 +45,7 @@ enum {
 };
 
 struct _ObtDDParse {
-    gchar *filename;
+    const gchar *filename;
     gulong lineno;
     gulong flags;
     ObtDDParseGroup *group;
@@ -747,15 +747,19 @@ static gboolean parse_desktop_entry_value(gchar *key, const gchar *val,
     return TRUE;
 }
 
-GHashTable* obt_ddparse_file(const gchar *name, GSList *paths)
+GHashTable* obt_ddparse_file(const gchar *filename)
 {
     ObtDDParse parse;
     ObtDDParseGroup *desktop_entry;
-    GSList *it;
     FILE *f;
     gboolean success;
 
-    parse.filename = NULL;
+    if (!g_utf8_validate(filename, -1, NULL)) {
+        g_warning("Filename contains bad utf8: %s", filename);
+        return NULL;
+    }
+
+    parse.filename = filename;
     parse.lineno = 0;
     parse.group = NULL;
     parse.group_hash = g_hash_table_new_full(g_str_hash,
@@ -769,39 +773,34 @@ GHashTable* obt_ddparse_file(const gchar *name, GSList *paths)
     g_hash_table_insert(parse.group_hash, desktop_entry->name, desktop_entry);
 
     success = FALSE;
-    for (it = paths; it && !success; it = g_slist_next(it)) {
-        gchar *path = g_strdup_printf("%s/%s", (char*)it->data, name);
-        if ((f = fopen(path, "r"))) {
-            parse.filename = path;
-            parse.lineno = 1;
-            parse.flags = 0;
-            if ((success = parse_file(f, &parse))) {
-                /* check that required keys exist */
-
-                if (!(parse.flags & DE_TYPE)) {
-                    g_warning("Missing Type key in %s", path);
-                    success = FALSE;
-                }
-                if (!(parse.flags & DE_NAME)) {
-                    g_warning("Missing Name key in %s", path);
-                    success = FALSE;
-                }
-                if (parse.flags & DE_TYPE_APPLICATION &&
-                    !(parse.flags & DE_EXEC))
-                {
-                    g_warning("Missing Exec key for Application in %s",
-                              path);
-                    success = FALSE;
-                }
-                else if (parse.flags & DE_TYPE_LINK && !(parse.flags & DE_URL))
-                {
-                    g_warning("Missing URL key for Link in %s", path);
-                    success = FALSE;
-                }
+    if ((f = fopen(parse.filename, "r"))) {
+        parse.lineno = 1;
+        parse.flags = 0;
+        if ((success = parse_file(f, &parse))) {
+            /* check that required keys exist */
+
+            if (!(parse.flags & DE_TYPE)) {
+                g_warning("Missing Type key in %s", parse.filename);
+                success = FALSE;
+            }
+            if (!(parse.flags & DE_NAME)) {
+                g_warning("Missing Name key in %s", parse.filename);
+                success = FALSE;
+            }
+            if (parse.flags & DE_TYPE_APPLICATION &&
+                !(parse.flags & DE_EXEC))
+            {
+                g_warning("Missing Exec key for Application in %s",
+                          parse.filename);
+                success = FALSE;
+            }
+            else if (parse.flags & DE_TYPE_LINK && !(parse.flags & DE_URL))
+            {
+                g_warning("Missing URL key for Link in %s", parse.filename);
+                success = FALSE;
             }
-            fclose(f);
         }
-        g_free(path);
+        fclose(f);
     }
     if (!success) {
         g_hash_table_destroy(parse.group_hash);
@@ -814,3 +813,44 @@ GHashTable* obt_ddparse_group_keys(ObtDDParseGroup *g)
 {
     return g->key_hash;
 }
+
+gchar* obt_ddparse_file_to_id(const gchar *filename)
+{
+    gint len;
+    const gchar *in;
+    gchar *out;
+    gboolean sep;
+
+    if (!g_utf8_validate(filename, -1, NULL)) {
+        g_warning("Filename contains bad utf8: %s", filename);
+        return NULL;
+    }
+
+    len = strlen(filename) - 8;  /* 8 = strlen(".desktop") */
+    g_assert(strcmp(filename+len, ".desktop") == 0);
+
+    out = g_new(char, len+1);
+    sep = TRUE;
+    for (in = filename; *in; ++in) {
+        gchar *next;
+
+        if (*in == '/') {
+            /* path separators becomes dashes */
+            if (!sep) {
+                *out = '-';
+                ++out;
+            }
+            sep = TRUE;
+        }
+        else {
+            /* everything else is copied as is */
+            next = g_utf8_next_char(in);
+            while (in < next) {
+                *out = *in;
+                ++out;
+                ++in;
+            }
+        }
+    }
+    return out;
+}
index d261f5bb0c444d253fbf89850564be9401fb53f7..050aaa9609c7c83748f6d2f8d960b43838e3dbf3 100644 (file)
@@ -48,10 +48,24 @@ typedef struct _ObtDDParseValue {
     } value;
 } ObtDDParseValue;
 
-/* Returns a hash table where the keys are groups, and the values are
-   ObtDDParseGroups */
-GHashTable* obt_ddparse_file(const gchar *name, GSList *paths);
+/*! Parse a .desktop file.
+  @param filename The full path to the .desktop file to be read.
+  @return Returns a hash table where the keys are groups, and the values are
+    ObtDDParseGroups */
+GHashTable* obt_ddparse_file(const gchar *filename);
 
-/* Returns a hash table where the keys are "keys" in the .desktop file,
-   and the values are "values" in the .desktop file, for the group @g. */
+/*! Get the keys in a group from a .desktop file.
+  The group comes from the hash table returned by obt_ddparse_file.
+  @return Returns a hash table where the keys are "keys" in the .desktop file,
+    represented as strings.  The values are "values" in the .desktop file, for
+    the group @g. Each value will be a pointer to an ObtDDParseValue structure.
+*/
 GHashTable* obt_ddparse_group_keys(ObtDDParseGroup *g);
+
+/*! Determine the id for a .desktop file.
+  @param filename The path to the .desktop file, _relative to_ some
+    basepath. filename must end with ".desktop" and be encoded in utf8.
+  @return Returns a string which is the id for the given .desktop file in its
+    current position.  Returns NULL if there is an error.
+*/
+gchar* obt_ddparse_file_to_id(const gchar *filename);
index 9cc2bac96d7cb3bdcf180d52711d739ed6898590..eb24a113fdb4684fb6ac40e21d72e7943888f100 100644 (file)
@@ -62,17 +62,21 @@ struct _ObtLink {
     } d;
 };
 
-ObtLink* obt_link_from_ddfile(const gchar *ddname, GSList *paths,
+ObtLink* obt_link_from_ddfile(const gchar *basepath, const gchar *filename,
                               ObtPaths *p)
 {
     ObtLink *link;
     GHashTable *groups, *keys;
     ObtDDParseGroup *g;
     ObtDDParseValue *v;
+    gchar *path;
 
     /* parse the file, and get a hash table of the groups */
-    groups = obt_ddparse_file(ddname, paths);
+    path = g_strconcat(basepath, filename, NULL);
+    groups = obt_ddparse_file(path);
+    g_free(path);
     if (!groups) return NULL; /* parsing failed */
+
     /* grab the Desktop Entry group */
     g = g_hash_table_lookup(groups, "Desktop Entry");
     g_assert(g != NULL);
index 9ad86cc9027ebedc88020e75d24f325fe3ef3e60..dff11f3c580d0067a2bb4f5364d10ff87967f7e9 100644 (file)
@@ -62,7 +62,13 @@ typedef enum {
 
 typedef struct _ObtLink     ObtLink;
 
-ObtLink* obt_link_from_ddfile(const gchar *name, GSList *paths,
+/*! Parse a .desktop (dd) file.
+  @param basepath The base directory in which to read the file.
+  @param filename The full path to the .desktop file _relative to_ basepath.
+    It must be in basepath or a subdirectory of it.
+  @param o An ObtPaths structure, which contains the executable paths.
+*/
+ObtLink* obt_link_from_ddfile(const gchar *basepath, const gchar *filename,
                               struct _ObtPaths *p);
 
 void obt_link_ref(ObtLink *e);
diff --git a/obt/linkbase.c b/obt/linkbase.c
new file mode 100644 (file)
index 0000000..1039b34
--- /dev/null
@@ -0,0 +1,66 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+   obt/linkbase.c for the Openbox window manager
+   Copyright (c) 2010        Dana Jansens
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "obt/linkbase.h"
+#include "obt/link.h"
+#include "obt/paths.h"
+#include "obt/watch.h"
+
+struct _ObtLinkBase {
+    gint ref;
+
+    ObtWatch *watch;
+    GHashTable *base;
+};
+
+static void func(ObtWatch *w, const gchar *subpath, ObtWatchNotifyType type,
+                 gpointer data)
+{
+}
+
+ObtLinkBase* obt_linkbase_new(ObtPaths *paths)
+{
+    ObtLinkBase *b;
+    GSList *it;
+    
+    b = g_slice_new(ObtLinkBase);
+    b->watch = obt_watch_new();
+    b->base = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+                                    (GDestroyNotify)obt_link_unref);
+
+    for (it = obt_paths_data_dirs(paths); it; it = g_slist_next(it)) {
+        gchar *p;
+        p = g_strconcat(it->data, "/applications", NULL);
+        obt_watch_add(b->watch, p, FALSE, func, b);
+    }
+    return b;
+}
+
+void obt_linkbase_ref(ObtLinkBase *lb)
+{
+    ++lb->ref;
+}
+
+void obt_linkbase_unref(ObtLinkBase *lb)
+{
+    if (--lb->ref < 1) {
+        obt_watch_unref(lb->watch);
+        g_hash_table_unref(lb->base);
+        g_slice_free(ObtLinkBase, lb);
+    }
+}
diff --git a/obt/linkbase.h b/obt/linkbase.h
new file mode 100644 (file)
index 0000000..76bf443
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+   obt/linkbase.h for the Openbox window manager
+   Copyright (c) 2010        Dana Jansens
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_linkbase_h
+#define __obt_linkbase_h
+
+struct _ObtPaths;
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ObtLinkBase ObtLinkBase;
+
+/*! Create a new database of ObtLinks. */
+ObtLinkBase* obt_linkbase_new(struct _ObtPaths *paths);
+void obt_linkbase_ref(ObtLinkBase *lb);
+void obt_linkbase_unref(ObtLinkBase *lb);
+
+G_END_DECLS
+
+#endif