[glib/wip/gdesktopappinfo: 6/8] Add support for the desktop file index
- From: Ryan Lortie <desrt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/gdesktopappinfo: 6/8] Add support for the desktop file index
- Date: Thu, 3 Oct 2013 15:09:42 +0000 (UTC)
commit aba3ed044cbdd21c7c90f76e6b72da17db285aaf
Author: Ryan Lortie <desrt desrt ca>
Date: Sat Jul 27 16:07:40 2013 -0400
Add support for the desktop file index
Add an implementation of GDesktopAppInfo based on the desktop file
index.
We currently construct keyfile-based GDesktopAppInfos in the
least-efficient way imaginable (which still ends up being faster than
reading them off the disk). Will be fixed in the future...
gio/gdesktopappinfo.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 163 insertions(+), 3 deletions(-)
---
diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
index 643d574..8ece3d8 100644
--- a/gio/gdesktopappinfo.c
+++ b/gio/gdesktopappinfo.c
@@ -49,6 +49,7 @@
#include "gappinfo.h"
#include "glocaldirectorymonitor.h"
+#include "dfi-reader.h"
/**
* SECTION:gdesktopappinfo
@@ -87,6 +88,12 @@ static void mime_info_cache_reload (const char *dir);
static gboolean g_desktop_app_info_ensure_saved (GDesktopAppInfo *info,
GError **error);
+static GDesktopAppInfo *
+g_desktop_app_info_new_from_index (const struct dfi_index *dfi,
+ const struct dfi_pointer_array *array,
+ guint app_num,
+ const gchar *desktop_id);
+
/**
* GDesktopAppInfo:
*
@@ -149,6 +156,7 @@ typedef struct
GLocalDirectoryMonitor *monitor;
GHashTable *app_names;
gboolean is_setup;
+ struct dfi_index *dfi;
} DesktopFileDir;
static DesktopFileDir *desktop_file_dirs;
@@ -328,6 +336,80 @@ desktop_file_dir_unindexed_get_all (DesktopFileDir *dir,
}
}
+/* Support for indexed DesktopFileDirs {{{2 */
+
+#if 0
+enum
+{
+ DFI_ID_THIS_LOCALE,
+
+ DFI_ID_Desktop_Entry,
+
+ DFI_ID_Name,
+ DFI_ID_Keywords,
+ DFI_ID_GenericName,
+ DFI_ID_X_GNOME_FullName,
+ DFI_ID_Comment,
+
+ N_DFI_IDS
+};
+#endif
+
+static void
+desktop_file_dir_indexed_init (DesktopFileDir *dir)
+{
+ const struct dfi_string_list *app_names;
+ guint n_app_names, i;
+
+ 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);
+
+ 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));
+}
+
+static GDesktopAppInfo *
+desktop_file_dir_indexed_get_app (DesktopFileDir *dir,
+ const gchar *desktop_id)
+{
+ gpointer value;
+ guint app_num;
+
+ if (!g_hash_table_lookup_extended (dir->app_names, desktop_id, NULL, &value))
+ return NULL;
+
+ app_num = GPOINTER_TO_UINT (value);
+
+ return g_desktop_app_info_new_from_index (dir->dfi, dfi_index_get_desktop_files (dir->dfi), app_num,
desktop_id);
+}
+
+static void
+desktop_file_dir_indexed_get_all (DesktopFileDir *dir,
+ GHashTable *apps)
+{
+ const struct dfi_pointer_array *desktop_files;
+ guint i, n_desktop_files;
+
+ desktop_files = dfi_index_get_desktop_files (dir->dfi);
+
+ n_desktop_files = dfi_pointer_array_get_length (desktop_files, dir->dfi);
+ for (i = 0; i < n_desktop_files; i++)
+ {
+ const gchar *app_name;
+
+ app_name = dfi_pointer_array_get_item_key (desktop_files, dir->dfi, i);
+
+ if (desktop_file_dir_app_name_is_masked (dir, app_name))
+ continue;
+
+ add_to_table_if_appropriate (apps, app_name,
+ g_desktop_app_info_new_from_index (dir->dfi, desktop_files, i, app_name));
+ }
+}
+
/* DesktopFileDir "API" {{{2 */
/*< internal >
@@ -371,6 +453,12 @@ desktop_file_dir_reset (DesktopFileDir *dir)
dir->app_names = NULL;
}
+ if (dir->dfi)
+ {
+ dfi_index_free (dir->dfi);
+ dir->dfi = NULL;
+ }
+
dir->is_setup = FALSE;
}
@@ -396,7 +484,12 @@ desktop_file_dir_init (DesktopFileDir *dir)
g_local_directory_monitor_start (dir->monitor);
}
- desktop_file_dir_unindexed_init (dir);
+ dir->dfi = dfi_index_new (dir->path);
+
+ if (dir->dfi)
+ desktop_file_dir_indexed_init (dir);
+ else
+ desktop_file_dir_unindexed_init (dir);
dir->is_setup = TRUE;
}
@@ -419,7 +512,10 @@ desktop_file_dir_get_app (DesktopFileDir *dir,
if (!dir->app_names)
return NULL;
- return desktop_file_dir_unindexed_get_app (dir, desktop_id);
+ if (dir->dfi)
+ return desktop_file_dir_indexed_get_app (dir, desktop_id);
+ else
+ return desktop_file_dir_unindexed_get_app (dir, desktop_id);
}
/*< internal >
@@ -435,7 +531,10 @@ static void
desktop_file_dir_get_all (DesktopFileDir *dir,
GHashTable *apps)
{
- desktop_file_dir_unindexed_get_all (dir, apps);
+ if (dir->dfi)
+ desktop_file_dir_indexed_get_all (dir, apps);
+ else
+ desktop_file_dir_unindexed_get_all (dir, apps);
}
/* Lock/unlock and global setup API {{{2 */
@@ -942,6 +1041,67 @@ g_desktop_app_info_dup (GAppInfo *appinfo)
return G_APP_INFO (new_info);
}
+
+static GDesktopAppInfo *
+g_desktop_app_info_new_from_index (const struct dfi_index *dfi,
+ const struct dfi_pointer_array *array,
+ guint app_num,
+ const gchar *desktop_id)
+{
+ const struct dfi_keyfile *keyfile;
+ GDesktopAppInfo *appinfo;
+ guint n_groups, i;
+ GString *string;
+ GKeyFile *kf;
+
+ keyfile = dfi_keyfile_from_pointer (dfi, dfi_pointer_array_get_pointer (array, app_num));
+
+ /* What is the least efficient possible way of doing this? Let's see... */
+ string = g_string_new (NULL);
+
+ n_groups = dfi_keyfile_get_n_groups (keyfile);
+ for (i = 0; i < n_groups; i++)
+ {
+ const gchar *group_name;
+ guint start, end;
+ guint j;
+
+ group_name = dfi_keyfile_get_group_name (keyfile, dfi, i);
+ g_string_append_printf (string, "[%s]\n", group_name);
+
+ dfi_keyfile_get_group_range (keyfile, i, &start, &end);
+
+ for (j = start; j < end; j++)
+ {
+ const gchar *key, *locale, *value;
+
+ dfi_keyfile_get_item (keyfile, dfi, j, &key, &locale, &value);
+
+ if (locale[0])
+ g_string_append_printf (string, "%s[%s]=%s\n", key, locale, value);
+ else
+ g_string_append_printf (string, "%s=%s\n", key, value);
+ }
+ }
+
+ kf = g_key_file_new ();
+ g_key_file_load_from_data (kf, string->str, string->len, G_KEY_FILE_NONE, NULL);
+ g_string_free (string, TRUE);
+
+ appinfo = g_object_new (G_TYPE_DESKTOP_APP_INFO, "filename", desktop_id, NULL);
+
+ if (!g_desktop_app_info_load_from_keyfile (appinfo, kf))
+ {
+ g_object_unref (appinfo);
+ g_key_file_free (kf);
+ return NULL;
+ }
+
+ g_key_file_free (kf);
+
+ return appinfo;
+}
+
/* GAppInfo interface implementation functions {{{2 */
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]