[glib/wip/gdesktopappinfo: 13/13] other stuff



commit 40c9dbc9c0030c758ddf80cd93b589f32207f041
Author: Ryan Lortie <desrt desrt ca>
Date:   Sun Jul 28 13:41:22 2013 -0400

    other stuff

 gio/gdesktopappinfo.c |  305 +++++++++++++++++++++++++++++++++++++++++++++----
 gio/gdesktopappinfo.h |    3 +
 2 files changed, 288 insertions(+), 20 deletions(-)
---
diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
index e2270a2..8b9fe4d 100644
--- a/gio/gdesktopappinfo.c
+++ b/gio/gdesktopappinfo.c
@@ -147,6 +147,8 @@ G_DEFINE_TYPE_WITH_CODE (GDesktopAppInfo, g_desktop_app_info, G_TYPE_OBJECT,
 G_LOCK_DEFINE_STATIC (g_desktop_env);
 static gchar *g_desktop_env = NULL;
 
+/* DesktopFileDirIndex implementation {{{1 */
+
 /* DesktopFileDir implementation {{{1 */
 
 typedef struct
@@ -156,6 +158,10 @@ typedef struct
   GHashTable                 *app_names;
   gboolean                    is_setup;
   struct dfi_index           *dfi;
+  gint8                      *key_id_map;
+  guint16                     key_id_map_length;
+  guint16                     this_locale_id;
+  guint16                     desktop_entry_id;
 } DesktopFileDir;
 
 static DesktopFileDir *desktop_file_dirs;
@@ -335,39 +341,185 @@ desktop_file_dir_unindexed_get_all (DesktopFileDir *dir,
     }
 }
 
+static void
+desktop_file_dir_unindexed_search (DesktopFileDir  *dir,
+                                   GSList         **buckets,
+                                   const gchar     *term)
+{
+  /* TODO */
+}
+
 /* Support for indexed DesktopFileDirs {{{2 */
 
-#if 0
 enum
 {
-  DFI_ID_THIS_LOCALE,
-
-  DFI_ID_Desktop_Entry,
+  DESKTOP_KEY_nil,
+
+  /* NB: must keep this list sorted */
+  DESKTOP_KEY_Actions,
+  DESKTOP_KEY_Categories,
+  DESKTOP_KEY_Comment,
+  DESKTOP_KEY_DBusActivatable,
+  DESKTOP_KEY_Exec,
+  DESKTOP_KEY_GenericName,
+  DESKTOP_KEY_Hidden,
+  DESKTOP_KEY_Icon,
+  DESKTOP_KEY_Keywords,
+  DESKTOP_KEY_MimeType,
+  DESKTOP_KEY_Name,
+  DESKTOP_KEY_NoDisplay,
+  DESKTOP_KEY_NotShowIn,
+  DESKTOP_KEY_OnlyShowIn,
+  DESKTOP_KEY_Path,
+  DESKTOP_KEY_StartupNotify,
+  DESKTOP_KEY_StartupWMClass,
+  DESKTOP_KEY_Terminal,
+  DESKTOP_KEY_TryExec,
+  DESKTOP_KEY_Type,
+  DESKTOP_KEY_Version,
+  DESKTOP_KEY_X_GNOME_FullName,
+
+  N_DESKTOP_KEYS
+};
 
-  DFI_ID_Name,
-  DFI_ID_Keywords,
-  DFI_ID_GenericName,
-  DFI_ID_X_GNOME_FullName,
-  DFI_ID_Comment,
+const gchar *desktop_key_names[N_DESKTOP_KEYS];
 
-  N_DFI_IDS
+const gchar desktop_key_match_category[N_DESKTOP_KEYS] = {
+  /* NB: no harm in repeating numbers in case of a tie */
+  [DESKTOP_KEY_Name]             = 1,
+  [DESKTOP_KEY_GenericName]      = 2,
+  [DESKTOP_KEY_Keywords]         = 3,
+  [DESKTOP_KEY_X_GNOME_FullName] = 4,
+  [DESKTOP_KEY_Comment]          = 5
 };
-#endif
+
+#define DESKTOP_KEY_NUM_MATCH_CATEGORIES  5
+
+static void
+desktop_key_init (void)
+{
+  if G_LIKELY (desktop_key_names[1])
+    return;
+
+  desktop_key_names[DESKTOP_KEY_Actions]                = g_intern_static_string ("Actions");
+  desktop_key_names[DESKTOP_KEY_Categories]             = g_intern_static_string ("Categories");
+  desktop_key_names[DESKTOP_KEY_Comment]                = g_intern_static_string ("Comment");
+  desktop_key_names[DESKTOP_KEY_DBusActivatable]        = g_intern_static_string ("DBusActivatable");
+  desktop_key_names[DESKTOP_KEY_Exec]                   = g_intern_static_string ("Exec");
+  desktop_key_names[DESKTOP_KEY_GenericName]            = g_intern_static_string ("GenericName");
+  desktop_key_names[DESKTOP_KEY_Hidden]                 = g_intern_static_string ("Hidden");
+  desktop_key_names[DESKTOP_KEY_Icon]                   = g_intern_static_string ("Icon");
+  desktop_key_names[DESKTOP_KEY_Keywords]               = g_intern_static_string ("Keywords");
+  desktop_key_names[DESKTOP_KEY_MimeType]               = g_intern_static_string ("MimeType");
+  desktop_key_names[DESKTOP_KEY_Name]                   = g_intern_static_string ("Name");
+  desktop_key_names[DESKTOP_KEY_NoDisplay]              = g_intern_static_string ("NoDisplay");
+  desktop_key_names[DESKTOP_KEY_NotShowIn]              = g_intern_static_string ("NotShowIn");
+  desktop_key_names[DESKTOP_KEY_OnlyShowIn]             = g_intern_static_string ("OnlyShowIn");
+  desktop_key_names[DESKTOP_KEY_Path]                   = g_intern_static_string ("Path");
+  desktop_key_names[DESKTOP_KEY_StartupNotify]          = g_intern_static_string ("StartupNotify");
+  desktop_key_names[DESKTOP_KEY_StartupWMClass]         = g_intern_static_string ("StartupWMClass");
+  desktop_key_names[DESKTOP_KEY_Terminal]               = g_intern_static_string ("Terminal");
+  desktop_key_names[DESKTOP_KEY_TryExec]                = g_intern_static_string ("TryExec");
+  desktop_key_names[DESKTOP_KEY_Type]                   = g_intern_static_string ("Type");
+  desktop_key_names[DESKTOP_KEY_Version]                = g_intern_static_string ("Version");
+  desktop_key_names[DESKTOP_KEY_X_GNOME_FullName]       = g_intern_static_string ("X-GNOME-FullName");
+}
 
 static void
 desktop_file_dir_indexed_init (DesktopFileDir *dir)
 {
-  const struct dfi_string_list *app_names;
-  guint n_app_names, i;
+  desktop_key_init ();
 
-  dir->app_names = g_hash_table_new (g_str_hash, g_str_equal);
-  app_names = dfi_index_get_app_names (dir->dfi);
-  n_app_names = dfi_string_list_get_length (app_names);
+  /* Find the current locale */
+  {
+    const struct dfi_string_list *locale_names;
+    const gchar * const *language_names;
+    gint i;
+
+    locale_names = dfi_index_get_locale_names (dir->dfi);
+
+    language_names = g_get_language_names ();
+    locale_names = dfi_index_get_locale_names (dir->dfi);
+
+    /* If we don't get anything, the C locale is always zero, so set
+     * it as a default.
+     */
+    dir->this_locale_id = 0;
 
-  for (i = 0; i < n_app_names; i++)
-    g_hash_table_insert (dir->app_names,
-                         (gchar *) dfi_string_list_get_string_at_index (app_names, dir->dfi, i),
-                         GUINT_TO_POINTER (i));
+    /* Iterate over our language names, in order of preference */
+    for (i = 0; language_names[i]; i++)
+      {
+        gint result = dfi_string_list_binary_search (locale_names, dir->dfi, language_names[i]);
+
+        if (result >= 0)
+          {
+            dir->this_locale_id = result;
+            break;
+          }
+      }
+
+    g_printerr ("found my locale is %d/%s\n", dir->this_locale_id, language_names[i]);
+  }
+
+  /* Populate the app names list. */
+  {
+    const struct dfi_string_list *app_names;
+    guint n_app_names, i;
+
+    app_names = dfi_index_get_app_names (dir->dfi);
+    n_app_names = dfi_string_list_get_length (app_names);
+
+    /* Store the index of each application so we don't need to do binary
+     * searches to find applications.
+     */
+    dir->app_names = g_hash_table_new (g_str_hash, g_str_equal);
+
+    for (i = 0; i < n_app_names; i++)
+      g_hash_table_insert (dir->app_names,
+                           (gchar *) dfi_string_list_get_string_at_index (app_names, dir->dfi, i),
+                           GUINT_TO_POINTER (i));
+  }
+
+  /* Find the ID of the [Desktop Entry] group */
+  {
+    const struct dfi_string_list *group_names;
+
+    group_names = dfi_index_get_group_names (dir->dfi);
+
+    dir->desktop_entry_id = dfi_string_list_binary_search (group_names, dir->dfi, "Desktop Entry");
+  }
+
+  /* Populate the key id map */
+  {
+    const struct dfi_string_list *key_names;
+    guint n_key_names;
+    guint i = 0;
+    guint j = 1;
+
+    key_names = dfi_index_get_key_names (dir->dfi);
+    n_key_names = dfi_string_list_get_length (key_names);
+
+    dir->key_id_map = g_malloc0 (n_key_names);
+    dir->key_id_map_length = n_key_names;
+
+    while (i < n_key_names && j < N_DESKTOP_KEYS)
+      {
+        const gchar *keyname = dfi_string_list_get_string_at_index (key_names, dir->dfi, i);
+        gint cmp;
+
+        cmp = strcmp (keyname, desktop_key_names[j]);
+
+        if (cmp == 0)
+          {
+            g_printerr ("mapped keyname %s(%d) to %d\n", keyname, i, j);
+          dir->key_id_map[i++] = j++;
+          }
+        else if (cmp < 0)
+          i++;
+        else
+          j++;
+      }
+  }
 }
 
 static GDesktopAppInfo *
@@ -409,6 +561,75 @@ desktop_file_dir_indexed_get_all (DesktopFileDir *dir,
     }
 }
 
+static void
+desktop_file_dir_indexed_search (DesktopFileDir  *dir,
+                                 GSList         **buckets,
+                                 const gchar     *term)
+{
+  const struct dfi_pointer_array *text_indexes;
+  const struct dfi_string_list *app_names;
+  const struct dfi_text_index *text_index;
+  const struct dfi_text_index_item *start;
+  const struct dfi_text_index_item *end;
+  const struct dfi_text_index_item *item;
+
+  text_indexes = dfi_index_get_text_indexes (dir->dfi);
+  text_index = dfi_text_index_from_pointer (dir->dfi,
+                                            dfi_pointer_array_get_pointer (text_indexes, 
dir->this_locale_id));
+  if (text_index == NULL)
+    return;
+
+  //dfi_text_index_prefix_search (text_index, dir->dfi, term, &start, &end);
+  start = NULL;
+  end = start + 1;
+
+  app_names = dfi_index_get_app_names (dir->dfi);
+
+  for (item = start; item < end; item++)
+    {
+      const dfi_id *ids;
+      guint n_ids;
+
+      gint j;
+
+      //ids = dfi_text_index_item_get_ids (item, dir->dfi, &n_ids);
+      n_ids = 0;
+      ids = dfi_text_index_get_ids_for_exact_match (dir->dfi, text_index, term, (gint *) &n_ids);
+      g_printerr ("n_ids is %u\n", n_ids);
+
+      if (n_ids % 3 != 0)
+        continue;
+
+      for (j = 0; j < n_ids; j += 3)
+        {
+          guint16 app_id, group_id, key_id;
+          const gchar *app_name;
+          guint8 match_category;
+
+          app_id   = dfi_id_get (ids[j + 0]);
+          group_id = dfi_id_get (ids[j + 1]);
+          key_id   = dfi_id_get (ids[j + 2]);
+
+          app_name = dfi_string_list_get_string_at_index (app_names, dir->dfi, app_id);
+          if (!app_name)
+            continue;
+
+          if (group_id != dir->desktop_entry_id)
+            continue;
+
+          if (key_id >= dir->key_id_map_length)
+            continue;
+
+          match_category = desktop_key_match_category[dir->key_id_map[key_id]];
+
+          if (!match_category)
+            continue;
+
+          g_printerr ("Matched '%s' in category %d\n", app_name, match_category);
+        }
+    }
+}
+
 /* DesktopFileDir "API" {{{2 */
 
 /*< internal >
@@ -458,6 +679,16 @@ desktop_file_dir_reset (DesktopFileDir *dir)
       dir->dfi = NULL;
     }
 
+  if (dir->key_id_map)
+    {
+      g_free (dir->key_id_map);
+      dir->key_id_map = NULL;
+    }
+
+  dir->key_id_map_length = 0;
+  dir->desktop_entry_id = 0;
+  dir->this_locale_id = 0;
+
   dir->is_setup = FALSE;
 }
 
@@ -536,6 +767,26 @@ desktop_file_dir_get_all (DesktopFileDir *dir,
     desktop_file_dir_unindexed_get_all (dir, apps);
 }
 
+#define N_SEARCH_BUCKETS 1
+
+/*< internal >
+ * desktop_file_dir_search:
+ * @dir: a #DesktopFilEDir
+ * @term: a normalised and casefolded search term
+ *
+ * Finds the names of applications in @dir that match @term.
+ */
+static void
+desktop_file_dir_search (DesktopFileDir  *dir,
+                         GSList         **buckets,
+                         const gchar     *term)
+{
+  if (dir->dfi)
+    desktop_file_dir_indexed_search (dir, buckets, term);
+  else
+    desktop_file_dir_unindexed_search (dir, buckets, term);
+}
+
 /* Lock/unlock and global setup API {{{2 */
 
 static void
@@ -3202,6 +3453,20 @@ g_app_info_get_default_for_uri_scheme (const char *uri_scheme)
 
 /* "Get all" API {{{2 */
 
+
+void
+g_desktop_app_info_search (const char *token)
+{
+  gint i;
+
+  desktop_file_dirs_lock ();
+
+  for (i = 0; i < n_desktop_file_dirs; i++)
+    desktop_file_dir_search (&desktop_file_dirs[i], NULL, token);
+
+  desktop_file_dirs_unlock ();
+}
+
 /**
  * g_app_info_get_all:
  *
diff --git a/gio/gdesktopappinfo.h b/gio/gdesktopappinfo.h
index 5f7f68a..eb1a491 100644
--- a/gio/gdesktopappinfo.h
+++ b/gio/gdesktopappinfo.h
@@ -165,6 +165,9 @@ gboolean    g_desktop_app_info_launch_uris_as_manager (GDesktopAppInfo
                                                       GError                    **error);
 
 
+GLIB_AVAILABLE_IN_2_30
+void g_desktop_app_info_search (const gchar *term);
+
 G_END_DECLS
 
 #endif /* __G_DESKTOP_APP_INFO_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]