[Xfce4-commits] <thunar:nick/new-shortcuts-pane-model> Add ThunarDevice and ThunarDeviceMonitor.
Nick Schermer
noreply at xfce.org
Sun Oct 7 02:10:02 CEST 2012
Updating branch refs/heads/nick/new-shortcuts-pane-model
to a0f743d61115cf90a48d6273f9b569e2b7dad63f (commit)
from e96bd793fbed41667d3fd8bbfc2ed231af71559d (commit)
commit a0f743d61115cf90a48d6273f9b569e2b7dad63f
Author: Nick Schermer <nick at xfce.org>
Date: Sun Oct 7 00:10:30 2012 +0200
Add ThunarDevice and ThunarDeviceMonitor.
This is an shell around GVolumeMonitor and GVolume/GMount and
possibly in the future GDrive. The idea is that the models
and views don't need to know what type they handle.
If a volume/drive/mount needs to be visible to the user, it is
added with device-added, if something changed, device-removed is
triggered and when the device need to be invisible or is removed
device-removed is called.
It also takes care of the mount/unmount/eject feature, independent of
the type.
thunar/Makefile.am | 4 +
thunar/thunar-device-monitor.c | 639 ++++++++++++++++++++++++++++++++++++
thunar/thunar-device-monitor.h | 44 +++
thunar/thunar-device.c | 711 ++++++++++++++++++++++++++++++++++++++++
thunar/thunar-device.h | 88 +++++
5 files changed, 1486 insertions(+), 0 deletions(-)
diff --git a/thunar/Makefile.am b/thunar/Makefile.am
index 3bafe9d..bc12573 100644
--- a/thunar/Makefile.am
+++ b/thunar/Makefile.am
@@ -71,6 +71,10 @@ thunar_SOURCES = \
thunar-details-view.h \
thunar-dialogs.c \
thunar-dialogs.h \
+ thunar-device.c \
+ thunar-device.h \
+ thunar-device-monitor.c \
+ thunar-device-monitor.h \
thunar-dnd.c \
thunar-dnd.h \
thunar-emblem-chooser.c \
diff --git a/thunar/thunar-device-monitor.c b/thunar/thunar-device-monitor.c
new file mode 100644
index 0000000..c70ff7a
--- /dev/null
+++ b/thunar/thunar-device-monitor.c
@@ -0,0 +1,639 @@
+/*-
+ * Copyright (c) 2009-2010 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2012 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gio/gio.h>
+#ifdef HAVE_GIO_UNIX
+#include <gio/gunixmounts.h>
+#endif
+
+#include <thunar/thunar-device-monitor.h>
+#include <thunar/thunar-private.h>
+
+
+
+/* signal identifiers */
+enum
+{
+ DEVICE_ADDED,
+ DEVICE_REMOVED,
+ DEVICE_CHANGED,
+ LAST_SIGNAL
+};
+
+
+
+static void thunar_device_monitor_finalize (GObject *object);
+static void thunar_device_monitor_volume_added (GVolumeMonitor *volume_monitor,
+ GVolume *volume,
+ ThunarDeviceMonitor *monitor);
+static void thunar_device_monitor_volume_removed (GVolumeMonitor *volume_monitor,
+ GVolume *volume,
+ ThunarDeviceMonitor *monitor);
+static void thunar_device_monitor_volume_changed (GVolumeMonitor *volume_monitor,
+ GVolume *volume,
+ ThunarDeviceMonitor *monitor);
+static void thunar_device_monitor_mount_added (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ ThunarDeviceMonitor *monitor);
+static void thunar_device_monitor_mount_removed (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ ThunarDeviceMonitor *monitor);
+static void thunar_device_monitor_mount_changed (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ ThunarDeviceMonitor *monitor);
+
+
+
+struct _ThunarDeviceMonitorClass
+{
+ GObjectClass __parent__;
+
+ /* signals */
+ void (*device_added) (ThunarDeviceMonitor *monitor,
+ ThunarDevice *device);
+ void (*device_removed) (ThunarDeviceMonitor *monitor,
+ ThunarDevice *device);
+ void (*device_changed) (ThunarDeviceMonitor *monitor,
+ ThunarDevice *device);
+};
+
+struct _ThunarDeviceMonitor
+{
+ GObject __parent__;
+
+ GVolumeMonitor *volume_monitor;
+
+ /* GVolume/GMount -> ThunarDevice */
+ GHashTable *devices;
+
+ GList *hidden_volumes;
+};
+
+struct _ThunarDevice
+{
+
+};
+
+
+
+static guint device_monitor_signals[LAST_SIGNAL];
+
+
+
+G_DEFINE_TYPE (ThunarDeviceMonitor, thunar_device_monitor, G_TYPE_OBJECT)
+
+
+
+static void
+thunar_device_monitor_class_init (ThunarDeviceMonitorClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = thunar_device_monitor_finalize;
+
+ device_monitor_signals[DEVICE_ADDED] =
+ g_signal_new (I_("device-added"),
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ThunarDeviceMonitorClass, device_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ device_monitor_signals[DEVICE_REMOVED] =
+ g_signal_new (I_("device-removed"),
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ThunarDeviceMonitorClass, device_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ device_monitor_signals[DEVICE_CHANGED] =
+ g_signal_new (I_("device-changed"),
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ThunarDeviceMonitorClass, device_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+}
+
+
+
+static void
+thunar_device_monitor_init (ThunarDeviceMonitor *monitor)
+{
+ GList *list;
+ GList *lp;
+
+ /* table for GVolume/GMount (key) -> ThunarDevice (value) */
+ monitor->devices = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, g_object_unref);
+
+ /* gio volume monitor */
+ monitor->volume_monitor = g_volume_monitor_get ();
+
+ /* load all volumes */
+ list = g_volume_monitor_get_volumes (monitor->volume_monitor);
+ for (lp = list; lp != NULL; lp = lp->next)
+ {
+ thunar_device_monitor_volume_added (monitor->volume_monitor, lp->data, monitor);
+ g_object_unref (G_OBJECT (lp->data));
+ }
+ g_list_free (list);
+
+ /* load all mount */
+ list = g_volume_monitor_get_mounts (monitor->volume_monitor);
+ for (lp = list; lp != NULL; lp = lp->next)
+ {
+ thunar_device_monitor_mount_added (monitor->volume_monitor, lp->data, monitor);
+ g_object_unref (G_OBJECT (lp->data));
+ }
+ g_list_free (list);
+
+ /* watch changes */
+ g_signal_connect (monitor->volume_monitor, "volume-added", G_CALLBACK (thunar_device_monitor_volume_added), monitor);
+ g_signal_connect (monitor->volume_monitor, "volume-removed", G_CALLBACK (thunar_device_monitor_volume_removed), monitor);
+ g_signal_connect (monitor->volume_monitor, "volume-changed", G_CALLBACK (thunar_device_monitor_volume_changed), monitor);
+ g_signal_connect (monitor->volume_monitor, "mount-added", G_CALLBACK (thunar_device_monitor_mount_added), monitor);
+ g_signal_connect (monitor->volume_monitor, "mount-removed", G_CALLBACK (thunar_device_monitor_mount_removed), monitor);
+ g_signal_connect (monitor->volume_monitor, "mount-changed", G_CALLBACK (thunar_device_monitor_mount_changed), monitor);
+}
+
+
+
+static void
+thunar_device_monitor_finalize (GObject *object)
+{
+ ThunarDeviceMonitor *monitor = THUNAR_DEVICE_MONITOR (object);
+
+ /* detatch from the monitor */
+ g_signal_handlers_disconnect_matched (monitor->volume_monitor, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, monitor);
+ g_object_unref (monitor->volume_monitor);
+
+ /* clear list of devices */
+ g_hash_table_destroy (monitor->devices);
+
+ /* clear list of hidden volumes */
+ g_list_free_full (monitor->hidden_volumes, g_object_unref);
+
+ (*G_OBJECT_CLASS (thunar_device_monitor_parent_class)->finalize) (object);
+}
+
+
+
+#ifdef HAVE_GIO_UNIX
+static gboolean
+thunar_device_monitor_mount_is_internal (GMount *mount)
+{
+ const gchar *point_mount_path;
+ gboolean is_internal = FALSE;
+ GFile *root;
+ GList *lp;
+ GList *mount_points;
+ gchar *mount_path;
+
+ _thunar_return_val_if_fail (G_IS_MOUNT (mount), FALSE);
+
+ /* determine the mount path */
+ root = g_mount_get_root (mount);
+ mount_path = g_file_get_path (root);
+ g_object_unref (root);
+
+ /* assume non-internal if we cannot determine the path */
+ if (mount_path == NULL)
+ return FALSE;
+
+ if (g_unix_is_mount_path_system_internal (mount_path))
+ {
+ /* mark as internal */
+ is_internal = TRUE;
+ }
+ else
+ {
+ /* get a list of all mount points */
+ mount_points = g_unix_mount_points_get (NULL);
+
+ /* search for the mount point associated with the mount entry */
+ for (lp = mount_points; !is_internal && lp != NULL; lp = lp->next)
+ {
+ point_mount_path = g_unix_mount_point_get_mount_path (lp->data);
+
+ /* check if this is the mount point we are looking for */
+ if (g_strcmp0 (mount_path, point_mount_path) == 0)
+ {
+ /* mark as internal if the user cannot mount this device */
+ if (!g_unix_mount_point_is_user_mountable (lp->data))
+ is_internal = TRUE;
+ }
+
+ /* free the mount point, we no longer need it */
+ g_unix_mount_point_free (lp->data);
+ }
+
+ /* free the mount point list */
+ g_list_free (mount_points);
+ }
+
+ g_free (mount_path);
+
+ return is_internal;
+}
+#endif
+
+
+
+static gboolean
+thunar_device_monitor_has_location (ThunarDeviceMonitor *monitor,
+ GFile *location)
+{
+
+ _thunar_return_val_if_fail (G_IS_FILE (location), FALSE);
+ _thunar_return_val_if_fail (THUNAR_IS_DEVICE_MONITOR (monitor), FALSE);
+
+ return FALSE;
+}
+
+
+
+static gboolean
+thunar_device_monitor_mount_is_hidden (GMount *mount,
+ ThunarDeviceMonitor *monitor)
+{
+ GVolume *volume;
+ GFile *location;
+
+ _thunar_return_val_if_fail (G_IS_MOUNT (mount), TRUE);
+ _thunar_return_val_if_fail (THUNAR_IS_DEVICE_MONITOR (monitor), TRUE);
+
+ /* never show shadowed mounts */
+ if (g_mount_is_shadowed (mount))
+ return TRUE;
+
+ /* skip mounts with a volume, we prefer a volume as device */
+ volume = g_mount_get_volume (mount);
+ if (volume != NULL)
+ {
+ g_object_unref (volume);
+ return TRUE;
+ }
+
+ location = g_mount_get_root (mount);
+
+ /* skip ghoto locations, since those also have a volume
+ * and igore locations already in the device list */
+ if (g_file_has_uri_scheme (location, "gphoto2")
+ || thunar_device_monitor_has_location (monitor, location))
+ {
+ g_object_unref (location);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+static gboolean
+thunar_device_monitor_volume_is_visible (GVolume *volume)
+{
+ gboolean can_eject = FALSE;
+ gboolean can_mount = FALSE;
+ gboolean can_unmount = FALSE;
+ gboolean is_removable = FALSE;
+ gboolean is_internal = FALSE;
+ GDrive *drive;
+ GMount *mount;
+
+ _thunar_return_val_if_fail (G_IS_VOLUME (volume), TRUE);
+
+ /* determine the mount for the volume (if it is mounted at all) */
+ mount = g_volume_get_mount (volume);
+ if (mount != NULL)
+ {
+#ifdef HAVE_GIO_UNIX
+ is_internal = thunar_device_monitor_mount_is_internal (mount);
+#endif
+
+ /* check if the volume can be unmounted */
+ can_unmount = g_mount_can_unmount (mount);
+
+ /* release the mount */
+ g_object_unref (mount);
+ }
+
+ /* don't show internal volumes */
+ if (is_internal)
+ return FALSE;
+
+ /* check if the volume can be ejected */
+ can_eject = g_volume_can_eject (volume);
+
+ /* determine the drive for the volume */
+ drive = g_volume_get_drive (volume);
+ if (drive != NULL)
+ {
+ /* check if the drive media can be removed */
+ is_removable = g_drive_is_media_removable (drive);
+
+ /* release the drive */
+ g_object_unref (drive);
+ }
+
+ /* determine whether the device can be mounted */
+ can_mount = g_volume_can_mount (volume);
+
+ return (can_eject || can_unmount || is_removable || can_mount);
+}
+
+
+
+static void
+thunar_device_monitor_volume_added (GVolumeMonitor *volume_monitor,
+ GVolume *volume,
+ ThunarDeviceMonitor *monitor)
+{
+ _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor));
+ _thunar_return_if_fail (THUNAR_IS_DEVICE_MONITOR (monitor));
+ _thunar_return_if_fail (monitor->volume_monitor == volume_monitor);
+ _thunar_return_if_fail (G_IS_VOLUME (volume));
+
+ /* add to internal list */
+ monitor->hidden_volumes = g_list_prepend (monitor->hidden_volumes, g_object_ref (volume));
+
+ /* change visibility in changed */
+ thunar_device_monitor_volume_changed (volume_monitor, volume, monitor);
+}
+
+
+
+static void
+thunar_device_monitor_volume_removed (GVolumeMonitor *volume_monitor,
+ GVolume *volume,
+ ThunarDeviceMonitor *monitor)
+{
+ ThunarDevice *device;
+ GList *lp;
+
+ _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor));
+ _thunar_return_if_fail (THUNAR_IS_DEVICE_MONITOR (monitor));
+ _thunar_return_if_fail (monitor->volume_monitor == volume_monitor);
+ _thunar_return_if_fail (G_IS_VOLUME (volume));
+
+ /* remove the volume */
+ lp = g_list_find (monitor->hidden_volumes, volume);
+ if (lp != NULL)
+ {
+ /* silently drop it */
+ monitor->hidden_volumes = g_list_delete_link (monitor->hidden_volumes, lp);
+
+ /* release ref from hidden list */
+ g_object_unref (G_OBJECT (volume));
+ }
+ else
+ {
+ /* find device */
+ device = g_hash_table_lookup (monitor->devices, volume);
+
+ /* meh */
+ _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
+ if (G_UNLIKELY (device == NULL))
+ return;
+
+ /* the device is not visble for the user */
+ g_signal_emit (G_OBJECT (monitor), device_monitor_signals[DEVICE_REMOVED], 0, device);
+
+ /* drop it */
+ g_hash_table_remove (monitor->devices, volume);
+ }
+}
+
+
+
+static void
+thunar_device_monitor_volume_changed (GVolumeMonitor *volume_monitor,
+ GVolume *volume,
+ ThunarDeviceMonitor *monitor)
+{
+ GList *lp;
+ ThunarDevice *device;
+
+ _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor));
+ _thunar_return_if_fail (THUNAR_IS_DEVICE_MONITOR (monitor));
+ _thunar_return_if_fail (monitor->volume_monitor == volume_monitor);
+ _thunar_return_if_fail (G_IS_VOLUME (volume));
+
+ lp = g_list_find (monitor->hidden_volumes, volume);
+ if (lp != NULL)
+ {
+ /* check if the volume should be visible again */
+ if (thunar_device_monitor_volume_is_visible (volume))
+ {
+ /* remove from the hidden list */
+ monitor->hidden_volumes = g_list_delete_link (monitor->hidden_volumes, lp);
+
+ /* create a new device for this volume */
+ device = g_object_new (THUNAR_TYPE_DEVICE,
+ "device", volume,
+ "kind", THUNAR_DEVICE_KIND_VOLUME,
+ NULL);
+
+ /* insert to list (takes ref from hidden list) */
+ g_hash_table_insert (monitor->devices, volume, device);
+
+ /* notify */
+ g_signal_emit (G_OBJECT (monitor), device_monitor_signals[DEVICE_ADDED], 0, device);
+ }
+ }
+ else
+ {
+ /* find device */
+ device = g_hash_table_lookup (monitor->devices, volume);
+
+ /* meh */
+ _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
+ if (G_UNLIKELY (device == NULL))
+ return;
+
+ if (!thunar_device_monitor_volume_is_visible (volume))
+ {
+ /* remove from table */
+ g_hash_table_steal (monitor->devices, volume);
+
+ /* insert volume in hidden table, take ref from table */
+ monitor->hidden_volumes = g_list_prepend (monitor->hidden_volumes, volume);
+
+ /* the device is not visble for the user */
+ g_signal_emit (G_OBJECT (monitor), device_monitor_signals[DEVICE_REMOVED], 0, device);
+
+ /* destroy device */
+ g_object_unref (G_OBJECT (device));
+ }
+ else
+ {
+ /* the device changed */
+ g_signal_emit (G_OBJECT (monitor), device_monitor_signals[DEVICE_CHANGED], 0, device);
+ }
+ }
+}
+
+
+
+static void
+thunar_device_monitor_mount_added (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ ThunarDeviceMonitor *monitor)
+{
+ ThunarDevice *device;
+ GFile *location;
+ ThunarDeviceKind kind = THUNAR_DEVICE_KIND_MOUNT_LOCAL;
+
+ _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor));
+ _thunar_return_if_fail (THUNAR_IS_DEVICE_MONITOR (monitor));
+ _thunar_return_if_fail (monitor->volume_monitor == volume_monitor);
+ _thunar_return_if_fail (G_IS_MOUNT (mount));
+
+ if (!thunar_device_monitor_mount_is_hidden (mount, monitor))
+ {
+ location = g_mount_get_root (mount);
+ if (G_LIKELY (location != NULL))
+ {
+ if (g_file_has_uri_scheme (location, "file")
+ || g_file_has_uri_scheme (location, "archive"))
+ kind = THUNAR_DEVICE_KIND_MOUNT_LOCAL;
+ else
+ kind = THUNAR_DEVICE_KIND_MOUNT_REMOTE;
+
+ g_object_unref (location);
+ }
+
+ /* create a new device for this mount */
+ device = g_object_new (THUNAR_TYPE_DEVICE,
+ "device", mount,
+ "kind", kind,
+ NULL);
+
+ /* insert to list */
+ g_hash_table_insert (monitor->devices, g_object_ref (mount), device);
+
+ /* notify */
+ g_signal_emit (G_OBJECT (monitor), device_monitor_signals[DEVICE_ADDED], 0, device);
+ }
+}
+
+
+
+static void
+thunar_device_monitor_mount_removed (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ ThunarDeviceMonitor *monitor)
+{
+ ThunarDevice *device;
+
+ _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor));
+ _thunar_return_if_fail (THUNAR_IS_DEVICE_MONITOR (monitor));
+ _thunar_return_if_fail (monitor->volume_monitor == volume_monitor);
+ _thunar_return_if_fail (G_IS_MOUNT (mount));
+
+ /* check if we have a device for this mount */
+ device = g_hash_table_lookup (monitor->devices, mount);
+ if (device != NULL)
+ {
+ /* notify */
+ g_signal_emit (G_OBJECT (monitor), device_monitor_signals[DEVICE_REMOVED], 0, device);
+
+ /* drop it */
+ g_hash_table_remove (monitor->devices, mount);
+ }
+}
+
+
+
+static void
+thunar_device_monitor_mount_changed (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ ThunarDeviceMonitor *monitor)
+{
+ ThunarDevice *device;
+
+ _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor));
+ _thunar_return_if_fail (THUNAR_IS_DEVICE_MONITOR (monitor));
+ _thunar_return_if_fail (monitor->volume_monitor == volume_monitor);
+ _thunar_return_if_fail (G_IS_MOUNT (mount));
+
+ /* check if we have a device for this mount */
+ device = g_hash_table_lookup (monitor->devices, mount);
+ if (device != NULL)
+ {
+ /* notify */
+ g_signal_emit (G_OBJECT (monitor), device_monitor_signals[DEVICE_CHANGED], 0, device);
+ }
+}
+
+
+
+static void
+thunar_device_monitor_list_prepend (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GList **list = user_data;
+
+ _thunar_return_if_fail (THUNAR_IS_DEVICE (value));
+ *list = g_list_prepend (*list, g_object_ref (value));
+}
+
+
+
+ThunarDeviceMonitor *
+thunar_device_monitor_get (void)
+{
+static ThunarDeviceMonitor *monitor = NULL;
+
+ if (G_UNLIKELY (monitor == NULL))
+ {
+ monitor = g_object_new (THUNAR_TYPE_DEVICE_MONITOR, NULL);
+ g_object_add_weak_pointer (G_OBJECT (monitor), (gpointer) &monitor);
+ }
+ else
+ {
+ g_object_ref (G_OBJECT (monitor));
+ }
+
+ return monitor;
+}
+
+
+
+GList *
+thunar_device_monitor_get_devices (ThunarDeviceMonitor *monitor)
+{
+ GList *list = NULL;
+
+ _thunar_return_val_if_fail (THUNAR_IS_DEVICE_MONITOR (monitor), NULL);
+
+ g_hash_table_foreach (monitor->devices, thunar_device_monitor_list_prepend, &list);
+
+ return list;
+}
diff --git a/thunar/thunar-device-monitor.h b/thunar/thunar-device-monitor.h
new file mode 100644
index 0000000..4932c41
--- /dev/null
+++ b/thunar/thunar-device-monitor.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2012 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __THUNAR_DEVICE_MONITOR_H__
+#define __THUNAR_DEVICE_MONITOR_H__
+
+#include <thunar/thunar-device.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ThunarDeviceMonitorClass ThunarDeviceMonitorClass;
+typedef struct _ThunarDeviceMonitor ThunarDeviceMonitor;
+
+#define THUNAR_TYPE_DEVICE_MONITOR (thunar_device_monitor_get_type ())
+#define THUNAR_DEVICE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_DEVICE_MONITOR, ThunarDeviceMonitor))
+#define THUNAR_DEVICE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_DEVICE_MONITOR, ThunarDeviceMonitorClass))
+#define THUNAR_IS_DEVICE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_DEVICE_MONITOR))
+#define THUNAR_IS_DEVICE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), THUNAR_TYPE_DEVICE_MONITOR))
+#define THUNAR_DEVICE_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_DEVICE_MONITOR, ThunarDeviceMonitorClass))
+
+GType thunar_device_monitor_get_type (void) G_GNUC_CONST;
+
+ThunarDeviceMonitor *thunar_device_monitor_get (void);
+
+GList *thunar_device_monitor_get_devices (ThunarDeviceMonitor *monitor);
+
+G_END_DECLS
+
+#endif /* !__THUNAR_DEVICE_MONITOR_H__ */
diff --git a/thunar/thunar-device.c b/thunar/thunar-device.c
new file mode 100644
index 0000000..0178014
--- /dev/null
+++ b/thunar/thunar-device.c
@@ -0,0 +1,711 @@
+/*-
+ * Copyright (c) 2012 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LIBNOTIFY
+#include <thunar/thunar-notify.h>
+#endif
+#include <thunar/thunar-device.h>
+#include <thunar/thunar-private.h>
+
+
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+ PROP_KIND
+};
+
+
+
+static void thunar_device_finalize (GObject *object);
+static void thunar_device_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void thunar_device_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+
+
+struct _ThunarDeviceClass
+{
+ GObjectClass __parent__;
+};
+
+struct _ThunarDevice
+{
+ GObject __parent__;
+
+ /* a GVolume/GMount/GDrive */
+ gpointer device;
+
+ ThunarDeviceKind kind;
+};
+
+typedef struct
+{
+ ThunarDevice *device;
+ ThunarDeviceCallback callback;
+ gpointer user_data;
+}
+ThunarDeviceOperation;
+
+
+
+G_DEFINE_TYPE (ThunarDevice, thunar_device, G_TYPE_OBJECT)
+
+
+
+static void
+thunar_device_class_init (ThunarDeviceClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = thunar_device_finalize;
+ gobject_class->get_property = thunar_device_get_property;
+ gobject_class->set_property = thunar_device_set_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_DEVICE,
+ g_param_spec_object ("device",
+ "device",
+ "device",
+ G_TYPE_OBJECT,
+ EXO_PARAM_READWRITE
+ | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class,
+ PROP_KIND,
+ g_param_spec_uint ("kind",
+ "kind",
+ "kind",
+ THUNAR_DEVICE_KIND_VOLUME,
+ THUNAR_DEVICE_KIND_MOUNT_REMOTE,
+ THUNAR_DEVICE_KIND_VOLUME,
+ EXO_PARAM_READWRITE
+ | G_PARAM_CONSTRUCT_ONLY));
+}
+
+
+
+static void
+thunar_device_init (ThunarDevice *device)
+{
+ device->kind = THUNAR_DEVICE_KIND_VOLUME;
+}
+
+
+
+static void
+thunar_device_finalize (GObject *object)
+{
+ ThunarDevice *device = THUNAR_DEVICE (object);
+
+ if (device->device != NULL)
+ g_object_unref (G_OBJECT (device->device));
+
+ (*G_OBJECT_CLASS (thunar_device_parent_class)->finalize) (object);
+}
+
+
+
+static void
+thunar_device_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ThunarDevice *device = THUNAR_DEVICE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ g_value_set_object (value, device->device);
+ break;
+
+ case PROP_KIND:
+ g_value_set_uint (value, device->kind);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+thunar_device_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ThunarDevice *device = THUNAR_DEVICE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ device->device = g_value_dup_object (value);
+ _thunar_assert (G_IS_VOLUME (device->device) || G_IS_MOUNT (device->device));
+ break;
+
+ case PROP_KIND:
+ device->kind = g_value_get_uint (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+
+static ThunarDeviceOperation *
+thunar_device_operation_new (ThunarDevice *device,
+ ThunarDeviceCallback callback,
+ gpointer user_data)
+{
+ ThunarDeviceOperation *operation;
+
+ operation = g_slice_new0 (ThunarDeviceOperation);
+ operation->device = g_object_ref (device);
+ operation->callback = callback;
+ operation->user_data = user_data;
+
+ return operation;
+}
+
+
+
+static void
+thunar_device_operation_free (ThunarDeviceOperation *operation)
+{
+ g_object_unref (operation->device);
+ g_slice_free (ThunarDeviceOperation, operation);
+}
+
+
+
+static void
+thunar_device_mount_unmount_finish (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ThunarDeviceOperation *operation = user_data;
+ GError *error = NULL;
+
+ _thunar_return_if_fail (G_IS_MOUNT (object));
+ _thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
+
+#ifdef HAVE_LIBNOTIFY
+ thunar_notify_unmount_finish (G_MOUNT (object));
+#endif
+
+ /* finish the unmount */
+ if (!g_mount_unmount_with_operation_finish (G_MOUNT (object), result, &error))
+ {
+ /* unset the error if a helper program has already interacted with the user */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED))
+ g_clear_error (&error);
+ }
+
+ /* callback */
+ (operation->callback) (operation->device, error, operation->user_data);
+
+ /* cleanup */
+ if (error != NULL)
+ g_error_free (error);
+ thunar_device_operation_free (operation);
+}
+
+
+
+static void
+thunar_device_mount_eject_finish (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ThunarDeviceOperation *operation = user_data;
+ GError *error = NULL;
+
+ _thunar_return_if_fail (G_IS_MOUNT (object));
+ _thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
+
+#ifdef HAVE_LIBNOTIFY
+ thunar_notify_unmount_finish (G_MOUNT (object));
+#endif
+
+ /* finish the eject */
+ if (!g_mount_eject_with_operation_finish (G_MOUNT (object), result, &error))
+ {
+ /* unset the error if a helper program has already interacted with the user */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED))
+ g_clear_error (&error);
+ }
+
+ /* callback */
+ (operation->callback) (operation->device, error, operation->user_data);
+
+ /* cleanup */
+ if (error != NULL)
+ g_error_free (error);
+ thunar_device_operation_free (operation);
+}
+
+
+
+static void
+thunar_device_volume_eject_finish (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ThunarDeviceOperation *operation = user_data;
+ GError *error = NULL;
+
+ _thunar_return_if_fail (G_IS_VOLUME (object));
+ _thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
+
+#ifdef HAVE_LIBNOTIFY
+ thunar_notify_eject_finish (G_VOLUME (object));
+#endif
+
+ /* finish the eject */
+ if (!g_volume_eject_with_operation_finish (G_VOLUME (object), result, &error))
+ {
+ /* unset the error if a helper program has already interacted with the user */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED))
+ g_clear_error (&error);
+ }
+
+ /* callback */
+ (operation->callback) (operation->device, error, operation->user_data);
+
+ /* cleanup */
+ if (error != NULL)
+ g_error_free (error);
+ thunar_device_operation_free (operation);
+}
+
+
+
+gchar *
+thunar_device_get_name (const ThunarDevice *device)
+{
+ _thunar_return_val_if_fail (THUNAR_IS_DEVICE (device), NULL);
+
+ if (G_IS_VOLUME (device->device))
+ return g_volume_get_name (device->device);
+ else if (G_IS_MOUNT (device->device))
+ return g_mount_get_name (device->device);
+ else
+ _thunar_assert_not_reached ();
+
+ return NULL;
+}
+
+
+
+GIcon *
+thunar_device_get_icon (const ThunarDevice *device)
+{
+ _thunar_return_val_if_fail (THUNAR_IS_DEVICE (device), NULL);
+
+ if (G_IS_VOLUME (device->device))
+ return g_volume_get_icon (device->device);
+ else if (G_IS_MOUNT (device->device))
+ return g_mount_get_icon (device->device);
+ else
+ _thunar_assert_not_reached ();
+
+ return NULL;
+}
+
+
+
+ThunarDeviceKind
+thunar_device_get_kind (const ThunarDevice *device)
+{
+ _thunar_return_val_if_fail (THUNAR_IS_DEVICE (device), THUNAR_DEVICE_KIND_VOLUME);
+ return device->kind;
+}
+
+
+
+/**
+ * thunar_device_can_eject:
+ *
+ * If the user should see the option to eject this device.
+ **/
+gboolean
+thunar_device_can_eject (const ThunarDevice *device)
+{
+ gboolean can_eject = FALSE;
+ GMount *volume_mount;
+
+ _thunar_return_val_if_fail (THUNAR_IS_DEVICE (device), FALSE);
+
+ if (G_IS_VOLUME (device->device))
+ {
+ can_eject = g_volume_can_eject (device->device);
+
+ if (!can_eject)
+ {
+ /* check if the mount can eject/unmount */
+ volume_mount = g_volume_get_mount (device->device);
+ if (volume_mount != NULL)
+ {
+ can_eject = g_mount_can_eject (volume_mount) || g_mount_can_unmount (volume_mount);
+ g_object_unref (volume_mount);
+ }
+ }
+ }
+ else if (G_IS_MOUNT (device->device))
+ {
+ /* eject or unmount because thats for the user the same
+ * because we prefer volumes over mounts as devices */
+ can_eject = g_mount_can_eject (device->device) || g_mount_can_unmount (device->device);
+ }
+ else
+ _thunar_assert_not_reached ();
+
+ return can_eject;
+}
+
+
+
+/**
+ * thunar_device_can_mount:
+ *
+ * If the user should see the option to mount this device.
+ **/
+gboolean
+thunar_device_can_mount (const ThunarDevice *device)
+{
+ gboolean can_mount = FALSE;
+ GMount *volume_mount;
+
+ _thunar_return_val_if_fail (THUNAR_IS_DEVICE (device), FALSE);
+
+ if (G_IS_VOLUME (device->device))
+ {
+ /* only volumes without a mountpoint and mount capability */
+ volume_mount = g_volume_get_mount (device->device);
+ if (volume_mount == NULL)
+ can_mount = g_volume_can_mount (device->device);
+ else
+ g_object_unref (volume_mount);
+ }
+ else if (G_IS_MOUNT (device->device))
+ {
+ /* a mount is already mounted... */
+ can_mount = FALSE;
+ }
+ else
+ _thunar_assert_not_reached ();
+
+ return can_mount;
+}
+
+
+
+/**
+ * thunar_device_can_unmount:
+ *
+ * If the user should see the option to unmount this device.
+ **/
+gboolean
+thunar_device_can_unmount (const ThunarDevice *device)
+{
+ gboolean can_unmount = FALSE;
+ GMount *volume_mount;
+
+ _thunar_return_val_if_fail (THUNAR_IS_DEVICE (device), FALSE);
+
+ if (G_IS_VOLUME (device->device))
+ {
+ /* only volumes with a mountpoint and unmount capability */
+ volume_mount = g_volume_get_mount (device->device);
+ if (volume_mount != NULL)
+ {
+ can_unmount = g_mount_can_unmount (volume_mount);
+ g_object_unref (volume_mount);
+ }
+ }
+ else if (G_IS_MOUNT (device->device))
+ {
+ /* check if the mount can unmount */
+ can_unmount = g_mount_can_unmount (device->device);
+ }
+ else
+ _thunar_assert_not_reached ();
+
+ return can_unmount;
+}
+
+
+
+gboolean
+thunar_device_is_mounted (const ThunarDevice *device)
+{
+ gboolean is_mounted = FALSE;
+ GMount *volume_mount;
+
+ _thunar_return_val_if_fail (THUNAR_IS_DEVICE (device), FALSE);
+
+ if (G_IS_VOLUME (device->device))
+ {
+ /* a volume with a mount point is mounted */
+ volume_mount = g_volume_get_mount (device->device);
+ if (volume_mount != NULL)
+ {
+ is_mounted = TRUE;
+ g_object_unref (volume_mount);
+ }
+ }
+ else if (G_IS_MOUNT (device->device))
+ {
+ /* mounter are always mounted... */
+ is_mounted = TRUE;
+ }
+ else
+ _thunar_assert_not_reached ();
+
+ return is_mounted;
+}
+
+
+
+GFile *
+thunar_device_get_root (const ThunarDevice *device)
+{
+ GFile *root = NULL;
+ GMount *volume_mount;
+
+ _thunar_return_val_if_fail (THUNAR_IS_DEVICE (device), NULL);
+
+ if (G_IS_VOLUME (device->device))
+ {
+ volume_mount = g_volume_get_mount (device->device);
+ if (volume_mount != NULL)
+ {
+ root = g_mount_get_root (volume_mount);
+ g_object_unref (volume_mount);
+ }
+ }
+ else if (G_IS_MOUNT (device->device))
+ {
+ root = g_mount_get_root (device->device);
+ }
+ else
+ _thunar_assert_not_reached ();
+
+ return root;
+}
+
+
+
+const gchar *
+thunar_device_get_sort_key (const ThunarDevice *device)
+{
+ _thunar_return_val_if_fail (THUNAR_IS_DEVICE (device), NULL);
+
+ if (G_IS_VOLUME (device->device))
+ return g_volume_get_sort_key (device->device);
+ else if (G_IS_MOUNT (device->device))
+ return g_mount_get_sort_key (device->device);
+ else
+ _thunar_assert_not_reached ();
+
+ return NULL;
+}
+
+
+
+void
+thunar_device_mount (ThunarDevice *device,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ ThunarDeviceCallback callback,
+ gpointer user_data)
+{
+ _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
+ _thunar_return_if_fail (G_IS_MOUNT_OPERATION (mount_operation));
+ _thunar_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ _thunar_return_if_fail (callback != NULL);
+}
+
+
+
+/**
+ * thunar_device_unmount:
+ *
+ * Unmount a #ThunarDevice. Don't try to eject.
+ **/
+void
+thunar_device_unmount (ThunarDevice *device,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ ThunarDeviceCallback callback,
+ gpointer user_data)
+{
+ ThunarDeviceOperation *operation;
+ GMount *mount;
+
+ _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
+ _thunar_return_if_fail (G_IS_MOUNT_OPERATION (mount_operation));
+ _thunar_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ _thunar_return_if_fail (callback != NULL);
+
+ /* get the mount from the volume or use existing mount */
+ if (G_IS_VOLUME (device->device))
+ mount = g_volume_get_mount (device->device);
+ else if (G_IS_MOUNT (device->device))
+ mount = g_object_ref (device->device);
+ else
+ mount = NULL;
+
+ if (G_LIKELY (mount != NULL))
+ {
+ /* only handle mounts that can be unmounted here */
+ if (g_mount_can_unmount (mount))
+ {
+#ifdef HAVE_LIBNOTIFY
+ thunar_notify_unmount (mount);
+#endif
+
+ /* try unmounting the mount */
+ operation = thunar_device_operation_new (device, callback, user_data);
+ g_mount_unmount_with_operation (mount,
+ G_MOUNT_UNMOUNT_NONE,
+ mount_operation,
+ cancellable,
+ thunar_device_mount_unmount_finish,
+ operation);
+ }
+
+ g_object_unref (G_OBJECT (mount));
+ }
+}
+
+
+
+/**
+ * thunar_device_unmount:
+ *
+ * Try to eject a #ThunarDevice, fall-back to unmounting
+ **/
+void
+thunar_device_eject (ThunarDevice *device,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ ThunarDeviceCallback callback,
+ gpointer user_data)
+{
+ ThunarDeviceOperation *operation;
+ GMount *mount = NULL;
+ GVolume *volume;
+
+ _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
+ _thunar_return_if_fail (G_IS_MOUNT_OPERATION (mount_operation));
+ _thunar_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ _thunar_return_if_fail (callback != NULL);
+
+
+ if (G_IS_VOLUME (device->device))
+ {
+ volume = device->device;
+
+ if (g_volume_can_eject (volume))
+ {
+#ifdef HAVE_LIBNOTIFY
+ thunar_notify_eject (volume);
+#endif
+
+ /* try ejecting the volume */
+ operation = thunar_device_operation_new (device, callback, user_data);
+ g_volume_eject_with_operation (volume,
+ G_MOUNT_UNMOUNT_NONE,
+ mount_operation,
+ cancellable,
+ thunar_device_volume_eject_finish,
+ operation);
+
+ /* done */
+ return;
+ }
+ else
+ {
+ /* get the mount and fall-through */
+ mount = g_volume_get_mount (volume);
+ }
+ }
+ else if (G_IS_MOUNT (device->device))
+ {
+ /* set the mount and fall-through */
+ mount = g_object_ref (device->device);
+ }
+
+ /* handle mounts */
+ if (mount != NULL)
+ {
+ /* distinguish between ejectable and unmountable mounts */
+ if (g_mount_can_eject (mount))
+ {
+#ifdef HAVE_LIBNOTIFY
+ thunar_notify_unmount (mount);
+#endif
+
+ /* try ejecting the mount */
+ operation = thunar_device_operation_new (device, callback, user_data);
+ g_mount_eject_with_operation (mount,
+ G_MOUNT_UNMOUNT_NONE,
+ mount_operation,
+ cancellable,
+ thunar_device_mount_eject_finish,
+ operation);
+ }
+ else if (g_mount_can_unmount (mount))
+ {
+#ifdef HAVE_LIBNOTIFY
+ thunar_notify_unmount (mount);
+#endif
+
+ /* try unmounting the mount */
+ operation = thunar_device_operation_new (device, callback, user_data);
+ g_mount_unmount_with_operation (mount,
+ G_MOUNT_UNMOUNT_NONE,
+ mount_operation,
+ cancellable,
+ thunar_device_mount_unmount_finish,
+ operation);
+ }
+
+ g_object_unref (G_OBJECT (mount));
+ }
+}
diff --git a/thunar/thunar-device.h b/thunar/thunar-device.h
new file mode 100644
index 0000000..f4de610
--- /dev/null
+++ b/thunar/thunar-device.h
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 2012 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __THUNAR_DEVICE_H__
+#define __THUNAR_DEVICE_H__
+
+#include <thunar/thunar-file.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ThunarDeviceClass ThunarDeviceClass;
+typedef struct _ThunarDevice ThunarDevice;
+typedef enum _ThunarDeviceKind ThunarDeviceKind;
+
+typedef void (*ThunarDeviceCallback) (ThunarDevice *device,
+ const GError *error,
+ gpointer user_data);
+
+enum _ThunarDeviceKind
+{
+ THUNAR_DEVICE_KIND_VOLUME,
+ THUNAR_DEVICE_KIND_MOUNT_LOCAL,
+ THUNAR_DEVICE_KIND_MOUNT_REMOTE
+};
+
+#define THUNAR_TYPE_DEVICE (thunar_device_get_type ())
+#define THUNAR_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_DEVICE, ThunarDevice))
+#define THUNAR_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_DEVICE, ThunarDeviceClass))
+#define THUNAR_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_DEVICE))
+#define THUNAR_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), THUNAR_TYPE_DEVICE))
+#define THUNAR_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_DEVICE, ThunarDeviceClass))
+
+GType thunar_device_get_type (void) G_GNUC_CONST;
+
+gchar *thunar_device_get_name (const ThunarDevice *device) G_GNUC_MALLOC;
+
+GIcon *thunar_device_get_icon (const ThunarDevice *device);
+
+ThunarDeviceKind thunar_device_get_kind (const ThunarDevice *device) G_GNUC_PURE;
+
+gboolean thunar_device_can_eject (const ThunarDevice *device);
+
+gboolean thunar_device_can_mount (const ThunarDevice *device);
+
+gboolean thunar_device_can_unmount (const ThunarDevice *device);
+
+gboolean thunar_device_is_mounted (const ThunarDevice *device);
+
+GFile *thunar_device_get_root (const ThunarDevice *device);
+
+const gchar *thunar_device_get_sort_key (const ThunarDevice *device);
+
+void thunar_device_mount (ThunarDevice *device,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ ThunarDeviceCallback callback,
+ gpointer user_data);
+
+void thunar_device_unmount (ThunarDevice *device,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ ThunarDeviceCallback callback,
+ gpointer user_data);
+
+void thunar_device_eject (ThunarDevice *device,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ ThunarDeviceCallback callback,
+ gpointer user_data);
+
+G_END_DECLS
+
+#endif /* !__THUNAR_DEVICE_H__ */
More information about the Xfce4-commits
mailing list