Author: jannis
Date: 2009-06-16 23:28:53 +0000 (Tue, 16 Jun 2009)
New Revision: 30037

Modified:
   thunar/branches/migration-to-gio/ChangeLog
   thunar/branches/migration-to-gio/thunar/main.c
   thunar/branches/migration-to-gio/thunar/thunar-application.c
   thunar/branches/migration-to-gio/thunar/thunar-application.h
Log:
        * thunar/main.c, thunar/thunar-application.{c,h}:
          thunar_application_process_filenames() now works asynchronously
          because it might have to mount the enclosing volumes of one of the
          filenames first (which is only possible asynchronously). Add new
          method thunar_application_is_processing() which returns whether
          ThunarApplication is still busy processing filenames or not. In
          main(), always enter the main loop but schedule an idle source to
          repeatedly check whether ThunarApplication has finished processing
          the command line arguments. Once this is the case, exit if there are
          no open Thunar windows. All in all, this gives us about the same
          behaviour main() had before, except that it the application might
          exit with a short delay. The result: Calling "thunar <remote URI>"
          from the shell works now!

Modified: thunar/branches/migration-to-gio/ChangeLog
===================================================================
--- thunar/branches/migration-to-gio/ChangeLog  2009-06-16 19:34:50 UTC (rev 
30036)
+++ thunar/branches/migration-to-gio/ChangeLog  2009-06-16 23:28:53 UTC (rev 
30037)
@@ -1,3 +1,19 @@
+2009-06-17     Jannis Pohlmann <jan...@xfce.org>
+
+       * thunar/main.c, thunar/thunar-application.{c,h}: 
+         thunar_application_process_filenames() now works asynchronously
+         because it might have to mount the enclosing volumes of one of the
+         filenames first (which is only possible asynchronously). Add new
+         method thunar_application_is_processing() which returns whether
+         ThunarApplication is still busy processing filenames or not. In
+         main(), always enter the main loop but schedule an idle source to
+         repeatedly check whether ThunarApplication has finished processing
+         the command line arguments. Once this is the case, exit if there are
+         no open Thunar windows. All in all, this gives us about the same 
+         behaviour main() had before, except that it the application might
+         exit with a short delay. The result: Calling "thunar <remote URI>"
+         from the shell works now!
+
 2009-06-16     Jannis Pohlmann <jan...@xfce.org>
 
        * thunar/thunar-location-entry.c: Split

Modified: thunar/branches/migration-to-gio/thunar/main.c
===================================================================
--- thunar/branches/migration-to-gio/thunar/main.c      2009-06-16 19:34:50 UTC 
(rev 30036)
+++ thunar/branches/migration-to-gio/thunar/main.c      2009-06-16 23:28:53 UTC 
(rev 30037)
@@ -39,6 +39,7 @@
 #include <thunar/thunar-dbus-client.h>
 #include <thunar/thunar-dbus-service.h>
 #include <thunar/thunar-gobject-extensions.h>
+#include <thunar/thunar-private.h>
 #include <thunar/thunar-session-client.h>
 #include <thunar/thunar-stock.h>
 
@@ -74,12 +75,43 @@
 
 
 
+static gboolean
+thunar_delayed_exit_check (gpointer user_data)
+{
+  ThunarApplication *application = user_data;
+
+  _thunar_return_val_if_fail (THUNAR_IS_APPLICATION (application), FALSE);
+
+  /* call this function again later if the application is still processing the
+   * command line arguments */
+  if (thunar_application_is_processing (application))
+    return TRUE;
+
+  /* the application has processed all command line arguments. don't call
+   * this function again if it could load at least one of them */
+  if (thunar_application_has_windows (application))
+    {
+      return FALSE;
+    }
+  else
+    {
+      /* no command line arguments opened in Thunar, exit now */
+      gtk_main_quit ();
+
+      /* don't call this function again */
+      return FALSE;
+    }
+  
+}
+
+
+
 int
 main (int argc, char **argv)
 {
   ThunarSessionClient *session_client;
 #ifdef HAVE_DBUS
-  ThunarDBusService   *dbus_service;
+  ThunarDBusService   *dbus_service = NULL;
 #endif
   ThunarApplication   *application;
   GError              *error = NULL;
@@ -241,22 +273,31 @@
   /* connect to the session manager */
   session_client = thunar_session_client_new (opt_sm_client_id);
 
-  /* do not enter the main loop, unless we have atleast one window or we are 
in daemon mode */
-  if (thunar_application_has_windows (application) || 
thunar_application_get_daemon (application))
+  /* check if the application should run as a daemon */
+  if (thunar_application_get_daemon (application))
     {
-      /* attach the D-BUS service */
 #ifdef HAVE_DBUS
+      /* attach the D-Bus service */
       dbus_service = g_object_new (THUNAR_TYPE_DBUS_SERVICE, NULL);
 #endif
+    }
+  else
+    {
+      /* processing the command line arguments is done asynchronously. Thus, we
+       * schedule an idle source which repeatedly checks whether we are done
+       * processing. Once we're done, it'll make the application quit if there
+       * are no open windows */
+      g_idle_add_full (G_PRIORITY_LOW, thunar_delayed_exit_check, 
+                       g_object_ref (application), g_object_unref);
+    }
 
-      /* enter the main loop */
-      gtk_main ();
+  /* enter the main loop */
+  gtk_main ();
 
-      /* detach the D-BUS service */
 #ifdef HAVE_DBUS
-      g_object_unref (G_OBJECT (dbus_service));
+  if (dbus_service != NULL)
+    g_object_unref (G_OBJECT (dbus_service));
 #endif
-    }
 
   /* disconnect from the session manager */
   g_object_unref (G_OBJECT (session_client));

Modified: thunar/branches/migration-to-gio/thunar/thunar-application.c
===================================================================
--- thunar/branches/migration-to-gio/thunar/thunar-application.c        
2009-06-16 19:34:50 UTC (rev 30036)
+++ thunar/branches/migration-to-gio/thunar/thunar-application.c        
2009-06-16 23:28:53 UTC (rev 30037)
@@ -64,56 +64,57 @@
 
 
 
-static void       thunar_application_class_init             
(ThunarApplicationClass *klass);
-static void       thunar_application_init                   (ThunarApplication 
     *application);
-static void       thunar_application_finalize               (GObject           
     *object);
-static void       thunar_application_get_property           (GObject           
     *object,
-                                                             guint             
      prop_id,
-                                                             GValue            
     *value,
-                                                             GParamSpec        
     *pspec);
-static void       thunar_application_set_property           (GObject           
     *object,
-                                                             guint             
      prop_id,
-                                                             const GValue      
     *value,
-                                                             GParamSpec        
     *pspec);
-static void       thunar_application_collect_and_launch     (ThunarApplication 
     *application,
-                                                             gpointer          
      parent,
-                                                             const gchar       
     *icon_name,
-                                                             const gchar       
     *title,
-                                                             Launcher          
      launcher,
-                                                             GList             
     *source_file_list,
-                                                             GFile             
     *target_file,
-                                                             GClosure          
     *new_files_closure);
-static void       thunar_application_launch                 (ThunarApplication 
     *application,
-                                                             gpointer          
      parent,
-                                                             const gchar       
     *icon_name,
-                                                             const gchar       
     *title,
-                                                             Launcher          
      launcher,
-                                                             GList             
     *source_path_list,
-                                                             GList             
     *target_path_list,
-                                                             GClosure          
     *new_files_closure);
-static GtkWidget *thunar_application_open_window_with_role  (ThunarApplication 
     *application,
-                                                             const gchar       
     *role,
-                                                             ThunarFile        
     *directory,
-                                                             GdkScreen         
     *screen);
-static void       thunar_application_window_destroyed       (GtkWidget         
     *window,
-                                                             ThunarApplication 
     *application);
-static void       thunar_application_drive_connected        (GVolumeMonitor    
     *volume_monitor,
-                                                             GDrive            
     *drive,
-                                                             ThunarApplication 
     *application);
-static void       thunar_application_drive_disconnected     (GVolumeMonitor    
     *volume_monitor,
-                                                             GDrive            
     *drive,
-                                                             ThunarApplication 
     *application);
-static void       thunar_application_drive_eject            (GVolumeMonitor    
     *volume_monitor,
-                                                             GDrive            
     *drive,
-                                                             ThunarApplication 
     *application);
-static gboolean   thunar_application_volman_idle            (gpointer          
      user_data);
-static void       thunar_application_volman_idle_destroy    (gpointer          
      user_data);
-static void       thunar_application_volman_watch           (GPid              
      pid,
-                                                             gint              
      status,
-                                                             gpointer          
      user_data);
-static void       thunar_application_volman_watch_destroy   (gpointer          
      user_data);
-static gboolean   thunar_application_show_dialogs           (gpointer          
      user_data);
-static void       thunar_application_show_dialogs_destroy   (gpointer          
      user_data);
+static void           thunar_application_class_init             
(ThunarApplicationClass *klass);
+static void           thunar_application_init                   
(ThunarApplication      *application);
+static void           thunar_application_finalize               (GObject       
         *object);
+static void           thunar_application_get_property           (GObject       
         *object,
+                                                                 guint         
          prop_id,
+                                                                 GValue        
         *value,
+                                                                 GParamSpec    
         *pspec);
+static void           thunar_application_set_property           (GObject       
         *object,
+                                                                 guint         
          prop_id,
+                                                                 const GValue  
         *value,
+                                                                 GParamSpec    
         *pspec);
+static void           thunar_application_collect_and_launch     
(ThunarApplication      *application,
+                                                                 gpointer      
          parent,
+                                                                 const gchar   
         *icon_name,
+                                                                 const gchar   
         *title,
+                                                                 Launcher      
          launcher,
+                                                                 GList         
         *source_file_list,
+                                                                 GFile         
         *target_file,
+                                                                 GClosure      
         *new_files_closure);
+static void           thunar_application_launch                 
(ThunarApplication      *application,
+                                                                 gpointer      
          parent,
+                                                                 const gchar   
         *icon_name,
+                                                                 const gchar   
         *title,
+                                                                 Launcher      
          launcher,
+                                                                 GList         
         *source_path_list,
+                                                                 GList         
         *target_path_list,
+                                                                 GClosure      
         *new_files_closure);
+static GtkWidget     *thunar_application_open_window_with_role  
(ThunarApplication      *application,
+                                                                 const gchar   
         *role,
+                                                                 ThunarFile    
         *directory,
+                                                                 GdkScreen     
         *screen);
+static void           thunar_application_window_destroyed       (GtkWidget     
         *window,
+                                                                 
ThunarApplication      *application);
+static void           thunar_application_drive_connected        
(GVolumeMonitor         *volume_monitor,
+                                                                 GDrive        
         *drive,
+                                                                 
ThunarApplication      *application);
+static void           thunar_application_drive_disconnected     
(GVolumeMonitor         *volume_monitor,
+                                                                 GDrive        
         *drive,
+                                                                 
ThunarApplication      *application);
+static void           thunar_application_drive_eject            
(GVolumeMonitor         *volume_monitor,
+                                                                 GDrive        
         *drive,
+                                                                 
ThunarApplication      *application);
+static gboolean       thunar_application_volman_idle            (gpointer      
          user_data);
+static void           thunar_application_volman_idle_destroy    (gpointer      
          user_data);
+static void           thunar_application_volman_watch           (GPid          
          pid,
+                                                                 gint          
          status,
+                                                                 gpointer      
          user_data);
+static void           thunar_application_volman_watch_destroy   (gpointer      
          user_data);
+static gboolean       thunar_application_show_dialogs           (gpointer      
          user_data);
+static void           thunar_application_show_dialogs_destroy   (gpointer      
          user_data);
+static void           thunar_application_process_files          
(ThunarApplication      *application);
 
 
 
@@ -138,11 +139,14 @@
   GSList                *volman_udis;
   guint                  volman_idle_id;
   guint                  volman_watch_id;
+
+  GList                 *files_to_launch;
 };
 
 
 
 static GObjectClass *thunar_application_parent_class;
+static GQuark        thunar_application_screen_quark;
 
 
 
@@ -180,6 +184,10 @@
 {
   GObjectClass *gobject_class;
  
+  /* pre-allocate the required quarks */
+  thunar_application_screen_quark = 
+    g_quark_from_static_string ("thunar-application-screen");
+
   /* determine the parent type class */
   thunar_application_parent_class = g_type_class_peek_parent (klass);
 
@@ -215,6 +223,8 @@
   /* initialize the application */
   application->preferences = thunar_preferences_get ();
 
+  application->files_to_launch = NULL;
+
   /* check if we have a saved accel map */
   path = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, "Thunar/accels.scm");
   if (G_LIKELY (path != NULL))
@@ -242,6 +252,9 @@
   gchar             *path;
   GList             *lp;
 
+  /* unqueue all files waiting to be processed */
+  thunar_file_list_free (application->files_to_launch);
+
   /* save the current accel map */
   path = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, 
"Thunar/accels.scm", TRUE);
   if (G_LIKELY (path != NULL))
@@ -1040,6 +1053,107 @@
 
 
 
+static void
+thunar_application_process_files_finish (GObject      *object,
+                                         GAsyncResult *result,
+                                         gpointer      user_data)
+{ 
+  ThunarApplication *application = THUNAR_APPLICATION (user_data);
+  ThunarFile        *file;
+  GdkScreen         *screen;
+  GError            *error = NULL;
+
+  _thunar_return_if_fail (G_IS_FILE (object));
+  _thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
+  _thunar_return_if_fail (THUNAR_IS_APPLICATION (application));
+  _thunar_return_if_fail (application->files_to_launch != NULL);
+  _thunar_return_if_fail (THUNAR_IS_FILE (application->files_to_launch->data));
+
+  /* finish mounting the volume */
+  if (!g_file_mount_enclosing_volume_finish (G_FILE (object), result, &error))
+    {
+      /* ignore already mounted and not supported errors */
+      if (error->domain == G_IO_ERROR && error->code == 
G_IO_ERROR_ALREADY_MOUNTED)
+        g_clear_error (&error);
+      else if (error->domain == G_IO_ERROR && error->code == 
G_IO_ERROR_NOT_SUPPORTED)
+        g_clear_error (&error);
+    }
+
+  /* get the current file */
+  file = THUNAR_FILE (application->files_to_launch->data);
+
+  /* determine and reset the screen of the file */
+  screen = g_object_get_qdata (G_OBJECT (file), 
thunar_application_screen_quark);
+  g_object_set_qdata (G_OBJECT (file), thunar_application_screen_quark, NULL);
+
+  /* check if mounting succeeded */
+  if (error == NULL)
+    {
+      /* try to open the file or directory */
+      thunar_file_launch (file, screen, &error);
+    }
+
+  if (error != NULL)
+    {
+      /* tell the user that we were unable to launch the file specified */
+      thunar_dialogs_show_error (screen, error, _("Failed to open \"%s\""), 
+                                 thunar_file_get_display_name (file));
+
+      /* stop processing files */
+      thunar_file_list_free (application->files_to_launch);
+      application->files_to_launch = NULL;
+    }
+  else
+    {
+      /* release the file */
+      g_object_unref (file);
+
+      /* remove the file item from the list */
+      application->files_to_launch = g_list_delete_link 
(application->files_to_launch, 
+                                                         
application->files_to_launch);
+
+      /* continue processing the next file */
+      thunar_application_process_files (application);
+    }
+}
+
+
+
+static void
+thunar_application_process_files (ThunarApplication *application)
+{
+  GMountOperation *mount_operation;
+  ThunarFile      *file;
+  GdkScreen       *screen;
+  GFile           *location;
+
+  _thunar_return_if_fail (THUNAR_IS_APPLICATION (application));
+  
+  /* don't do anything if no files are to be processed */
+  if (application->files_to_launch == NULL)
+    return;
+
+  /* get the next file */
+  file = THUNAR_FILE (application->files_to_launch->data);
+
+  /* create a GTK+ mount operation */
+  mount_operation = gtk_mount_operation_new (NULL);
+  screen = g_object_get_qdata (G_OBJECT (file), 
thunar_application_screen_quark);
+  gtk_mount_operation_set_screen (GTK_MOUNT_OPERATION (mount_operation), 
screen);
+
+  /* determine the location of the file */
+  location = thunar_file_get_file (file);
+
+  /* try to mount the enclosing volume asynchronously. Thunar will launch files
+   * that are accessible in the mount callback */
+  g_file_mount_enclosing_volume (location, G_MOUNT_MOUNT_NONE,
+                                 mount_operation, NULL,
+                                 thunar_application_process_files_finish,
+                                 application);
+}
+
+
+
 /**
  * thunar_application_process_filenames:
  * @application       : a #ThunarApplication.
@@ -1096,37 +1210,53 @@
 
       /* verify that we have a valid file */
       if (G_LIKELY (file != NULL))
-        file_list = g_list_append (file_list, file);
+        {
+          file_list = g_list_append (file_list, file);
+        }
       else
-        goto failure;
+        {
+          /* tell the user that we were unable to launch the file specified */
+          thunar_dialogs_show_error (screen, derror, _("Failed to open 
\"%s\""), 
+                                     filenames[n]);
+
+          g_set_error (error, derror->domain, derror->code, 
+                       _("Failed to open \"%s\": %s"), filenames[n], 
derror->message);
+          g_error_free (derror);
+
+          thunar_file_list_free (file_list);
+
+          return FALSE;
+        }
     }
 
-  /* ok, let's try to launch the given files then */
+  /* loop over all files */
   for (lp = file_list; lp != NULL; lp = lp->next)
     {
-      /* try to launch this file, display an error dialog if that fails */
-      if (!thunar_file_launch (lp->data, screen, &derror))
-        {
-          /* tell the user that we were unable to launch the file specified on 
the cmdline */
-          thunar_dialogs_show_error (screen, derror, _("Failed to open 
\"%s\""), thunar_file_get_display_name (lp->data));
-          g_error_free (derror);
-          break;
-        }
+      /* remember the screen to launch the file on */
+      g_object_set_qdata (G_OBJECT (lp->data), 
thunar_application_screen_quark, screen);
+
+      /* append the file to the list of files we need to launch */
+      application->files_to_launch = g_list_append 
(application->files_to_launch, 
+                                                    lp->data);
     }
 
-  /* release all files */
-  thunar_file_list_free (file_list);
+  /* start processing files if we have any to launch */
+  if (application->files_to_launch != NULL)
+    thunar_application_process_files (application);
 
+  /* free the file list */
+  g_list_free (file_list);
+
   return TRUE;
+}
 
-failure:
-  /* tell the user that we were unable to launch the file specified on the 
cmdline */
-  thunar_dialogs_show_error (screen, derror, _("Failed to open \"%s\""), 
filenames[n]);
 
-  g_set_error (error, derror->domain, derror->code, _("Failed to open \"%s\": 
%s"), filenames[n], derror->message);
-  thunar_file_list_free (file_list);
-  g_error_free (derror);
-  return FALSE;
+
+gboolean
+thunar_application_is_processing (ThunarApplication *application)
+{
+  _thunar_return_val_if_fail (THUNAR_IS_APPLICATION (application), FALSE);
+  return application->files_to_launch != NULL;
 }
 
 

Modified: thunar/branches/migration-to-gio/thunar/thunar-application.h
===================================================================
--- thunar/branches/migration-to-gio/thunar/thunar-application.h        
2009-06-16 19:34:50 UTC (rev 30036)
+++ thunar/branches/migration-to-gio/thunar/thunar-application.h        
2009-06-16 23:28:53 UTC (rev 30037)
@@ -68,6 +68,8 @@
                                                          GdkScreen         
*screen,
                                                          GError           
**error);
 
+gboolean           thunar_application_is_processing     (ThunarApplication 
*application);
+
 void               thunar_application_copy_to           (ThunarApplication 
*application,
                                                          gpointer           
parent,
                                                          GList             
*source_file_list,

_______________________________________________
Xfce4-commits mailing list
Xfce4-commits@xfce.org
http://foo-projects.org/mailman/listinfo/xfce4-commits

Reply via email to