mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-13 15:56:23 +01:00
appinfo: add g_app_info_set_as_last_used_for_type()
This commit also changes (maintaining compatibility) the way user-specified default applications are stored (as in, those for which g_app_info_set_as_default_for_type() has been called. We now store the default application for a content type in a new group in the mimeapps.list keyfile, and "Added Associations" tracks only the applications that have been added by the user, following a most-recently-used first order. This is useful in GtkAppChooser-like widgets to pre-select the last used application when constructing a widget. https://bugzilla.gnome.org/show_bug.cgi?id=636311
This commit is contained in:
parent
01ba7bd8e8
commit
678bcad92c
@ -1256,6 +1256,7 @@ g_app_info_delete
|
|||||||
g_app_info_reset_type_associations
|
g_app_info_reset_type_associations
|
||||||
g_app_info_set_as_default_for_type
|
g_app_info_set_as_default_for_type
|
||||||
g_app_info_set_as_default_for_extension
|
g_app_info_set_as_default_for_extension
|
||||||
|
g_app_info_set_as_last_used_for_type
|
||||||
g_app_info_add_supports_type
|
g_app_info_add_supports_type
|
||||||
g_app_info_can_remove_supports_type
|
g_app_info_can_remove_supports_type
|
||||||
g_app_info_remove_supports_type
|
g_app_info_remove_supports_type
|
||||||
|
@ -308,6 +308,33 @@ g_app_info_set_as_default_for_type (GAppInfo *appinfo,
|
|||||||
return (* iface->set_as_default_for_type) (appinfo, content_type, error);
|
return (* iface->set_as_default_for_type) (appinfo, content_type, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_app_info_set_as_last_used_for_type:
|
||||||
|
* @appinfo: a #GAppInfo.
|
||||||
|
* @content_type: the content type.
|
||||||
|
* @error: a #GError.
|
||||||
|
*
|
||||||
|
* Sets the application as the last used application for a given type.
|
||||||
|
* This will make the application appear as first in the list returned by
|
||||||
|
* #g_app_info_get_recommended_for_type, regardless of the default application
|
||||||
|
* for that content type.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE on success, %FALSE on error.
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
g_app_info_set_as_last_used_for_type (GAppInfo *appinfo,
|
||||||
|
const char *content_type,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GAppInfoIface *iface;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
|
||||||
|
g_return_val_if_fail (content_type != NULL, FALSE);
|
||||||
|
|
||||||
|
iface = G_APP_INFO_GET_IFACE (appinfo);
|
||||||
|
|
||||||
|
return (* iface->set_as_last_used_for_type) (appinfo, content_type, error);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_app_info_set_as_default_for_extension:
|
* g_app_info_set_as_default_for_extension:
|
||||||
|
@ -128,6 +128,9 @@ struct _GAppInfoIface
|
|||||||
gboolean (* do_delete) (GAppInfo *appinfo);
|
gboolean (* do_delete) (GAppInfo *appinfo);
|
||||||
const char * (* get_commandline) (GAppInfo *appinfo);
|
const char * (* get_commandline) (GAppInfo *appinfo);
|
||||||
const char * (* get_display_name) (GAppInfo *appinfo);
|
const char * (* get_display_name) (GAppInfo *appinfo);
|
||||||
|
gboolean (* set_as_last_used_for_type) (GAppInfo *appinfo,
|
||||||
|
const char *content_type,
|
||||||
|
GError **error);
|
||||||
};
|
};
|
||||||
|
|
||||||
GType g_app_info_get_type (void) G_GNUC_CONST;
|
GType g_app_info_get_type (void) G_GNUC_CONST;
|
||||||
@ -173,6 +176,10 @@ gboolean g_app_info_remove_supports_type (GAppInfo *appin
|
|||||||
gboolean g_app_info_can_delete (GAppInfo *appinfo);
|
gboolean g_app_info_can_delete (GAppInfo *appinfo);
|
||||||
gboolean g_app_info_delete (GAppInfo *appinfo);
|
gboolean g_app_info_delete (GAppInfo *appinfo);
|
||||||
|
|
||||||
|
gboolean g_app_info_set_as_last_used_for_type (GAppInfo *appinfo,
|
||||||
|
const char *content_type,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
GList * g_app_info_get_all (void);
|
GList * g_app_info_get_all (void);
|
||||||
GList * g_app_info_get_all_for_type (const char *content_type);
|
GList * g_app_info_get_all_for_type (const char *content_type);
|
||||||
GList * g_app_info_get_recommended_for_type (const gchar *content_type);
|
GList * g_app_info_get_recommended_for_type (const gchar *content_type);
|
||||||
|
@ -69,7 +69,8 @@
|
|||||||
static void g_desktop_app_info_iface_init (GAppInfoIface *iface);
|
static void g_desktop_app_info_iface_init (GAppInfoIface *iface);
|
||||||
static GList * get_all_desktop_entries_for_mime_type (const char *base_mime_type,
|
static GList * get_all_desktop_entries_for_mime_type (const char *base_mime_type,
|
||||||
const char **except,
|
const char **except,
|
||||||
gboolean include_fallback);
|
gboolean include_fallback,
|
||||||
|
char **explicit_default);
|
||||||
static void mime_info_cache_reload (const char *dir);
|
static void mime_info_cache_reload (const char *dir);
|
||||||
static gboolean g_desktop_app_info_ensure_saved (GDesktopAppInfo *info,
|
static gboolean g_desktop_app_info_ensure_saved (GDesktopAppInfo *info,
|
||||||
GError **error);
|
GError **error);
|
||||||
@ -107,6 +108,14 @@ struct _GDesktopAppInfo
|
|||||||
/* FIXME: what about StartupWMClass ? */
|
/* FIXME: what about StartupWMClass ? */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
UPDATE_MIME_NONE = 1 << 0,
|
||||||
|
UPDATE_MIME_SET_DEFAULT = 1 << 1,
|
||||||
|
UPDATE_MIME_SET_NON_DEFAULT = 1 << 2,
|
||||||
|
UPDATE_MIME_REMOVE = 1 << 3,
|
||||||
|
UPDATE_MIME_SET_LAST_USED = 1 << 4,
|
||||||
|
} UpdateMimeFlags;
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (GDesktopAppInfo, g_desktop_app_info, G_TYPE_OBJECT,
|
G_DEFINE_TYPE_WITH_CODE (GDesktopAppInfo, g_desktop_app_info, G_TYPE_OBJECT,
|
||||||
G_IMPLEMENT_INTERFACE (G_TYPE_APP_INFO,
|
G_IMPLEMENT_INTERFACE (G_TYPE_APP_INFO,
|
||||||
g_desktop_app_info_iface_init))
|
g_desktop_app_info_iface_init))
|
||||||
@ -1170,23 +1179,21 @@ ensure_dir (DirType type,
|
|||||||
static gboolean
|
static gboolean
|
||||||
update_mimeapps_list (const char *desktop_id,
|
update_mimeapps_list (const char *desktop_id,
|
||||||
const char *content_type,
|
const char *content_type,
|
||||||
gboolean add_as_default,
|
UpdateMimeFlags flags,
|
||||||
gboolean add_non_default,
|
|
||||||
gboolean remove,
|
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
char *dirname, *filename;
|
char *dirname, *filename, *string;
|
||||||
GKeyFile *key_file;
|
GKeyFile *key_file;
|
||||||
gboolean load_succeeded, res;
|
gboolean load_succeeded, res;
|
||||||
char **old_list, **list;
|
char **old_list, **list;
|
||||||
GList *system_list, *l;
|
|
||||||
gsize length, data_size;
|
gsize length, data_size;
|
||||||
char *data;
|
char *data;
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
char **content_types;
|
char **content_types;
|
||||||
|
|
||||||
/* Don't add both at start and end */
|
/* Don't add both at start and end */
|
||||||
g_assert (!(add_as_default && add_non_default));
|
g_assert (!((flags & UPDATE_MIME_SET_DEFAULT) &&
|
||||||
|
(flags & UPDATE_MIME_SET_NON_DEFAULT)));
|
||||||
|
|
||||||
dirname = ensure_dir (APP_DIR, error);
|
dirname = ensure_dir (APP_DIR, error);
|
||||||
if (!dirname)
|
if (!dirname)
|
||||||
@ -1211,6 +1218,48 @@ update_mimeapps_list (const char *desktop_id,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
content_types = g_key_file_get_keys (key_file, DEFAULT_APPLICATIONS_GROUP, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 0; content_types && content_types[k]; k++)
|
||||||
|
{
|
||||||
|
/* set as default, if requested so */
|
||||||
|
string = g_key_file_get_string (key_file,
|
||||||
|
DEFAULT_APPLICATIONS_GROUP,
|
||||||
|
content_types[k],
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (g_strcmp0 (string, desktop_id) != 0 &&
|
||||||
|
(flags & UPDATE_MIME_SET_DEFAULT))
|
||||||
|
{
|
||||||
|
g_free (string);
|
||||||
|
string = g_strdup (desktop_id);
|
||||||
|
|
||||||
|
/* add in the non-default list too, if it's not already there */
|
||||||
|
flags |= UPDATE_MIME_SET_NON_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string == NULL || desktop_id == NULL)
|
||||||
|
g_key_file_remove_key (key_file,
|
||||||
|
DEFAULT_APPLICATIONS_GROUP,
|
||||||
|
content_types[k],
|
||||||
|
NULL);
|
||||||
|
else
|
||||||
|
g_key_file_set_string (key_file,
|
||||||
|
DEFAULT_APPLICATIONS_GROUP,
|
||||||
|
content_types[k],
|
||||||
|
string);
|
||||||
|
|
||||||
|
g_free (string);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content_type)
|
||||||
|
{
|
||||||
|
/* reuse the list from above */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_strfreev (content_types);
|
||||||
content_types = g_key_file_get_keys (key_file, ADDED_ASSOCIATIONS_GROUP, NULL, NULL);
|
content_types = g_key_file_get_keys (key_file, ADDED_ASSOCIATIONS_GROUP, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1225,47 +1274,40 @@ update_mimeapps_list (const char *desktop_id,
|
|||||||
list = g_new (char *, 1 + length + 1);
|
list = g_new (char *, 1 + length + 1);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
if (add_as_default)
|
|
||||||
|
/* if we're adding a last-used hint, just put the application in front of the list */
|
||||||
|
if (flags & UPDATE_MIME_SET_LAST_USED)
|
||||||
|
{
|
||||||
|
/* avoid adding this again as non-default later */
|
||||||
|
if (flags & UPDATE_MIME_SET_NON_DEFAULT)
|
||||||
|
flags ^= UPDATE_MIME_SET_NON_DEFAULT;
|
||||||
|
|
||||||
list[i++] = g_strdup (desktop_id);
|
list[i++] = g_strdup (desktop_id);
|
||||||
|
}
|
||||||
|
|
||||||
if (old_list)
|
if (old_list)
|
||||||
{
|
{
|
||||||
for (j = 0; old_list[j] != NULL; j++)
|
for (j = 0; old_list[j] != NULL; j++)
|
||||||
{
|
{
|
||||||
if (g_strcmp0 (old_list[j], desktop_id) != 0)
|
if (g_strcmp0 (old_list[j], desktop_id) != 0)
|
||||||
list[i++] = g_strdup (old_list[j]);
|
|
||||||
else if (add_non_default)
|
|
||||||
{
|
{
|
||||||
/* If adding as non-default, and it's already in,
|
/* rewrite other entries if they're different from the new one */
|
||||||
don't change order of desktop ids */
|
list[i++] = g_strdup (old_list[j]);
|
||||||
add_non_default = FALSE;
|
}
|
||||||
|
else if (flags & UPDATE_MIME_SET_NON_DEFAULT)
|
||||||
|
{
|
||||||
|
/* we encountered an old entry which is equal to the one we're adding as non-default,
|
||||||
|
* don't change its position in the list.
|
||||||
|
*/
|
||||||
|
flags ^= UPDATE_MIME_SET_NON_DEFAULT;
|
||||||
list[i++] = g_strdup (old_list[j]);
|
list[i++] = g_strdup (old_list[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add_non_default)
|
/* add it at the end of the list */
|
||||||
{
|
if (flags & UPDATE_MIME_SET_NON_DEFAULT)
|
||||||
/* We're adding as non-default, and it wasn't already in the list,
|
|
||||||
so we add at the end. But to avoid listing the app before the
|
|
||||||
current system default (thus changing the default) we have to
|
|
||||||
add the current list of (not yet listed) apps before it. */
|
|
||||||
|
|
||||||
list[i] = NULL; /* Terminate current list so we can use it */
|
|
||||||
system_list = get_all_desktop_entries_for_mime_type (content_type, (const char **)list, FALSE);
|
|
||||||
|
|
||||||
list = g_renew (char *, list, 1 + length + g_list_length (system_list) + 1);
|
|
||||||
|
|
||||||
for (l = system_list; l != NULL; l = l->next)
|
|
||||||
{
|
|
||||||
list[i++] = l->data; /* no strdup, taking ownership */
|
|
||||||
if (g_strcmp0 (l->data, desktop_id) == 0)
|
|
||||||
add_non_default = FALSE;
|
|
||||||
}
|
|
||||||
g_list_free (system_list);
|
|
||||||
|
|
||||||
if (add_non_default)
|
|
||||||
list[i++] = g_strdup (desktop_id);
|
list[i++] = g_strdup (desktop_id);
|
||||||
}
|
|
||||||
|
|
||||||
list[i] = NULL;
|
list[i] = NULL;
|
||||||
|
|
||||||
@ -1306,7 +1348,7 @@ update_mimeapps_list (const char *desktop_id,
|
|||||||
list = g_new (char *, 1 + length + 1);
|
list = g_new (char *, 1 + length + 1);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
if (remove)
|
if (flags & UPDATE_MIME_REMOVE)
|
||||||
list[i++] = g_strdup (desktop_id);
|
list[i++] = g_strdup (desktop_id);
|
||||||
if (old_list)
|
if (old_list)
|
||||||
{
|
{
|
||||||
@ -1349,6 +1391,23 @@ update_mimeapps_list (const char *desktop_id,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
g_desktop_app_info_set_as_last_used_for_type (GAppInfo *appinfo,
|
||||||
|
const char *content_type,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GDesktopAppInfo *info = G_DESKTOP_APP_INFO (appinfo);
|
||||||
|
|
||||||
|
if (!g_desktop_app_info_ensure_saved (info, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* both add support for the content type and set as last used */
|
||||||
|
return update_mimeapps_list (info->desktop_id, content_type,
|
||||||
|
UPDATE_MIME_SET_NON_DEFAULT |
|
||||||
|
UPDATE_MIME_SET_LAST_USED,
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
g_desktop_app_info_set_as_default_for_type (GAppInfo *appinfo,
|
g_desktop_app_info_set_as_default_for_type (GAppInfo *appinfo,
|
||||||
const char *content_type,
|
const char *content_type,
|
||||||
@ -1359,7 +1418,9 @@ g_desktop_app_info_set_as_default_for_type (GAppInfo *appinfo,
|
|||||||
if (!g_desktop_app_info_ensure_saved (info, error))
|
if (!g_desktop_app_info_ensure_saved (info, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return update_mimeapps_list (info->desktop_id, content_type, TRUE, FALSE, FALSE, error);
|
return update_mimeapps_list (info->desktop_id, content_type,
|
||||||
|
UPDATE_MIME_SET_DEFAULT,
|
||||||
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1476,7 +1537,9 @@ g_desktop_app_info_add_supports_type (GAppInfo *appinfo,
|
|||||||
if (!g_desktop_app_info_ensure_saved (G_DESKTOP_APP_INFO (info), error))
|
if (!g_desktop_app_info_ensure_saved (G_DESKTOP_APP_INFO (info), error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return update_mimeapps_list (info->desktop_id, content_type, FALSE, TRUE, FALSE, error);
|
return update_mimeapps_list (info->desktop_id, content_type,
|
||||||
|
UPDATE_MIME_SET_NON_DEFAULT,
|
||||||
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -1495,7 +1558,9 @@ g_desktop_app_info_remove_supports_type (GAppInfo *appinfo,
|
|||||||
if (!g_desktop_app_info_ensure_saved (G_DESKTOP_APP_INFO (info), error))
|
if (!g_desktop_app_info_ensure_saved (G_DESKTOP_APP_INFO (info), error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return update_mimeapps_list (info->desktop_id, content_type, FALSE, FALSE, TRUE, error);
|
return update_mimeapps_list (info->desktop_id, content_type,
|
||||||
|
UPDATE_MIME_REMOVE,
|
||||||
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -1616,7 +1681,9 @@ g_desktop_app_info_delete (GAppInfo *appinfo)
|
|||||||
{
|
{
|
||||||
if (g_remove (info->filename) == 0)
|
if (g_remove (info->filename) == 0)
|
||||||
{
|
{
|
||||||
update_mimeapps_list (info->desktop_id, NULL, FALSE, FALSE, FALSE, NULL);
|
update_mimeapps_list (info->desktop_id, NULL,
|
||||||
|
UPDATE_MIME_NONE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
g_free (info->filename);
|
g_free (info->filename);
|
||||||
info->filename = NULL;
|
info->filename = NULL;
|
||||||
@ -1709,6 +1776,7 @@ g_desktop_app_info_iface_init (GAppInfoIface *iface)
|
|||||||
iface->do_delete = g_desktop_app_info_delete;
|
iface->do_delete = g_desktop_app_info_delete;
|
||||||
iface->get_commandline = g_desktop_app_info_get_commandline;
|
iface->get_commandline = g_desktop_app_info_get_commandline;
|
||||||
iface->get_display_name = g_desktop_app_info_get_display_name;
|
iface->get_display_name = g_desktop_app_info_get_display_name;
|
||||||
|
iface->set_as_last_used_for_type = g_desktop_app_info_set_as_last_used_for_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -1731,6 +1799,9 @@ app_info_in_list (GAppInfo *info,
|
|||||||
* Gets a list of recommended #GAppInfos for a given content type, i.e.
|
* Gets a list of recommended #GAppInfos for a given content type, i.e.
|
||||||
* those applications which claim to support the given content type exactly,
|
* those applications which claim to support the given content type exactly,
|
||||||
* and not by MIME type subclassing.
|
* and not by MIME type subclassing.
|
||||||
|
* Note that the first application of the list is the last used one, i.e.
|
||||||
|
* the last one for which #g_app_info_set_as_last_used_for_type has been
|
||||||
|
* called.
|
||||||
*
|
*
|
||||||
* Returns: (element-type GAppInfo) (transfer full): #GList of #GAppInfos
|
* Returns: (element-type GAppInfo) (transfer full): #GList of #GAppInfos
|
||||||
* for given @content_type or %NULL on error.
|
* for given @content_type or %NULL on error.
|
||||||
@ -1746,7 +1817,7 @@ g_app_info_get_recommended_for_type (const gchar *content_type)
|
|||||||
|
|
||||||
g_return_val_if_fail (content_type != NULL, NULL);
|
g_return_val_if_fail (content_type != NULL, NULL);
|
||||||
|
|
||||||
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL, FALSE);
|
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL, FALSE, NULL);
|
||||||
|
|
||||||
infos = NULL;
|
infos = NULL;
|
||||||
for (l = desktop_entries; l != NULL; l = l->next)
|
for (l = desktop_entries; l != NULL; l = l->next)
|
||||||
@ -1791,7 +1862,7 @@ g_app_info_get_fallback_for_type (const gchar *content_type)
|
|||||||
|
|
||||||
g_return_val_if_fail (content_type != NULL, NULL);
|
g_return_val_if_fail (content_type != NULL, NULL);
|
||||||
|
|
||||||
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL, TRUE);
|
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL, TRUE, NULL);
|
||||||
recommended_infos = g_app_info_get_recommended_for_type (content_type);
|
recommended_infos = g_app_info_get_recommended_for_type (content_type);
|
||||||
|
|
||||||
infos = NULL;
|
infos = NULL;
|
||||||
@ -1831,13 +1902,25 @@ g_app_info_get_all_for_type (const char *content_type)
|
|||||||
{
|
{
|
||||||
GList *desktop_entries, *l;
|
GList *desktop_entries, *l;
|
||||||
GList *infos;
|
GList *infos;
|
||||||
|
char *user_default = NULL;
|
||||||
GDesktopAppInfo *info;
|
GDesktopAppInfo *info;
|
||||||
|
|
||||||
g_return_val_if_fail (content_type != NULL, NULL);
|
g_return_val_if_fail (content_type != NULL, NULL);
|
||||||
|
|
||||||
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL, TRUE);
|
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL, TRUE, &user_default);
|
||||||
|
|
||||||
infos = NULL;
|
infos = NULL;
|
||||||
|
|
||||||
|
/* put the user default in front of the list, for compatibility */
|
||||||
|
if (user_default != NULL)
|
||||||
|
{
|
||||||
|
info = g_desktop_app_info_new (user_default);
|
||||||
|
|
||||||
|
if (info != NULL)
|
||||||
|
infos = g_list_prepend (infos, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (user_default);
|
||||||
|
|
||||||
for (l = desktop_entries; l != NULL; l = l->next)
|
for (l = desktop_entries; l != NULL; l = l->next)
|
||||||
{
|
{
|
||||||
char *desktop_entry = l->data;
|
char *desktop_entry = l->data;
|
||||||
@ -1872,7 +1955,9 @@ g_app_info_get_all_for_type (const char *content_type)
|
|||||||
void
|
void
|
||||||
g_app_info_reset_type_associations (const char *content_type)
|
g_app_info_reset_type_associations (const char *content_type)
|
||||||
{
|
{
|
||||||
update_mimeapps_list (NULL, content_type, FALSE, FALSE, FALSE, NULL);
|
update_mimeapps_list (NULL, content_type,
|
||||||
|
UPDATE_MIME_NONE,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1890,13 +1975,40 @@ g_app_info_get_default_for_type (const char *content_type,
|
|||||||
gboolean must_support_uris)
|
gboolean must_support_uris)
|
||||||
{
|
{
|
||||||
GList *desktop_entries, *l;
|
GList *desktop_entries, *l;
|
||||||
|
char *user_default = NULL;
|
||||||
GAppInfo *info;
|
GAppInfo *info;
|
||||||
|
|
||||||
g_return_val_if_fail (content_type != NULL, NULL);
|
g_return_val_if_fail (content_type != NULL, NULL);
|
||||||
|
|
||||||
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL, TRUE);
|
desktop_entries = get_all_desktop_entries_for_mime_type (content_type, NULL, TRUE, &user_default);
|
||||||
|
|
||||||
info = NULL;
|
info = NULL;
|
||||||
|
|
||||||
|
if (user_default != NULL)
|
||||||
|
{
|
||||||
|
info = (GAppInfo *) g_desktop_app_info_new (user_default);
|
||||||
|
|
||||||
|
if (info)
|
||||||
|
{
|
||||||
|
if (must_support_uris && !g_app_info_supports_uris (info))
|
||||||
|
{
|
||||||
|
g_object_unref (info);
|
||||||
|
info = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (user_default);
|
||||||
|
|
||||||
|
if (info != NULL)
|
||||||
|
{
|
||||||
|
g_list_free_full (desktop_entries, g_free);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pick the first from the other list that matches our URI
|
||||||
|
* requirements.
|
||||||
|
*/
|
||||||
for (l = desktop_entries; l != NULL; l = l->next)
|
for (l = desktop_entries; l != NULL; l = l->next)
|
||||||
{
|
{
|
||||||
char *desktop_entry = l->data;
|
char *desktop_entry = l->data;
|
||||||
@ -1914,8 +2026,7 @@ g_app_info_get_default_for_type (const char *content_type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_list_foreach (desktop_entries, (GFunc)g_free, NULL);
|
g_list_free_full (desktop_entries, g_free);
|
||||||
g_list_free (desktop_entries);
|
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@ -2066,6 +2177,7 @@ typedef struct {
|
|||||||
GHashTable *defaults_list_map;
|
GHashTable *defaults_list_map;
|
||||||
GHashTable *mimeapps_list_added_map;
|
GHashTable *mimeapps_list_added_map;
|
||||||
GHashTable *mimeapps_list_removed_map;
|
GHashTable *mimeapps_list_removed_map;
|
||||||
|
GHashTable *mimeapps_list_defaults_map;
|
||||||
time_t mime_info_cache_timestamp;
|
time_t mime_info_cache_timestamp;
|
||||||
time_t defaults_list_timestamp;
|
time_t defaults_list_timestamp;
|
||||||
time_t mimeapps_list_timestamp;
|
time_t mimeapps_list_timestamp;
|
||||||
@ -2318,6 +2430,7 @@ mime_info_cache_dir_init_mimeapps_list (MimeInfoCacheDir *dir)
|
|||||||
gchar *filename, **mime_types;
|
gchar *filename, **mime_types;
|
||||||
char *unaliased_type;
|
char *unaliased_type;
|
||||||
char **desktop_file_ids;
|
char **desktop_file_ids;
|
||||||
|
char *desktop_id;
|
||||||
int i;
|
int i;
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
|
|
||||||
@ -2339,6 +2452,11 @@ mime_info_cache_dir_init_mimeapps_list (MimeInfoCacheDir *dir)
|
|||||||
dir->mimeapps_list_removed_map = g_hash_table_new_full (g_str_hash, g_str_equal,
|
dir->mimeapps_list_removed_map = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
g_free, (GDestroyNotify)g_strfreev);
|
g_free, (GDestroyNotify)g_strfreev);
|
||||||
|
|
||||||
|
if (dir->mimeapps_list_defaults_map != NULL)
|
||||||
|
g_hash_table_destroy (dir->mimeapps_list_defaults_map);
|
||||||
|
dir->mimeapps_list_defaults_map = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, g_free);
|
||||||
|
|
||||||
key_file = g_key_file_new ();
|
key_file = g_key_file_new ();
|
||||||
|
|
||||||
filename = g_build_filename (dir->path, "mimeapps.list", NULL);
|
filename = g_build_filename (dir->path, "mimeapps.list", NULL);
|
||||||
@ -2403,6 +2521,28 @@ mime_info_cache_dir_init_mimeapps_list (MimeInfoCacheDir *dir)
|
|||||||
g_strfreev (mime_types);
|
g_strfreev (mime_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mime_types = g_key_file_get_keys (key_file, DEFAULT_APPLICATIONS_GROUP,
|
||||||
|
NULL, NULL);
|
||||||
|
if (mime_types != NULL)
|
||||||
|
{
|
||||||
|
for (i = 0; mime_types[i] != NULL; i++)
|
||||||
|
{
|
||||||
|
desktop_id = g_key_file_get_string (key_file,
|
||||||
|
DEFAULT_APPLICATIONS_GROUP,
|
||||||
|
mime_types[i],
|
||||||
|
NULL);
|
||||||
|
if (desktop_id == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
unaliased_type = _g_unix_content_type_unalias (mime_types[i]);
|
||||||
|
g_hash_table_replace (dir->mimeapps_list_defaults_map,
|
||||||
|
unaliased_type,
|
||||||
|
desktop_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (mime_types);
|
||||||
|
}
|
||||||
|
|
||||||
g_key_file_free (key_file);
|
g_key_file_free (key_file);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2459,6 +2599,12 @@ mime_info_cache_dir_free (MimeInfoCacheDir *dir)
|
|||||||
dir->mimeapps_list_removed_map = NULL;
|
dir->mimeapps_list_removed_map = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dir->mimeapps_list_defaults_map != NULL)
|
||||||
|
{
|
||||||
|
g_hash_table_destroy (dir->mimeapps_list_defaults_map);
|
||||||
|
dir->mimeapps_list_defaults_map = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
g_free (dir);
|
g_free (dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2637,11 +2783,13 @@ append_desktop_entry (GList *list,
|
|||||||
static GList *
|
static GList *
|
||||||
get_all_desktop_entries_for_mime_type (const char *base_mime_type,
|
get_all_desktop_entries_for_mime_type (const char *base_mime_type,
|
||||||
const char **except,
|
const char **except,
|
||||||
gboolean include_fallback)
|
gboolean include_fallback,
|
||||||
|
char **explicit_default)
|
||||||
{
|
{
|
||||||
GList *desktop_entries, *removed_entries, *list, *dir_list, *tmp;
|
GList *desktop_entries, *removed_entries, *list, *dir_list, *tmp;
|
||||||
MimeInfoCacheDir *dir;
|
MimeInfoCacheDir *dir;
|
||||||
char *mime_type;
|
char *mime_type, *default_entry = NULL;
|
||||||
|
const char *entry;
|
||||||
char **mime_types;
|
char **mime_types;
|
||||||
char **default_entries;
|
char **default_entries;
|
||||||
char **removed_associations;
|
char **removed_associations;
|
||||||
@ -2696,14 +2844,24 @@ get_all_desktop_entries_for_mime_type (const char *base_mime_type,
|
|||||||
{
|
{
|
||||||
mime_type = mime_types[i];
|
mime_type = mime_types[i];
|
||||||
|
|
||||||
/* Go through all apps listed as defaults */
|
/* Go through all apps listed in user and system dirs */
|
||||||
for (dir_list = mime_info_cache->dirs;
|
for (dir_list = mime_info_cache->dirs;
|
||||||
dir_list != NULL;
|
dir_list != NULL;
|
||||||
dir_list = dir_list->next)
|
dir_list = dir_list->next)
|
||||||
{
|
{
|
||||||
dir = dir_list->data;
|
dir = dir_list->data;
|
||||||
|
|
||||||
/* First added associations from mimeapps.list */
|
/* Pick the explicit default application */
|
||||||
|
entry = g_hash_table_lookup (dir->mimeapps_list_defaults_map, mime_type);
|
||||||
|
|
||||||
|
if (entry != NULL)
|
||||||
|
{
|
||||||
|
/* Save the default entry if it's the first one we encounter */
|
||||||
|
if (default_entry == NULL)
|
||||||
|
default_entry = g_strdup (entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then added associations from mimeapps.list */
|
||||||
default_entries = g_hash_table_lookup (dir->mimeapps_list_added_map, mime_type);
|
default_entries = g_hash_table_lookup (dir->mimeapps_list_added_map, mime_type);
|
||||||
for (j = 0; default_entries != NULL && default_entries[j] != NULL; j++)
|
for (j = 0; default_entries != NULL && default_entries[j] != NULL; j++)
|
||||||
desktop_entries = append_desktop_entry (desktop_entries, default_entries[j], removed_entries);
|
desktop_entries = append_desktop_entry (desktop_entries, default_entries[j], removed_entries);
|
||||||
@ -2736,6 +2894,11 @@ get_all_desktop_entries_for_mime_type (const char *base_mime_type,
|
|||||||
|
|
||||||
g_strfreev (mime_types);
|
g_strfreev (mime_types);
|
||||||
|
|
||||||
|
if (explicit_default != NULL)
|
||||||
|
*explicit_default = default_entry;
|
||||||
|
else
|
||||||
|
g_free (default_entry);
|
||||||
|
|
||||||
g_list_foreach (removed_entries, (GFunc)g_free, NULL);
|
g_list_foreach (removed_entries, (GFunc)g_free, NULL);
|
||||||
g_list_free (removed_entries);
|
g_list_free (removed_entries);
|
||||||
|
|
||||||
|
@ -84,6 +84,7 @@ g_app_info_launch_uris
|
|||||||
g_app_info_should_show
|
g_app_info_should_show
|
||||||
g_app_info_set_as_default_for_type
|
g_app_info_set_as_default_for_type
|
||||||
g_app_info_set_as_default_for_extension
|
g_app_info_set_as_default_for_extension
|
||||||
|
g_app_info_set_as_last_used_for_type
|
||||||
g_app_info_add_supports_type
|
g_app_info_add_supports_type
|
||||||
g_app_info_can_remove_supports_type
|
g_app_info_can_remove_supports_type
|
||||||
g_app_info_remove_supports_type
|
g_app_info_remove_supports_type
|
||||||
|
@ -242,6 +242,56 @@ test_fallback (void)
|
|||||||
g_object_unref (info2);
|
g_object_unref (info2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_last_used (void)
|
||||||
|
{
|
||||||
|
GList *applications;
|
||||||
|
GAppInfo *info1, *info2, *default_app;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
info1 = create_app_info ("Test1");
|
||||||
|
info2 = create_app_info ("Test2");
|
||||||
|
|
||||||
|
g_app_info_set_as_default_for_type (info1, "application/x-test", &error);
|
||||||
|
g_assert (error == NULL);
|
||||||
|
|
||||||
|
g_app_info_add_supports_type (info2, "application/x-test", &error);
|
||||||
|
g_assert (error == NULL);
|
||||||
|
|
||||||
|
applications = g_app_info_get_recommended_for_type ("application/x-test");
|
||||||
|
g_assert (g_list_length (applications) == 2);
|
||||||
|
|
||||||
|
/* the first should be the default app now */
|
||||||
|
g_assert (g_app_info_equal (g_list_nth_data (applications, 0), info1));
|
||||||
|
g_assert (g_app_info_equal (g_list_nth_data (applications, 1), info2));
|
||||||
|
|
||||||
|
g_list_free_full (applications, g_object_unref);
|
||||||
|
|
||||||
|
g_app_info_set_as_last_used_for_type (info2, "application/x-test", &error);
|
||||||
|
g_assert (error == NULL);
|
||||||
|
|
||||||
|
applications = g_app_info_get_recommended_for_type ("application/x-test");
|
||||||
|
g_assert (g_list_length (applications) == 2);
|
||||||
|
|
||||||
|
default_app = g_app_info_get_default_for_type ("application/x-test", FALSE);
|
||||||
|
g_assert (g_app_info_equal (default_app, info1));
|
||||||
|
|
||||||
|
/* the first should be the other app now */
|
||||||
|
g_assert (g_app_info_equal (g_list_nth_data (applications, 0), info2));
|
||||||
|
g_assert (g_app_info_equal (g_list_nth_data (applications, 1), info1));
|
||||||
|
|
||||||
|
g_list_free_full (applications, g_object_unref);
|
||||||
|
|
||||||
|
g_app_info_reset_type_associations ("application/x-test");
|
||||||
|
|
||||||
|
g_app_info_delete (info1);
|
||||||
|
g_app_info_delete (info2);
|
||||||
|
|
||||||
|
g_object_unref (info1);
|
||||||
|
g_object_unref (info2);
|
||||||
|
g_object_unref (default_app);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cleanup_dir_recurse (GFile *parent, GFile *root)
|
cleanup_dir_recurse (GFile *parent, GFile *root)
|
||||||
{
|
{
|
||||||
@ -319,6 +369,7 @@ main (int argc,
|
|||||||
g_test_add_func ("/desktop-app-info/delete", test_delete);
|
g_test_add_func ("/desktop-app-info/delete", test_delete);
|
||||||
g_test_add_func ("/desktop-app-info/default", test_default);
|
g_test_add_func ("/desktop-app-info/default", test_default);
|
||||||
g_test_add_func ("/desktop-app-info/fallback", test_fallback);
|
g_test_add_func ("/desktop-app-info/fallback", test_fallback);
|
||||||
|
g_test_add_func ("/desktop-app-info/lastused", test_last_used);
|
||||||
|
|
||||||
result = g_test_run ();
|
result = g_test_run ();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user