[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