[Xfce4-commits] <thunar:nick/1.8> Port ThunarFolder to GTask.

Nick Schermer noreply at xfce.org
Sun Aug 4 21:52:04 CEST 2013


Updating branch refs/heads/nick/1.8
         to dc1f8d6c46098939d1024e0ba77fc777b2771cd2 (commit)
       from e8716ceff38197bc75d4aabd8afbe31b9aec78cd (commit)

commit dc1f8d6c46098939d1024e0ba77fc777b2771cd2
Author: Nick Schermer <nick at xfce.org>
Date:   Sat Aug 3 20:07:30 2013 +0200

    Port ThunarFolder to GTask.

 thunar/thunar-folder.c            |  132 ++++++++++++------------------
 thunar/thunar-io-jobs.c           |   74 ++++-------------
 thunar/thunar-io-jobs.h           |    5 +-
 thunar/thunar-io-scan-directory.c |  160 +++++++++++++++++++++++++++++++++++--
 thunar/thunar-io-scan-directory.h |    9 +++
 5 files changed, 231 insertions(+), 149 deletions(-)

diff --git a/thunar/thunar-folder.c b/thunar/thunar-folder.c
index bc1dcdf..d305404 100644
--- a/thunar/thunar-folder.c
+++ b/thunar/thunar-folder.c
@@ -64,14 +64,6 @@ static void     thunar_folder_set_property                (GObject
                                                            const GValue           *value,
                                                            GParamSpec             *pspec);
 static void     thunar_folder_real_destroy                (ThunarFolder           *folder);
-static void     thunar_folder_error                       (ExoJob                 *job,
-                                                           GError                 *error,
-                                                           ThunarFolder           *folder);
-static gboolean thunar_folder_files_ready                 (ThunarJob              *job,
-                                                           GList                  *files,
-                                                           ThunarFolder           *folder);
-static void     thunar_folder_finished                    (ExoJob                 *job,
-                                                           ThunarFolder           *folder);
 static void     thunar_folder_file_changed                (ThunarFileMonitor      *file_monitor,
                                                            ThunarFile             *file,
                                                            ThunarFolder           *folder);
@@ -104,10 +96,9 @@ struct _ThunarFolder
 {
   GObject __parent__;
 
-  ThunarJob         *job;
+  GTask             *task;
 
   ThunarFile        *corresponding_file;
-  GList             *new_files;
   GList             *files;
 
   GList             *content_type_ptr;
@@ -286,12 +277,11 @@ thunar_folder_finalize (GObject *object)
       g_object_unref (folder->monitor);
     }
 
-  /* cancel the pending job (if any) */
-  if (G_UNLIKELY (folder->job != NULL))
+  /* cancel the pending task (if any) */
+  if (G_UNLIKELY (folder->task != NULL))
     {
-      g_signal_handlers_disconnect_matched (folder->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, folder);
-      g_object_unref (folder->job);
-      folder->job = NULL;
+      g_object_unref (folder->task);
+      folder->task = NULL;
     }
 
   /* disconnect from the corresponding file */
@@ -306,9 +296,6 @@ thunar_folder_finalize (GObject *object)
   if (folder->content_type_idle_id != 0)
     g_source_remove (folder->content_type_idle_id);
 
-  /* release references to the new files */
-  thunar_g_file_list_free (folder->new_files);
-
   /* release references to the current files */
   thunar_g_file_list_free (folder->files);
 
@@ -377,38 +364,6 @@ thunar_folder_real_destroy (ThunarFolder *folder)
 
 
 
-static void
-thunar_folder_error (ExoJob       *job,
-                     GError       *error,
-                     ThunarFolder *folder)
-{
-  _thunar_return_if_fail (THUNAR_IS_FOLDER (folder));
-  _thunar_return_if_fail (THUNAR_IS_JOB (job));
-
-  /* tell the consumer about the problem */
-  g_signal_emit (G_OBJECT (folder), folder_signals[ERROR], 0, error);
-}
-
-
-
-static gboolean
-thunar_folder_files_ready (ThunarJob    *job,
-                           GList        *files,
-                           ThunarFolder *folder)
-{
-  _thunar_return_val_if_fail (THUNAR_IS_FOLDER (folder), FALSE);
-  _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE);
-  _thunar_return_val_if_fail (folder->monitor == NULL, FALSE);
-
-  /* merge the list with the existing list of new files */
-  folder->new_files = g_list_concat (folder->new_files, files);
-
-  /* indicate that we took over ownership of the file list */
-  return TRUE;
-}
-
-
-
 static gboolean
 thunar_folder_content_type_loader_idle (gpointer data)
 {
@@ -460,24 +415,44 @@ thunar_folder_content_type_loader (ThunarFolder *folder)
 
 
 static void
-thunar_folder_finished (ExoJob       *job,
-                        ThunarFolder *folder)
+thunar_folder_finished (GObject      *source_object,
+                        GAsyncResult *result,
+                        gpointer      user_data)
 {
-  ThunarFile *file;
-  GList      *files;
-  GList      *lp;
+  ThunarFolder *folder = THUNAR_FOLDER (source_object);
+  ThunarFile   *file;
+  GList        *files;
+  GList        *lp;
+  GList        *new_files;
+  GError       *error = NULL;
 
   _thunar_return_if_fail (THUNAR_IS_FOLDER (folder));
-  _thunar_return_if_fail (THUNAR_IS_JOB (job));
   _thunar_return_if_fail (THUNAR_IS_FILE (folder->corresponding_file));
   _thunar_return_if_fail (folder->monitor == NULL);
+  _thunar_return_if_fail (folder->task == G_TASK (result));
   _thunar_return_if_fail (folder->content_type_idle_id == 0);
 
+  /* check if everything went fine */
+  new_files = g_task_propagate_pointer (folder->task, &error);
+  if (error != NULL)
+    {
+      /* something when wrong */
+      _thunar_assert (new_files == NULL);
+      g_signal_emit (G_OBJECT (folder), folder_signals[ERROR], 0, error);
+      g_error_free (error);
+
+      /* remove the task */
+      g_object_unref (folder->task);
+      folder->task = NULL;
+
+      return;
+    }
+
   /* check if we need to merge new files with existing files */
   if (G_UNLIKELY (folder->files != NULL))
     {
       /* determine all added files (files on new_files, but not on files) */
-      for (files = NULL, lp = folder->new_files; lp != NULL; lp = lp->next)
+      for (files = NULL, lp = new_files; lp != NULL; lp = lp->next)
         if (g_list_find (folder->files, lp->data) == NULL)
           {
             /* put the file on the added list */
@@ -508,7 +483,7 @@ thunar_folder_finished (ExoJob       *job,
           lp = lp->next;
 
           /* check if the file is not on new_files */
-          if (g_list_find (folder->new_files, file) == NULL)
+          if (g_list_find (new_files, file) == NULL)
             {
               /* put the file on the removed list (owns the reference now) */
               files = g_list_prepend (files, file);
@@ -529,14 +504,12 @@ thunar_folder_finished (ExoJob       *job,
         }
 
       /* drop the temporary new_files list */
-      thunar_g_file_list_free (folder->new_files);
-      folder->new_files = NULL;
+      thunar_g_file_list_free (new_files);
     }
   else
     {
       /* just use the new files for the files list */
-      folder->files = folder->new_files;
-      folder->new_files = NULL;
+      folder->files = new_files;
 
       if (folder->files != NULL)
         {
@@ -546,9 +519,8 @@ thunar_folder_finished (ExoJob       *job,
     }
 
   /* we did it, the folder is loaded */
-  g_signal_handlers_disconnect_matched (folder->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, folder);
-  g_object_unref (folder->job);
-  folder->job = NULL;
+  g_object_unref (folder->task);
+  folder->task = NULL;
 
   /* restart the content type idle loader */
   thunar_folder_content_type_loader (folder);
@@ -705,7 +677,6 @@ thunar_folder_monitor (GFileMonitor     *monitor,
   _thunar_return_if_fail (G_IS_FILE_MONITOR (monitor));
   _thunar_return_if_fail (THUNAR_IS_FOLDER (folder));
   _thunar_return_if_fail (folder->monitor == monitor);
-  _thunar_return_if_fail (folder->job == NULL);
   _thunar_return_if_fail (THUNAR_IS_FILE (folder->corresponding_file));
   _thunar_return_if_fail (G_IS_FILE (event_file));
 
@@ -881,7 +852,7 @@ gboolean
 thunar_folder_get_loading (const ThunarFolder *folder)
 {
   _thunar_return_val_if_fail (THUNAR_IS_FOLDER (folder), FALSE);
-  return (folder->job != NULL);
+  return (folder->task != NULL);
 }
 
 
@@ -896,6 +867,8 @@ thunar_folder_get_loading (const ThunarFolder *folder)
 void
 thunar_folder_reload (ThunarFolder *folder)
 {
+  GCancellable *cancellable;
+
   _thunar_return_if_fail (THUNAR_IS_FOLDER (folder));
 
   /* stop metadata collector */
@@ -903,12 +876,12 @@ thunar_folder_reload (ThunarFolder *folder)
     g_source_remove (folder->content_type_idle_id);
 
   /* check if we are currently connect to a job */
-  if (G_UNLIKELY (folder->job != NULL))
+  if (G_UNLIKELY (folder->task != NULL))
     {
-      /* disconnect from the job */
-      g_signal_handlers_disconnect_matched (folder->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, folder);
-      g_object_unref (folder->job);
-      folder->job = NULL;
+      /* stop the task */
+      g_task_return_error_if_cancelled (folder->task);
+      g_object_unref (folder->task);
+      folder->task = NULL;
     }
 
   /* disconnect from the file alteration monitor */
@@ -920,15 +893,12 @@ thunar_folder_reload (ThunarFolder *folder)
       folder->monitor = NULL;
     }
 
-  /* reset the new_files list */
-  thunar_g_file_list_free (folder->new_files);
-  folder->new_files = NULL;
-
-  /* start a new job */
-  folder->job = thunar_io_jobs_list_directory (thunar_file_get_file (folder->corresponding_file));
-  g_signal_connect (folder->job, "error", G_CALLBACK (thunar_folder_error), folder);
-  g_signal_connect (folder->job, "finished", G_CALLBACK (thunar_folder_finished), folder);
-  g_signal_connect (folder->job, "files-ready", G_CALLBACK (thunar_folder_files_ready), folder);
+  /* start a new task */
+  cancellable = g_cancellable_new ();
+  folder->task = g_task_new (folder, cancellable, thunar_folder_finished, NULL);
+  g_task_set_task_data (folder->task, thunar_file_get_file (folder->corresponding_file), NULL);
+  g_task_run_in_thread (folder->task, thunar_io_jobs_list_directory);
+  g_object_unref (cancellable);
 
   /* tell all consumers that we're loading */
   g_object_notify (G_OBJECT (folder), "loading");
diff --git a/thunar/thunar-io-jobs.c b/thunar/thunar-io-jobs.c
index 9d904f9..c9dd3e6 100644
--- a/thunar/thunar-io-jobs.c
+++ b/thunar/thunar-io-jobs.c
@@ -1165,79 +1165,33 @@ thunar_io_jobs_change_mode (GList         *files,
 
 
 
-static gboolean
-_thunar_io_jobs_ls (ThunarJob  *job,
-                    GArray     *param_values,
-                    GError    **error)
+void
+thunar_io_jobs_list_directory (GTask        *task,
+                               gpointer      source_object,
+                               gpointer      task_data,
+                               GCancellable *cancellable)
 {
+  GFile  *directory = G_FILE (task_data);
+  GList  *file_list;
   GError *err = NULL;
-  GFile  *directory;
-  GList  *file_list = NULL;
-
-  _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE);
-  _thunar_return_val_if_fail (param_values != NULL, FALSE);
-  _thunar_return_val_if_fail (param_values->len == 1, FALSE);
-  _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-  if (exo_job_set_error_if_cancelled (EXO_JOB (job), error))
-    return FALSE;
-
-  /* determine the directory to list */
-  directory = g_value_get_object (&g_array_index (param_values, GValue, 0));
 
-  /* make sure the object is valid */
-  _thunar_assert (G_IS_FILE (directory));
+  _thunar_return_if_fail (G_IS_FILE (task_data));
 
   /* collect directory contents (non-recursively) */
-  file_list = thunar_io_scan_directory (job, directory,
+  file_list = thunar_io_scan_directory2 (directory, cancellable,
                                         G_FILE_QUERY_INFO_NONE, 
                                         FALSE, FALSE, TRUE, &err);
 
   /* abort on errors or cancellation */
   if (err != NULL)
     {
-      g_propagate_error (error, err);
-      return FALSE;
-    }
-  else if (exo_job_set_error_if_cancelled (EXO_JOB (job), &err))
-    {
-      g_propagate_error (error, err);
-      return FALSE;
-    }
-
-  /* check if we have any files to report */
-  if (G_LIKELY (file_list != NULL))
-    {
-      /* emit the "files-ready" signal */
-      if (!thunar_job_files_ready (THUNAR_JOB (job), file_list))
-        {
-          /* none of the handlers took over the file list, so it's up to us
-           * to destroy it */
-          thunar_g_file_list_free (file_list);
-        }
-    }
-  
-  /* there should be no errors here */
-  _thunar_assert (err == NULL);
-
-  /* propagate cancellation error */
-  if (exo_job_set_error_if_cancelled (EXO_JOB (job), &err))
-    {
-      g_propagate_error (error, err);
-      return FALSE;
+      _thunar_assert (file_list == NULL);
+      g_task_return_error (task, err);
+      return;
     }
 
-  return TRUE;
-}
-
-
-
-ThunarJob *
-thunar_io_jobs_list_directory (GFile *directory)
-{
-  _thunar_return_val_if_fail (G_IS_FILE (directory), NULL);
-  
-  return thunar_simple_job_launch (_thunar_io_jobs_ls, 1, G_TYPE_FILE, directory);
+  /* we've got the files */
+  g_task_return_pointer (task, file_list, NULL);
 }
 
 
diff --git a/thunar/thunar-io-jobs.h b/thunar/thunar-io-jobs.h
index 51dc682..82b1aa2 100644
--- a/thunar/thunar-io-jobs.h
+++ b/thunar/thunar-io-jobs.h
@@ -48,7 +48,10 @@ ThunarJob *thunar_io_jobs_change_mode      (GList         *files,
                                             ThunarFileMode file_mask,
                                             ThunarFileMode file_mode,
                                             gboolean       recursive) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-ThunarJob *thunar_io_jobs_list_directory   (GFile         *directory) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+void       thunar_io_jobs_list_directory   (GTask          *task,
+                                            gpointer        source_object,
+                                            gpointer        task_data,
+                                            GCancellable   *cancellable);
 ThunarJob *thunar_io_jobs_rename_file      (ThunarFile    *file,
                                             const gchar   *display_name) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
 
diff --git a/thunar/thunar-io-scan-directory.c b/thunar/thunar-io-scan-directory.c
index 66ddbdf..f5f2ee8 100644
--- a/thunar/thunar-io-scan-directory.c
+++ b/thunar/thunar-io-scan-directory.c
@@ -31,7 +31,153 @@
 #include <thunar/thunar-private.h>
 #include <thunar/thunar-io-scan-directory.h>
 
+GList *
+thunar_io_scan_directory2 (GFile              *file,
+                          GCancellable       *cancellable,
+                          GFileQueryInfoFlags flags,
+                          gboolean            recursively,
+                          gboolean            unlinking,
+                          gboolean            return_thunar_files,
+                          GError            **error)
+{
+  GFileEnumerator *enumerator;
+  GFileInfo       *info;
+  GFileType        type;
+  GError          *err = NULL;
+  GFile           *child_file;
+  GList           *child_files = NULL;
+  GList           *files = NULL;
+  const gchar     *namespace;
+  ThunarFile      *thunar_file;
+  gboolean         is_mounted;
+
+  _thunar_return_val_if_fail (G_IS_CANCELLABLE (cancellable), NULL);
+  _thunar_return_val_if_fail (G_IS_FILE (file), NULL);
+  _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  /* abort if the job was cancelled */
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return NULL;
+
+  /* don't recurse when we are scanning prior to unlinking and the current
+   * file/dir is in the trash. In GVfs, only the top-level directories in
+   * the trash can be modified and deleted directly. See
+   * http://bugzilla.xfce.org/show_bug.cgi?id=7147
+   * for more information */
+  if (unlinking
+      && thunar_g_file_is_trashed (file)
+      && !thunar_g_file_is_root (file))
+    {
+      return NULL;
+    }
+
+  /* query the file type */
+  type = g_file_query_file_type (file, flags, cancellable);
+
+  /* abort if the job was cancelled */
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return NULL;
+
+  /* ignore non-directory nodes */
+  if (type != G_FILE_TYPE_DIRECTORY)
+    return NULL;
+
+  /* determine the namespace */
+  if (return_thunar_files)
+    namespace = THUNARX_FILE_INFO_NAMESPACE;
+  else
+    namespace = G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+                G_FILE_ATTRIBUTE_STANDARD_NAME;
+
+  /* try to read from the direectory */
+  enumerator = g_file_enumerate_children (file, namespace,
+                                          flags, cancellable,
+                                          &err);
+
+  /* abort if there was an error or the job was cancelled */
+  if (err != NULL)
+    {
+      g_propagate_error (error, err);
+      return NULL;
+    }
+
+  /* iterate over children one by one */
+  while (!g_cancellable_is_cancelled (cancellable))
+    {
+      /* query info of the child */
+      info = g_file_enumerator_next_file (enumerator,
+                                          cancellable,
+                                          &err);
+
+      if (G_UNLIKELY (info == NULL))
+        break;
+
+      is_mounted = TRUE;
+      if (err != NULL)
+        {
+          if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED))
+            {
+              is_mounted = FALSE;
+              g_clear_error (&err);
+            }
+          else
+            {
+              /* break on errors */
+              break;
+            }
+        }
 
+      /* create GFile for the child */
+      child_file = g_file_get_child (file, g_file_info_get_name (info));
+
+      if (return_thunar_files)
+        {
+          /* Prepend the ThunarFile */
+          thunar_file = thunar_file_get_with_info (child_file, info, !is_mounted);
+          files = thunar_g_file_list_prepend (files, thunar_file);
+          g_object_unref (G_OBJECT (thunar_file));
+        }
+      else
+        {
+          /* Prepend the GFile */
+          files = thunar_g_file_list_prepend (files, child_file);
+        }
+
+      /* if the child is a directory and we need to recurse ... just do so */
+      if (recursively
+          && is_mounted
+          && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+        {
+          child_files = thunar_io_scan_directory2 (child_file, cancellable, flags, recursively,
+                                                  unlinking, return_thunar_files, &err);
+
+          /* prepend children to the file list to make sure they're
+           * processed first (required for unlinking) */
+          files = g_list_concat (child_files, files);
+        }
+
+      g_object_unref (child_file);
+      g_object_unref (info);
+    }
+
+  /* release the enumerator */
+  g_object_unref (enumerator);
+
+  if (G_UNLIKELY (err != NULL))
+    {
+      g_propagate_error (error, err);
+      thunar_g_file_list_free (files);
+      return NULL;
+    }
+  else if (g_cancellable_set_error_if_cancelled (cancellable, &err))
+    {
+      g_propagate_error (error, err);
+      thunar_g_file_list_free (files);
+      return NULL;
+    }
+
+  return files;
+}
 
 GList *
 thunar_io_scan_directory (ThunarJob          *job,
@@ -52,7 +198,7 @@ thunar_io_scan_directory (ThunarJob          *job,
   const gchar     *namespace;
   ThunarFile      *thunar_file;
   gboolean         is_mounted;
-  
+
   _thunar_return_val_if_fail (THUNAR_IS_JOB (job), NULL);
   _thunar_return_val_if_fail (G_IS_FILE (file), NULL);
   _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL);
@@ -61,8 +207,8 @@ thunar_io_scan_directory (ThunarJob          *job,
   if (exo_job_set_error_if_cancelled (EXO_JOB (job), error))
     return NULL;
 
-  /* don't recurse when we are scanning prior to unlinking and the current 
-   * file/dir is in the trash. In GVfs, only the top-level directories in 
+  /* don't recurse when we are scanning prior to unlinking and the current
+   * file/dir is in the trash. In GVfs, only the top-level directories in
    * the trash can be modified and deleted directly. See
    * http://bugzilla.xfce.org/show_bug.cgi?id=7147
    * for more information */
@@ -108,7 +254,7 @@ thunar_io_scan_directory (ThunarJob          *job,
     {
       /* query info of the child */
       info = g_file_enumerator_next_file (enumerator,
-                                          exo_job_get_cancellable (EXO_JOB (job)), 
+                                          exo_job_get_cancellable (EXO_JOB (job)),
                                           &err);
 
       if (G_UNLIKELY (info == NULL))
@@ -150,10 +296,10 @@ thunar_io_scan_directory (ThunarJob          *job,
           && is_mounted
           && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
         {
-          child_files = thunar_io_scan_directory (job, child_file, flags, recursively, 
+          child_files = thunar_io_scan_directory (job, child_file, flags, recursively,
                                                   unlinking, return_thunar_files, &err);
 
-          /* prepend children to the file list to make sure they're 
+          /* prepend children to the file list to make sure they're
            * processed first (required for unlinking) */
           files = g_list_concat (child_files, files);
         }
@@ -177,6 +323,6 @@ thunar_io_scan_directory (ThunarJob          *job,
       thunar_g_file_list_free (files);
       return NULL;
     }
-  
+
   return files;
 }
diff --git a/thunar/thunar-io-scan-directory.h b/thunar/thunar-io-scan-directory.h
index 8137d6a..199ee05 100644
--- a/thunar/thunar-io-scan-directory.h
+++ b/thunar/thunar-io-scan-directory.h
@@ -28,6 +28,15 @@
 
 G_BEGIN_DECLS
 
+GList *
+thunar_io_scan_directory2 (GFile              *file,
+                          GCancellable       *cancellable,
+                          GFileQueryInfoFlags flags,
+                          gboolean            recursively,
+                          gboolean            unlinking,
+                          gboolean            return_thunar_files,
+                          GError            **error);
+
 GList *thunar_io_scan_directory (ThunarJob          *job,
                                  GFile              *file,
                                  GFileQueryInfoFlags flags,


More information about the Xfce4-commits mailing list