From: Dana Jansens Date: Tue, 25 Jan 2011 22:38:47 +0000 (-0500) Subject: Store all links in the linkbase grouped by their main category. X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=d3ae4aa0809da1e9abc7b83c2a03b5f74dbdcd5d;p=dana%2Fopenbox.git Store all links in the linkbase grouped by their main category. --- diff --git a/obt/link.c b/obt/link.c index de665f07..b434ea37 100644 --- a/obt/link.c +++ b/obt/link.c @@ -1,7 +1,7 @@ /* -*- 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 @@ -17,10 +17,16 @@ */ #include "obt/link.h" +#include "obt/bsearch.h" #include "obt/ddparse.h" #include "obt/paths.h" +#include "obt/util.h" #include +#ifdef HAVE_STDLIB_H +#include +#endif + struct _ObtLink { guint ref; @@ -49,6 +55,7 @@ struct _ObtLink { 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 */ @@ -64,6 +71,30 @@ struct _ObtLink { } 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, @@ -74,6 +105,8 @@ ObtLink* obt_link_from_ddfile(const gchar *path, ObtPaths *p, 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 */ @@ -177,13 +210,27 @@ ObtLink* obt_link_from_ddfile(const gchar *path, ObtPaths *p, 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 */ } } @@ -233,6 +280,21 @@ void obt_link_unref(ObtLink *dd) } } +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); diff --git a/obt/link.h b/obt/link.h index 973f1132..922030cd 100644 --- a/obt/link.h +++ b/obt/link.h @@ -1,7 +1,7 @@ /* -*- 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 @@ -117,8 +117,16 @@ const gchar* obt_link_app_executable (ObtLink *e); /*! 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. */ diff --git a/obt/linkbase.c b/obt/linkbase.c index 6ab02887..f96ffbfc 100644 --- a/obt/linkbase.c +++ b/obt/linkbase.c @@ -55,6 +55,12 @@ struct _ObtLinkBase { 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; }; @@ -98,6 +104,27 @@ static GSList* find_base_entry_priority(GSList *list, gint priority) 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, @@ -125,6 +152,13 @@ static void update(ObtWatch *w, const gchar *base_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); @@ -145,6 +179,13 @@ static void update(ObtWatch *w, const gchar *base_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); /* this will put the modified list into the hash table */ @@ -185,6 +226,10 @@ static void update(ObtWatch *w, const gchar *base_path, /* 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); } } } @@ -209,6 +254,7 @@ ObtLinkBase* obt_linkbase_new(ObtPaths *paths, const gchar *locale, 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); @@ -298,6 +344,7 @@ void obt_linkbase_unref(ObtLinkBase *self) 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);