mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 10:42:11 +01:00
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...
This commit is contained in:
parent
1a1ea47126
commit
951b90f224
@ -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;
|
||||
@ -489,6 +497,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 >
|
||||
@ -532,6 +614,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;
|
||||
}
|
||||
|
||||
@ -557,7 +645,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;
|
||||
}
|
||||
@ -580,7 +673,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 >
|
||||
@ -596,7 +692,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 */
|
||||
@ -1103,6 +1202,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
|
||||
|
Loading…
x
Reference in New Issue
Block a user