+2008-02-21 David Zeuthen <davidz@redhat.com>
+
+ * glocalfileinfo.c: (_g_local_file_info_get):
+ * gcontenttype.c:
+ (g_content_type_get_icon): Implement this function by
+ moving bits from glocalfileinfo.c
+ (g_content_type_get_description): Unalias before getting
+ description (#517687)
+
+ * gfile.c: (g_file_class_init),
+ (g_file_query_filesystem_info_async),
+ (g_file_query_filesystem_info_finish),
+ (query_filesystem_info_data_free),
+ (query_filesystem_info_async_thread),
+ (g_file_real_query_filesystem_info_async),
+ (g_file_real_query_filesystem_info_finish):
+ * gfile.h: Implement async version of
+ g_file_query_filesystem_info()
+
+ * gfileinfo.h: Add new attributes for filesystem::use-preview
+
+ * gio.symbols: Update
+
+ * gthemedicon.c: (g_themed_icon_append_name):
+ * gthemedicon.h: Add new new convenience function.
+
+ * gunionvolumemonitor.c: (g_union_volume_monitor_dispose),
+ (get_mounts), (get_volumes), (get_connected_drives),
+ (get_volume_for_uuid), (get_mount_for_uuid),
+ (g_union_volume_monitor_init), (populate_union_monitor),
+ (g_volume_monitor_get), (_g_mount_get_for_mount_path),
+ (g_volume_monitor_adopt_orphan_mount):
+ * gvolumemonitor.c:
+ * gvolumemonitor.h: Use recursive locks so it's safe for volume
+ monitor implementations to call into the main volume monitor. Also
+ separate object initialization and volume monitor initialization
+ such that non-native volume monitors can properly adopt their
+ mounts away.
+
2008-02-21 Alexander Larsson <alexl@redhat.com>
* gfile.c:
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
#include <string.h>
#include <stdio.h>
#include "gcontenttypeprivate.h"
+#include "gthemedicon.h"
#include "glibintl.h"
#include "gioalias.h"
g_return_val_if_fail (type != NULL, NULL);
G_LOCK (gio_xdgmime);
+ type = xdg_mime_unalias_mime_type (type);
+
if (type_comment_cache == NULL)
type_comment_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
GIcon *
g_content_type_get_icon (const char *type)
{
+ char *mimetype_icon, *generic_mimetype_icon, *p;
+ char *icon_names[2];
+ GThemedIcon *themed_icon;
+
g_return_val_if_fail (type != NULL, NULL);
-
- /* TODO: Implement */
- return NULL;
+
+ mimetype_icon = g_strdup (type);
+
+ while ((p = strchr (mimetype_icon, '/')) != NULL)
+ *p = '-';
+
+ p = strchr (type, '/');
+ if (p == NULL)
+ p = type + strlen (type);
+
+ generic_mimetype_icon = g_malloc (p - type + strlen ("-x-generic") + 1);
+ memcpy (generic_mimetype_icon, type, p - type);
+ memcpy (generic_mimetype_icon + (p - type), "-x-generic", strlen ("-x-generic"));
+ generic_mimetype_icon[(p - type) + strlen ("-x-generic")] = 0;
+
+ icon_names[0] = mimetype_icon;
+ icon_names[1] = generic_mimetype_icon;
+
+ themed_icon = g_themed_icon_new_from_names (icon_names, 2);
+
+ g_free (mimetype_icon);
+ g_free (generic_mimetype_icon);
+
+ return G_ICON (themed_icon);
}
/**
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
static GFileInfo * g_file_real_query_info_finish (GFile *file,
GAsyncResult *res,
GError **error);
+static void g_file_real_query_filesystem_info_async (GFile *file,
+ const char *attributes,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+static GFileInfo * g_file_real_query_filesystem_info_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error);
static void g_file_real_enumerate_children_async (GFile *file,
const char *attributes,
GFileQueryInfoFlags flags,
iface->set_display_name_finish = g_file_real_set_display_name_finish;
iface->query_info_async = g_file_real_query_info_async;
iface->query_info_finish = g_file_real_query_info_finish;
+ iface->query_filesystem_info_async = g_file_real_query_filesystem_info_async;
+ iface->query_filesystem_info_finish = g_file_real_query_filesystem_info_finish;
iface->set_attributes_async = g_file_real_set_attributes_async;
iface->set_attributes_finish = g_file_real_set_attributes_finish;
iface->read_async = g_file_real_read_async;
return (* iface->query_filesystem_info) (file, attributes, cancellable, error);
}
+/**
+ * g_file_query_filesystem_info_async:
+ * @file: input #GFile.
+ * @attributes: an attribute query string.
+ * @io_priority: the <link linkend="io-priority">I/O priority</link>
+ * of the request.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: the data to pass to callback function
+ *
+ * Asynchronously gets the requested information about the filesystem
+ * that the specified @file is on. The result is a #GFileInfo object
+ * that contains key-value attributes (such as type or size for the
+ * file).
+ *
+ * For more details, see g_file_query_filesystem_info() which is the
+ * synchronous version of this call.
+ *
+ * When the operation is finished, @callback will be called. You can
+ * then call g_file_query_info_finish() to get the result of the
+ * operation.
+ **/
+void
+g_file_query_filesystem_info_async (GFile *file,
+ const char *attributes,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GFileIface *iface;
+
+ g_return_if_fail (G_IS_FILE (file));
+
+ iface = G_FILE_GET_IFACE (file);
+ (* iface->query_filesystem_info_async) (file,
+ attributes,
+ io_priority,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * g_file_query_filesystem_info_finish:
+ * @file: input #GFile.
+ * @res: a #GAsyncResult.
+ * @error: a #GError.
+ *
+ * Finishes an asynchronous filesystem info query. See
+ * g_file_query_filesystem_info_async().
+ *
+ * Returns: #GFileInfo for given @file or %NULL on error.
+ **/
+GFileInfo *
+g_file_query_filesystem_info_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
+{
+ GFileIface *iface;
+
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
+
+ if (G_IS_SIMPLE_ASYNC_RESULT (res))
+ {
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+ }
+
+ iface = G_FILE_GET_IFACE (file);
+ return (* iface->query_filesystem_info_finish) (file, res, error);
+}
+
/**
* g_file_find_enclosing_mount:
* @file: input #GFile.
return NULL;
}
+typedef struct {
+ char *attributes;
+ GFileInfo *info;
+} QueryFilesystemInfoAsyncData;
+
+static void
+query_filesystem_info_data_free (QueryFilesystemInfoAsyncData *data)
+{
+ if (data->info)
+ g_object_unref (data->info);
+ g_free (data->attributes);
+ g_free (data);
+}
+
+static void
+query_filesystem_info_async_thread (GSimpleAsyncResult *res,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ GError *error = NULL;
+ QueryFilesystemInfoAsyncData *data;
+ GFileInfo *info;
+
+ data = g_simple_async_result_get_op_res_gpointer (res);
+
+ info = g_file_query_filesystem_info (G_FILE (object), data->attributes, cancellable, &error);
+
+ if (info == NULL)
+ {
+ g_simple_async_result_set_from_error (res, error);
+ g_error_free (error);
+ }
+ else
+ data->info = info;
+}
+
+static void
+g_file_real_query_filesystem_info_async (GFile *file,
+ const char *attributes,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ QueryFilesystemInfoAsyncData *data;
+
+ data = g_new0 (QueryFilesystemInfoAsyncData, 1);
+ data->attributes = g_strdup (attributes);
+
+ res = g_simple_async_result_new (G_OBJECT (file), callback, user_data, g_file_real_query_filesystem_info_async);
+ g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify)query_filesystem_info_data_free);
+
+ g_simple_async_result_run_in_thread (res, query_filesystem_info_async_thread, io_priority, cancellable);
+ g_object_unref (res);
+}
+
+static GFileInfo *
+g_file_real_query_filesystem_info_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ QueryFilesystemInfoAsyncData *data;
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_query_filesystem_info_async);
+
+ data = g_simple_async_result_get_op_res_gpointer (simple);
+ if (data->info)
+ return g_object_ref (data->info);
+
+ return NULL;
+}
+
typedef struct {
char *attributes;
GFileQueryInfoFlags flags;
* @query_info_async: Asynchronously gets the #GFileInfo for a #GFile.
* @query_info_finish: Finishes an asynchronous query info operation.
* @query_filesystem_info: Gets a #GFileInfo for the file system #GFile is on.
- * @_query_filesystem_info_async: Asynchronously gets a #GFileInfo for the file system #GFile is on.
- * @_query_filesystem_info_finish: Finishes asynchronously getting the file system info.
+ * @query_filesystem_info_async: Asynchronously gets a #GFileInfo for the file system #GFile is on.
+ * @query_filesystem_info_finish: Finishes asynchronously getting the file system info.
* @find_enclosing_mount: Gets a #GMount for the #GFile.
* @find_enclosing_mount_async: Asynchronously gets the #GMount for a #GFile.
* @find_enclosing_mount_finish: Finishes asynchronously getting the volume.
const char *attributes,
GCancellable *cancellable,
GError **error);
- void (*_query_filesystem_info_async) (void);
- void (*_query_filesystem_info_finish) (void);
+ void (*query_filesystem_info_async) (GFile *file,
+ const char *attributes,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ GFileInfo * (*query_filesystem_info_finish) (GFile *file,
+ GAsyncResult *res,
+ GError **error);
GMount * (*find_enclosing_mount)(GFile *file,
GCancellable *cancellable,
const char *attributes,
GCancellable *cancellable,
GError **error);
+void g_file_query_filesystem_info_async (GFile *file,
+ const char *attributes,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GFileInfo * g_file_query_filesystem_info_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error);
GMount * g_file_find_enclosing_mount (GFile *file,
GCancellable *cancellable,
GError **error);
G_FILE_TYPE_MOUNTABLE
} GFileType;
+/**
+ * GFilesystemPreviewType:
+ * @G_FILESYSTEM_PREVIEW_TYPE_IF_ALWAYS: Only preview files if user has explicitly requested it.
+ * @G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL: Preview files if user has requested preview of "local" files.
+ * @G_FILESYSTEM_PREVIEW_TYPE_NEVER: Never preview files.
+ *
+ * Indicates a hint from the file system whether files should be
+ * previewed in a file manager. Returned as the value of the key
+ * #G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW.
+ **/
+typedef enum {
+ G_FILESYSTEM_PREVIEW_TYPE_IF_ALWAYS = 0,
+ G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL,
+ G_FILESYSTEM_PREVIEW_TYPE_NEVER
+} GFilesystemPreviewType;
+
/* Common Attributes: */
/**
* G_FILE_ATTRIBUTE_STANDARD_TYPE:
**/
#define G_FILE_ATTRIBUTE_FILESYSTEM_READONLY "filesystem::readonly" /* boolean */
+/**
+ * G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW:
+ *
+ * A key in the "filesystem" namespace for hinting a file manager
+ * application whether it should preview (e.g. thumbnail) files on the
+ * file system. The value for this key contain a
+ * #GFilesystemPreviewType.
+ **/
+#define G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW "filesystem::use-preview" /* uint32 (GFilesystemPreviewType) */
+
/**
* G_FILE_ATTRIBUTE_GVFS_BACKEND:
*
g_file_query_info_async
g_file_query_info_finish
g_file_query_filesystem_info
+g_file_query_filesystem_info_async
+g_file_query_filesystem_info_finish
g_file_find_enclosing_mount
g_file_find_enclosing_mount_async
g_file_find_enclosing_mount_finish
g_themed_icon_new_with_default_fallbacks
g_themed_icon_new_from_names
g_themed_icon_get_names
+g_themed_icon_append_name
#endif
#endif
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
if (g_file_attribute_matcher_matches (attribute_matcher,
G_FILE_ATTRIBUTE_STANDARD_ICON))
{
- char *mimetype_icon, *generic_mimetype_icon, *type_icon, *p;
- char *icon_names[3];
GIcon *icon;
- int i;
- mimetype_icon = g_strdup (content_type);
-
- while ((p = strchr (mimetype_icon, '/')) != NULL)
- *p = '-';
-
- p = strchr (content_type, '/');
- if (p == NULL)
- p = content_type + strlen (content_type);
-
- generic_mimetype_icon = g_malloc (p - content_type + strlen ("-x-generic") + 1);
- memcpy (generic_mimetype_icon, content_type, p - content_type);
- memcpy (generic_mimetype_icon + (p - content_type), "-x-generic", strlen ("-x-generic"));
- generic_mimetype_icon[(p - content_type) + strlen ("-x-generic")] = 0;
-
- /* TODO: Special case desktop dir? That could be expensive with xdg dirs... */
- if (strcmp (path, g_get_home_dir ()) == 0)
- type_icon = "user-home";
- else if (S_ISDIR (statbuf.st_mode))
- type_icon = "folder";
- else if (statbuf.st_mode & S_IXUSR)
- type_icon = "application-x-executable";
- else
- type_icon = "text-x-generic";
-
- i = 0;
- icon_names[i++] = mimetype_icon;
- icon_names[i++] = generic_mimetype_icon;
- if (strcmp (generic_mimetype_icon, type_icon) != 0 &&
- strcmp (mimetype_icon, type_icon) != 0)
- icon_names[i++] = type_icon;
-
- icon = g_themed_icon_new_from_names (icon_names, i);
- g_file_info_set_icon (info, icon);
-
- g_object_unref (icon);
- g_free (mimetype_icon);
- g_free (generic_mimetype_icon);
+ icon = g_content_type_get_icon (content_type);
+ if (icon != NULL)
+ {
+ if (G_IS_THEMED_ICON (icon))
+ {
+ const char *type_icon;
+
+ /* TODO: Special case desktop dir? That could be expensive with xdg dirs... */
+ if (strcmp (path, g_get_home_dir ()) == 0)
+ type_icon = "user-home";
+ else if (S_ISDIR (statbuf.st_mode))
+ type_icon = "folder";
+ else if (statbuf.st_mode & S_IXUSR)
+ type_icon = "application-x-executable";
+ else
+ type_icon = "text-x-generic";
+
+ g_themed_icon_append_name (G_THEMED_ICON (icon), type_icon);
+ }
+
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ }
}
g_free (content_type);
return (const char * const *)icon->names;
}
+/**
+ * g_themed_icon_append_name:
+ * @icon: a #GThemedIcon
+ * @iconname: name of icon to append to list of icons from within @icon.
+ *
+ * Append a name to the list of icons from within @icon.
+ */
+void
+g_themed_icon_append_name (GThemedIcon *icon, const char *iconname)
+{
+ guint num_names;
+ char **new_names;
+
+ g_return_if_fail (G_IS_THEMED_ICON (icon));
+ g_return_if_fail (iconname != NULL);
+
+ num_names = g_strv_length (icon->names);
+ icon->names = g_realloc (icon->names, sizeof (char*) * (num_names + 2));
+ icon->names[num_names] = g_strdup (iconname);
+ icon->names[num_names + 1] = NULL;
+}
+
static guint
g_themed_icon_hash (GIcon *icon)
{
GIcon *g_themed_icon_new (const char *iconname);
GIcon *g_themed_icon_new_with_default_fallbacks (const char *iconname);
GIcon *g_themed_icon_new_from_names (char **iconnames, int len);
+void g_themed_icon_append_name (GThemedIcon *icon, const char *iconname);
const char * const *g_themed_icon_get_names (GThemedIcon *icon);
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
#define g_union_volume_monitor_get_type _g_union_volume_monitor_get_type
G_DEFINE_TYPE (GUnionVolumeMonitor, g_union_volume_monitor, G_TYPE_VOLUME_MONITOR);
+static GStaticRecMutex the_volume_monitor_mutex = G_STATIC_REC_MUTEX_INIT;
-G_LOCK_DEFINE_STATIC(the_volume_monitor);
static GUnionVolumeMonitor *the_volume_monitor = NULL;
static void
monitor = G_UNION_VOLUME_MONITOR (object);
- G_LOCK (the_volume_monitor);
+ g_static_rec_mutex_lock (&the_volume_monitor_mutex);
the_volume_monitor = NULL;
- G_UNLOCK (the_volume_monitor);
+ g_static_rec_mutex_unlock (&the_volume_monitor_mutex);
if (G_OBJECT_CLASS (g_union_volume_monitor_parent_class)->dispose)
(*G_OBJECT_CLASS (g_union_volume_monitor_parent_class)->dispose) (object);
res = NULL;
- G_LOCK (the_volume_monitor);
+ g_static_rec_mutex_lock (&the_volume_monitor_mutex);
for (l = monitor->monitors; l != NULL; l = l->next)
{
res = g_list_concat (res, g_volume_monitor_get_mounts (child_monitor));
}
- G_UNLOCK (the_volume_monitor);
+ g_static_rec_mutex_unlock (&the_volume_monitor_mutex);
return res;
}
res = NULL;
- G_LOCK (the_volume_monitor);
+ g_static_rec_mutex_lock (&the_volume_monitor_mutex);
for (l = monitor->monitors; l != NULL; l = l->next)
{
res = g_list_concat (res, g_volume_monitor_get_volumes (child_monitor));
}
- G_UNLOCK (the_volume_monitor);
+ g_static_rec_mutex_unlock (&the_volume_monitor_mutex);
return res;
}
res = NULL;
- G_LOCK (the_volume_monitor);
+ g_static_rec_mutex_lock (&the_volume_monitor_mutex);
for (l = monitor->monitors; l != NULL; l = l->next)
{
res = g_list_concat (res, g_volume_monitor_get_connected_drives (child_monitor));
}
- G_UNLOCK (the_volume_monitor);
+ g_static_rec_mutex_unlock (&the_volume_monitor_mutex);
return res;
}
volume = NULL;
- G_LOCK (the_volume_monitor);
+ g_static_rec_mutex_lock (&the_volume_monitor_mutex);
for (l = monitor->monitors; l != NULL; l = l->next)
{
}
- G_UNLOCK (the_volume_monitor);
+ g_static_rec_mutex_unlock (&the_volume_monitor_mutex);
return volume;
}
mount = NULL;
- G_LOCK (the_volume_monitor);
+ g_static_rec_mutex_lock (&the_volume_monitor_mutex);
for (l = monitor->monitors; l != NULL; l = l->next)
{
}
- G_UNLOCK (the_volume_monitor);
+ g_static_rec_mutex_unlock (&the_volume_monitor_mutex);
return mount;
}
static void
g_union_volume_monitor_init (GUnionVolumeMonitor *union_monitor)
+{
+}
+
+static void
+populate_union_monitor (GUnionVolumeMonitor *union_monitor)
{
GVolumeMonitor *monitor;
GNativeVolumeMonitorClass *native_class;
{
GVolumeMonitor *vm;
- G_LOCK (the_volume_monitor);
+ g_static_rec_mutex_lock (&the_volume_monitor_mutex);
if (the_volume_monitor)
vm = G_VOLUME_MONITOR (g_object_ref (the_volume_monitor));
else
{
the_volume_monitor = g_union_volume_monitor_new ();
+ populate_union_monitor (the_volume_monitor);
vm = G_VOLUME_MONITOR (the_volume_monitor);
}
- G_UNLOCK (the_volume_monitor);
+ g_static_rec_mutex_unlock (&the_volume_monitor_mutex);
return vm;
}
if (klass->get_mount_for_mount_path)
{
- G_LOCK (the_volume_monitor);
+ g_static_rec_mutex_lock (&the_volume_monitor_mutex);
mount = klass->get_mount_for_mount_path (mount_path, cancellable);
- G_UNLOCK (the_volume_monitor);
+ g_static_rec_mutex_unlock (&the_volume_monitor_mutex);
}
/* TODO: How do we know this succeeded? Keep in mind that the native
volume = NULL;
- /* TODO: nasty locking issues because current VM's don't emit signals in idle */
-
- /*G_LOCK (the_volume_monitor);*/
+ g_static_rec_mutex_lock (&the_volume_monitor_mutex);
for (l = the_volume_monitor->monitors; l != NULL; l = l->next)
{
}
}
- /*G_UNLOCK (the_volume_monitor);*/
+ g_static_rec_mutex_unlock (&the_volume_monitor_mutex);
return volume;
}
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.