Introduce g_volume_monitor_adopt_orphan_mount() function. Also add signals
authorDavid Zeuthen <davidz@redhat.com>
Wed, 19 Dec 2007 09:39:50 +0000 (09:39 +0000)
committerAlexander Larsson <alexl@src.gnome.org>
Wed, 19 Dec 2007 09:39:50 +0000 (09:39 +0000)
2007-12-19  David Zeuthen  <davidz@redhat.com>

Introduce g_volume_monitor_adopt_orphan_mount() function. Also
add signals 'disconnected' and 'eject-button' on GDrive. Add
signal 'removed' on GVolume and 'unmounted' on GMount.

* gdrive.c: (g_drive_base_init):
* gdrive.h:
* gfile.c: (g_file_mount_mountable),
(g_file_mount_enclosing_volume):
* gio.symbols:
* gioerror.h:
* gmount.c: (g_mount_base_init):
* gmount.h:
* gunionvolumemonitor.c: (g_volume_monitor_adopt_orphan_mount):
* gunixvolumemonitor.c: (update_volumes), (update_mounts):
* gvolume.c: (g_volume_base_init), (g_volume_mount):
* gvolume.h:
* gvolumemonitor.h:

svn path=/trunk/; revision=6153

13 files changed:
gio/ChangeLog
gio/gdrive.c
gio/gdrive.h
gio/gfile.c
gio/gio.symbols
gio/gioerror.h
gio/gmount.c
gio/gmount.h
gio/gunionvolumemonitor.c
gio/gunixvolumemonitor.c
gio/gvolume.c
gio/gvolume.h
gio/gvolumemonitor.h

index 4a8da254eea7430f0f9d549c084a2282fdbc89f4..d7983b640af085c630221cb795e601f3473c188a 100644 (file)
@@ -1,3 +1,23 @@
+2007-12-19  David Zeuthen  <davidz@redhat.com>
+
+       Introduce g_volume_monitor_adopt_orphan_mount() function. Also
+       add signals 'disconnected' and 'eject-button' on GDrive. Add
+       signal 'removed' on GVolume and 'unmounted' on GMount.
+
+       * gdrive.c: (g_drive_base_init):
+       * gdrive.h:
+       * gfile.c: (g_file_mount_mountable),
+       (g_file_mount_enclosing_volume):
+       * gio.symbols:
+       * gioerror.h:
+       * gmount.c: (g_mount_base_init):
+       * gmount.h:
+       * gunionvolumemonitor.c: (g_volume_monitor_adopt_orphan_mount):
+       * gunixvolumemonitor.c: (update_volumes), (update_mounts):
+       * gvolume.c: (g_volume_base_init), (g_volume_mount):
+       * gvolume.h:
+       * gvolumemonitor.h:
+
 2007-12-17  Matthias Clasen  <mclasen@redhat.com>
 
        * *.c: Fix up includes in the section docs.
index 642ef6b2fbf9d8e131ef8bce86ccd2fc1095452b..b047774b50d63ad64528603d7828db5f64f6f7e6 100644 (file)
@@ -97,10 +97,9 @@ g_drive_base_init (gpointer g_class)
     {
       /**
       * GDrive::changed:
-      * @volume: a #GVolume.
+      * @drive: a #GDrive.
       * 
       * Emitted when the drive's state has changed.
-      * 
       **/
       g_signal_new (I_("changed"),
                     G_TYPE_DRIVE,
@@ -110,6 +109,38 @@ g_drive_base_init (gpointer g_class)
                     g_cclosure_marshal_VOID__VOID,
                     G_TYPE_NONE, 0);
 
+      /**
+      * GDrive::disconnected:
+      * @drive: a #GDrive.
+      * 
+      * This signal is emitted when the #GDrive have been
+      * disconnected. If the recipient is holding references to the
+      * object they should release them so the object can be
+      * finalized.
+      **/
+      g_signal_new (I_("disconnected"),
+                    G_TYPE_DRIVE,
+                    G_SIGNAL_RUN_LAST,
+                    G_STRUCT_OFFSET (GDriveIface, disconnected),
+                    NULL, NULL,
+                    g_cclosure_marshal_VOID__VOID,
+                    G_TYPE_NONE, 0);
+
+      /**
+      * GDrive::eject-button:
+      * @drive: a #GDrive.
+      * 
+      * Emitted when the physical eject button (if any) of a drive have been pressed.
+      * 
+      **/
+      g_signal_new (I_("eject-button"),
+                    G_TYPE_DRIVE,
+                    G_SIGNAL_RUN_LAST,
+                    G_STRUCT_OFFSET (GDriveIface, eject_button),
+                    NULL, NULL,
+                    g_cclosure_marshal_VOID__VOID,
+                    G_TYPE_NONE, 0);
+
       initialized = TRUE;
     }
 }
index 6d9e46310b03d485a6615624d64d0dfa9236eeff..230d02e1f5a5c100a94456de15ded171c940b82f 100644 (file)
@@ -44,6 +44,8 @@ G_BEGIN_DECLS
  * GDriveIface:
  * @g_iface: The parent interface.
  * @changed: Signal emitted when the drive is changed.
+ * @disconnected: The removed signal that is emitted when the #GDrive have been disconnected. If the recipient is holding references to the object they should release them so the object can be finalized.
+ * @eject_button: Signal emitted when the physical eject button (if any) of a drive have been pressed.
  * @get_name: Returns the name for the given #GDrive.
  * @get_icon: Returns a #GIcon for the given #GDrive.
  * @has_volumes: Returns %TRUE if the #GDrive has mountable volumes.
@@ -68,6 +70,8 @@ struct _GDriveIface
 
   /* signals */
   void (*changed)                      (GDrive              *drive);
+  void (*disconnected)                 (GDrive              *drive);
+  void (*eject_button)                 (GDrive              *drive);
   
   /* Virtual Table */
   char *   (*get_name)                 (GDrive              *drive);
index f3829da3d31b3a4bd9d0a613f04dfb85c63d8c9c..e651bed2358c6b02aeb0044414fce6039b4494ba 100644 (file)
@@ -2997,7 +2997,7 @@ g_file_set_attribute_int64 (GFile                *file,
 /**
  * g_file_mount_mountable:
  * @file: input #GFile.
- * @mount_operation: a #GMountOperation, or %NULL.
+ * @mount_operation: a #GMountOperation, or %NULL to avoid user interaction.
  * @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
@@ -3023,7 +3023,6 @@ g_file_mount_mountable (GFile               *file,
   GFileIface *iface;
 
   g_return_if_fail (G_IS_FILE (file));
-  g_return_if_fail (G_IS_MOUNT_OPERATION (mount_operation));
 
   iface = G_FILE_GET_IFACE (file);
 
@@ -3998,7 +3997,7 @@ g_file_new_for_commandline_arg (const char *arg)
 /**
  * g_file_mount_enclosing_volume:
  * @location: input #GFile.
- * @mount_operation: a #GMountOperation.
+ * @mount_operation: a #GMountOperation or %NULL to avoid user interaction.
  * @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
@@ -4023,7 +4022,6 @@ g_file_mount_enclosing_volume (GFile               *location,
   GFileIface *iface;
 
   g_return_if_fail (G_IS_FILE (location));
-  g_return_if_fail (G_IS_MOUNT_OPERATION (mount_operation));
 
   iface = G_FILE_GET_IFACE (location);
 
index 3f2806e4971119f15f808255b6b1edf9c7940318..6d7f89f55d44144e77d161de94ca5b02547ae5bb 100644 (file)
@@ -720,6 +720,7 @@ g_volume_monitor_get_mount_for_uuid
 #endif
 #if IN_FILE(__G_UNION_VOLUME_MONITOR_C__)
 g_volume_monitor_get 
+g_volume_monitor_adopt_orphan_mount
 #endif
 #endif
 
index f024c09ba28aa0454dbb99e6be4ee3637c6f0e83..01a1ae2972f0b9f6b1ddbfc56871be5d12ed218d 100644 (file)
@@ -79,6 +79,7 @@ GQuark          g_io_error_quark      (void);
  * @G_IO_ERROR_WOULD_BLOCK: Operation would block.
  * @G_IO_ERROR_HOST_NOT_FOUND: Host couldn't be found (remote operations).
  * @G_IO_ERROR_WOULD_MERGE: Operation would merge files.
+ * @G_IO_ERROR_FAILED_HANDLED: Operation failed and a helper program has already interacted with the user. Do not display any error dialog.
  *
  * Error codes returned by GIO functions.
  * 
@@ -114,7 +115,8 @@ typedef enum
   G_IO_ERROR_BUSY,
   G_IO_ERROR_WOULD_BLOCK,
   G_IO_ERROR_HOST_NOT_FOUND,
-  G_IO_ERROR_WOULD_MERGE
+  G_IO_ERROR_WOULD_MERGE,
+  G_IO_ERROR_FAILED_HANDLED
 } GIOErrorEnum;
 
 GIOErrorEnum g_io_error_from_errno (gint err_no);
index d1ed537c7879cf32596b2674d3ad4e90b37b1e7a..3b4d297992add69490713e88c9cabb6ca5215ea6 100644 (file)
@@ -115,6 +115,22 @@ g_mount_base_init (gpointer g_class)
                     g_cclosure_marshal_VOID__VOID,
                     G_TYPE_NONE, 0);
 
+     /**
+      * GMount::unmounted:
+      * 
+      * This signal is emitted when the #GMount have been
+      * unmounted. If the recipient is holding references to the
+      * object they should release them so the object can be
+      * finalized.
+      **/
+      g_signal_new (I_("unmounted"),
+                    G_TYPE_MOUNT,
+                    G_SIGNAL_RUN_LAST,
+                    G_STRUCT_OFFSET (GMountIface, unmounted),
+                    NULL, NULL,
+                    g_cclosure_marshal_VOID__VOID,
+                    G_TYPE_NONE, 0);
+
       initialized = TRUE;
     }
 }
index 621b434e2d141f5889e537d8090732a61a122540..46958f972906946443dce4dcb1f031f6e303f032 100644 (file)
@@ -59,6 +59,7 @@ typedef struct _GMountIface    GMountIface;
  * GMountIface:
  * @g_iface: The parent interface.
  * @changed: Changed signal that is emitted when the mount's state has changed.
+ * @unmounted: The unmounted signal that is emitted when the #GMount have been unmounted. If the recipient is holding references to the object they should release them so the object can be finalized.
  * @get_root: Gets a #GFile to the root directory of the #GMount.
  * @get_name: Gets a string containing the name of the #GMount.
  * @get_icon: Gets a #GIcon for the #GMount.
@@ -81,6 +82,7 @@ struct _GMountIface
   /* signals */
 
   void (*changed) (GMount *mount);
+  void (*unmounted) (GMount *mount);
   
   /* Virtual Table */
 
index 3fb6485a8632824ecdd89090c48ab0e1bcffccb0..b3815d8efc54487f46706e0cb15aa3f6911ed43a 100644 (file)
@@ -601,5 +601,79 @@ _g_mount_get_for_mount_path (const char *mount_path,
   return mount;
 }
 
+/**
+ * g_volume_monitor_adopt_orphan_mount:
+ * @mount: a #GMount object to find a parent for
+ *
+ * This function should be called by any #GVolumeMonitor
+ * implementation when a new #GMount object is created that is not
+ * associated with a #GVolume object. It must be called just before
+ * emitting the @mount_added signal.
+ *
+ * If the return value is not %NULL, the caller must associate the
+ * returned #GVolume object with the #GMount. This involves returning
+ * it in it's g_mount_get_volume() implementation. The caller must
+ * also listen for the "removed" signal on the returned object
+ * and give up it's reference when handling that signal
+ * 
+ * Similary, if implementing g_volume_monitor_adopt_orphan_mount(),
+ * the implementor must take a reference to @mount and return it in
+ * it's g_volume_get_mount() implemented. Also, the implementor must
+ * listen for the "unmounted" signal on @mount and give up it's
+ * reference upon handling that signal.
+ *
+ * There are two main use cases for this function.
+ *
+ * One is when implementing a user space file system driver that reads
+ * blocks of a block device that is already represented by the native
+ * volume monitor (for example a CD Audio file system driver). Such
+ * a driver will generate it's own #GMount object that needs to be
+ * assoicated with the #GVolume object that represents the volume.
+ *
+ * The other is for implementing a #GVolumeMonitor whose sole purpose
+ * is to return #GVolume objects representing entries in the users
+ * "favorite servers" list or similar.
+ *
+ * Returns: the #GVolume object that is the parent for @mount or %NULL
+ * if no wants to adopt the #GMount.
+ */
+GVolume *
+g_volume_monitor_adopt_orphan_mount (GMount *mount)
+{
+  GVolumeMonitor *child_monitor;
+  GVolumeMonitorClass *child_monitor_class;
+  GVolume *volume;
+  GList *l;
+
+  g_return_val_if_fail (mount != NULL, NULL);
+
+  if (the_volume_monitor == NULL)
+    return NULL;
+
+  volume = NULL;
+  
+  /* TODO: nasty locking issues because current VM's don't emit signals in idle */
+
+  //G_LOCK (the_volume_monitor);
+
+  for (l = the_volume_monitor->monitors; l != NULL; l = l->next)
+    {
+      child_monitor = l->data;
+      child_monitor_class = G_VOLUME_MONITOR_GET_CLASS (child_monitor);
+
+      if (child_monitor_class->adopt_orphan_mount != NULL)
+        {
+          volume = child_monitor_class->adopt_orphan_mount (mount);
+          if (volume != NULL)
+            break;
+        }
+    }
+  
+  //G_UNLOCK (the_volume_monitor);
+
+  return volume;
+}
+
+
 #define __G_UNION_VOLUME_MONITOR_C__
 #include "gioaliasdef.c"
index dd4b82eafeb7eb2cdb94558bd74f9f4db654f6a0..4fc81e9f077cccc5f3a997b610c1a5247408e3b4 100644 (file)
@@ -340,6 +340,7 @@ update_volumes (GUnixVolumeMonitor *monitor)
          _g_unix_volume_disconnected (volume);
          monitor->volumes = g_list_remove (monitor->volumes, volume);
          g_signal_emit_by_name (monitor, "volume_removed", volume);
+         g_signal_emit_by_name (volume, "removed");
          g_object_unref (volume);
        }
     }
@@ -392,6 +393,7 @@ update_mounts (GUnixVolumeMonitor *monitor)
          _g_unix_mount_unmounted (mount);
          monitor->mounts = g_list_remove (monitor->mounts, mount);
          g_signal_emit_by_name (monitor, "mount_removed", mount);
+         g_signal_emit_by_name (mount, "unmounted");
          g_object_unref (mount);
        }
     }
index 501e770ebf0eb840a8e1f9692fc7caa1052bef21..84d0a2c41564e6d071ab71afcf677db3d222d4b7 100644 (file)
  * Mounting a #GVolume instance is an asynchronous operation. For more
  * information about asynchronous operations, see #GAsyncReady and
  * #GSimpleAsyncReady. To mount a #GVolume, first call
- * g_volume_mount() with (at least) the #GVolume instane, a
- * #GMountOperation object and a #GAsyncReadyCallback.  The callback
- * will be fired when the operation has resolved (either with success
- * or failure), and a #GAsyncReady structure will be passed to the
- * callback.  That callback should then call g_volume_mount_finish()
- * with the #GVolume instance and the #GAsyncReady data to see if the
- * operation was completed successfully.  If an @error is present when
- * g_volume_mount_finish() is called, then it will be filled with any
- * error information.
+ * g_volume_mount() with (at least) the #GVolume instance, optionally
+ * a #GMountOperation object and a #GAsyncReadyCallback. 
+ *
+ * Typically, one will only want to pass %NULL for the
+ * #GMountOperation if automounting all volumes when a desktop session
+ * starts since it's not desirable to put up a lot of dialogs asking
+ * for credentials.
+ *
+ * The callback will be fired when the operation has resolved (either
+ * with success or failure), and a #GAsyncReady structure will be
+ * passed to the callback.  That callback should then call
+ * g_volume_mount_finish() with the #GVolume instance and the
+ * #GAsyncReady data to see if the operation was completed
+ * successfully.  If an @error is present when g_volume_mount_finish()
+ * is called, then it will be filled with any error information.
  **/
 
 static void g_volume_base_init (gpointer g_class);
@@ -112,6 +118,21 @@ g_volume_base_init (gpointer g_class)
                     g_cclosure_marshal_VOID__VOID,
                     G_TYPE_NONE, 0);
 
+     /**
+      * GVolume::removed:
+      * 
+      * This signal is emitted when the #GVolume have been removed. If
+      * the recipient is holding references to the object they should
+      * release them so the object can be finalized.
+      **/
+      g_signal_new (I_("removed"),
+                    G_TYPE_VOLUME,
+                    G_SIGNAL_RUN_LAST,
+                    G_STRUCT_OFFSET (GVolumeIface, removed),
+                    NULL, NULL,
+                    g_cclosure_marshal_VOID__VOID,
+                    G_TYPE_NONE, 0);
+
       initialized = TRUE;
     }
 }
@@ -270,7 +291,7 @@ g_volume_can_eject (GVolume *volume)
 /**
  * g_volume_mount:
  * @volume: a #GVolume.
- * @mount_operation: a #GMountOperation.
+ * @mount_operation: a #GMountOperation or %NULL to avoid user interaction.
  * @cancellable: optional #GCancellable object, %NULL to ignore.
  * @callback: a #GAsyncReadyCallback.
  * @user_data: a #gpointer.
@@ -287,7 +308,6 @@ g_volume_mount (GVolume    *volume,
   GVolumeIface *iface;
 
   g_return_if_fail (G_IS_VOLUME (volume));
-  g_return_if_fail (G_IS_MOUNT_OPERATION (mount_operation));
 
   iface = G_VOLUME_GET_IFACE (volume);
 
index 7939e839ecc2907a8445d2e39b1e72c65cad636a..bef590ea8b1e6be451b9c1bf929dbcffcd62b97a 100644 (file)
@@ -43,6 +43,7 @@ G_BEGIN_DECLS
  * GVolumeIface:
  * @g_iface: The parent interface.
  * @changed: Changed signal that is emitted when the volume's state has changed.
+ * @removed: The removed signal that is emitted when the #GVolume have been removed. If the recipient is holding references to the object they should release them so the object can be finalized.
  * @get_name: Gets a string containing the name of the #GVolume.
  * @get_icon: Gets a #GIcon for the #GVolume.
  * @get_uuid: Gets the UUID for the #GVolume. The reference is typically based on the file system UUID for the mount in question and should be considered an opaque string. Returns %NULL if there is no UUID available.
@@ -66,6 +67,7 @@ struct _GVolumeIface
   /* signals */
 
   void (*changed) (GVolume *volume);
+  void (*removed) (GVolume *volume);
   
   /* Virtual Table */
 
index 18478fa77f1969d1c6baa3f742a685a660a0193c..726627828466dcd99602321d1bf73f530e00a908 100644 (file)
@@ -98,6 +98,9 @@ struct _GVolumeMonitorClass {
   GMount *  (*get_mount_for_uuid)   (GVolumeMonitor  *volume_monitor, 
                                      const char      *uuid);
 
+
+  GVolume * (*adopt_orphan_mount)   (GMount          *mount);
+
   /*< private >*/
   /* Padding for future expansion */
   void (*_g_reserved1) (void);
@@ -121,6 +124,8 @@ GVolume *       g_volume_monitor_get_volume_for_uuid     (GVolumeMonitor  *volum
 GMount *        g_volume_monitor_get_mount_for_uuid      (GVolumeMonitor  *volume_monitor,
                                                           const char      *uuid);
 
+GVolume *       g_volume_monitor_adopt_orphan_mount      (GMount *mount);
+
 G_END_DECLS
 
 #endif /* __G_VOLUME_MONITOR_H__ */