/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
obt/link.c for the Openbox window manager
- Copyright (c) 2009 Dana Jansens
+ Copyright (c) 2009-2011 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
*/
#include "obt/link.h"
+#include "obt/bsearch.h"
#include "obt/ddparse.h"
#include "obt/paths.h"
+#include "obt/util.h"
#include <glib.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
struct _ObtLink {
guint ref;
gchar **mime; /*!< Mime types the app can open */
+ GQuark main_category; /*!< The first main category listed */
GQuark *categories; /*!< Array of quarks representing the
application's categories */
gulong n_categories; /*!< Number of categories for the app */
} d;
};
+#define NUM_MAIN_CATEGORIES 10
+static GQuark MAIN_CATEGORIES[NUM_MAIN_CATEGORIES];
+static gboolean setup = FALSE;
+
+static void startup()
+{
+ if (setup) return;
+
+ setup = TRUE;
+
+ /* From http://standards.freedesktop.org/menu-spec/latest/apa.html */
+ MAIN_CATEGORIES[0] = g_quark_from_static_string("AudioVideo");
+ MAIN_CATEGORIES[1] = g_quark_from_static_string("Development");
+ MAIN_CATEGORIES[2] = g_quark_from_static_string("Education");
+ MAIN_CATEGORIES[3] = g_quark_from_static_string("Game");
+ MAIN_CATEGORIES[4] = g_quark_from_static_string("Graphics");
+ MAIN_CATEGORIES[5] = g_quark_from_static_string("Network");
+ MAIN_CATEGORIES[6] = g_quark_from_static_string("Office");
+ MAIN_CATEGORIES[7] = g_quark_from_static_string("Settings");
+ MAIN_CATEGORIES[8] = g_quark_from_static_string("System");
+ MAIN_CATEGORIES[9] = g_quark_from_static_string("Utility");
+ qsort(MAIN_CATEGORIES, NUM_MAIN_CATEGORIES, sizeof(guint), obt_guint_cmp);
+}
+
ObtLink* obt_link_from_ddfile(const gchar *path, ObtPaths *p,
const gchar *language,
const gchar *country,
ObtDDParseGroup *g;
ObtDDParseValue *v;
+ startup();
+
/* parse the file, and get a hash table of the groups */
groups = obt_ddparse_file(path, language, country, modifier);
if (!groups) return NULL; /* parsing failed */
if ((v = g_hash_table_lookup(keys, "Categories"))) {
gulong i;
gchar *end;
+ gboolean found_main;
+ GQuark cat;
link->d.app.categories = g_new(GQuark, v->value.strings.n);
link->d.app.n_categories = v->value.strings.n;
+ found_main = FALSE;
for (i = 0; i < v->value.strings.n; ++i) {
- link->d.app.categories[i] =
+ cat = link->d.app.categories[i] =
g_quark_from_string(v->value.strings.a[i]);
+
+ if (!found_main) {
+ BSEARCH_SETUP(guint);
+ BSEARCH(guint, MAIN_CATEGORIES, 0, NUM_MAIN_CATEGORIES,
+ cat);
+ if (BSEARCH_FOUND()) {
+ found_main = TRUE;
+ link->d.app.main_category = cat;
+ }
+ }
+
c = end = end+1; /* next */
}
}
}
}
+ObtLinkType obt_link_type (ObtLink *e)
+{
+ g_return_val_if_fail(e != NULL, 0);
+
+ return e->type;
+}
+
+GQuark obt_link_app_main_category (ObtLink *e)
+{
+ g_return_val_if_fail(e != NULL, 0);
+ g_return_val_if_fail(e->type == OBT_LINK_TYPE_APPLICATION, 0);
+
+ return e->d.app.main_category;
+}
+
const GQuark* obt_link_app_categories(ObtLink *e, gulong *n)
{
g_return_val_if_fail(e != NULL, NULL);
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
obt/link.h for the Openbox window manager
- Copyright (c) 2009 Dana Jansens
+ Copyright (c) 2009-2011 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
/*! Returns the path in which the application should be run */
const gchar* obt_link_app_path (ObtLink *e);
gboolean obt_link_app_run_in_terminal (ObtLink *e);
-const gchar*const* obt_link_app_mime_types (ObtLink *e);
+const gchar*const* obt_link_app_mime_types (ObtLink *e);
+
+/*! Returns the first main category listed by the link. This may be 0 if the
+ application does not list a category. */
+GQuark obt_link_app_main_category (ObtLink *e);
+
+/*! Returns a list of categories listed by the link. This may be empty if the
+ application does not list a category. */
const GQuark* obt_link_app_categories (ObtLink *e, gulong *n);
+
/*! Returns a combination of values in the ObtLinkAppOpen enum,
specifying if the application can be launched to open one or more files
and URLs. */
integer that is the priority of that directory. */
GHashTable *path_to_priority;
+ /*! This maps GQuark main categories to GSLists of ObtLink objects found in
+ the category. The ObtLink objects are not reffed to be placed in this
+ structure since they will always be in the base hash table as well. So
+ they are not unreffed when they are removed. */
+ GHashTable *main_categories;
+
ObtLinkBaseUpdateFunc update_func;
gpointer update_data;
};
return it;
}
+static void main_category_add(ObtLinkBase *lb, GQuark cat, ObtLink *link)
+{
+ GSList *list;
+
+ list = g_hash_table_lookup(lb->main_categories, &cat);
+ list = g_slist_prepend(list, link);
+ g_hash_table_insert(lb->main_categories, &cat, list);
+}
+
+static void main_category_remove(ObtLinkBase *lb, GQuark cat, ObtLink *link)
+{
+ GSList *list, *it;
+
+ list = g_hash_table_lookup(lb->main_categories, &cat);
+ it = list;
+ while (it->data != link)
+ it = g_slist_next(it);
+ list = g_slist_delete_link(list, it);
+ g_hash_table_insert(lb->main_categories, &cat, list);
+}
+
/*! Called when a change happens in the filesystem. */
static void update(ObtWatch *w, const gchar *base_path,
const gchar *sub_path,
if (it) {
/* it may be false if the link was skipped during the add because
it did not want to be displayed */
+
+ ObtLink *link = it->data;
+
+ if (obt_link_type(link) == OBT_LINK_TYPE_APPLICATION)
+ main_category_remove(
+ self, obt_link_app_main_category(link), link);
+
list = g_slist_delete_link(list, it);
base_entry_free(it->data);
if (it) {
/* it may be false if the link was skipped during the add because
it did not want to be displayed */
+
+ ObtLink *link = it->data;
+
+ if (obt_link_type(link) == OBT_LINK_TYPE_APPLICATION)
+ main_category_remove(
+ self, obt_link_app_main_category(link), link);
+
list = g_slist_delete_link(list, it);
base_entry_free(it->data);
/* this will put the modified list into the hash table */
/* this will free 'id' */
g_hash_table_insert(self->base, id, list);
id = NULL;
+
+ if (obt_link_type(link) == OBT_LINK_TYPE_APPLICATION)
+ main_category_add(
+ self, obt_link_app_main_category(link), link);
}
}
}
self->base = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
self->path_to_priority = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_free);
+ self->main_categories = g_hash_table_new(g_int_hash, g_int_equal);
self->paths = paths;
obt_paths_ref(paths);
g_hash_table_foreach(self->base, base_entry_list_free, NULL);
obt_watch_unref(self->watch);
+ g_hash_table_unref(self->main_categories);
g_hash_table_unref(self->path_to_priority);
g_hash_table_unref(self->base);
obt_paths_unref(self->paths);