summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarlos Soriano <csoriano@gnome.org>2016-09-06 17:27:12 +0200
committerCarlos Soriano <csoriano@gnome.org>2016-09-07 16:10:02 +0200
commit819546836462408022b1ebf8f5d8569542dfa831 (patch)
tree263679c235b96f5876671c76b9106f7c00c3517b /src
parent35ca20ce4ba350269ebf879ce529d2bb64cd27bb (diff)
downloadnautilus-819546836462408022b1ebf8f5d8569542dfa831.tar.gz
batch-rename-dialog: use GTask appropiately
The Gtask has to finish only when all the internal async call are ready, doing the other way around is conceptually wrong and will cause problems if we rely on the task for checking the status of the general operation. For that implement a correct GTask handling, waitig with a mutex and condition for all async calls to be ready, and only then mark the task as finished. https://bugzilla.gnome.org/show_bug.cgi?id=770586
Diffstat (limited to 'src')
-rw-r--r--src/nautilus-batch-rename-dialog.c246
1 files changed, 173 insertions, 73 deletions
diff --git a/src/nautilus-batch-rename-dialog.c b/src/nautilus-batch-rename-dialog.c
index c43135311..9f7c3b2f6 100644
--- a/src/nautilus-batch-rename-dialog.c
+++ b/src/nautilus-batch-rename-dialog.c
@@ -82,17 +82,12 @@ struct _NautilusBatchRenameDialog
GHashTable *create_date;
GList *selection_metadata;
- /* check if all files in selection have the same parent */
- gboolean same_parent;
/* the index of the currently selected conflict */
gint selected_conflict;
/* total conflicts number */
gint conflicts_number;
- gint checked_parents;
GList *duplicates;
- GList *distinct_parents;
- GTask *conflicts_task;
GCancellable *conflict_cancellable;
gboolean checking_conflicts;
@@ -1400,7 +1395,6 @@ update_listbox (NautilusBatchRenameDialog *dialog)
}
}
-
void
check_conflict_for_files (NautilusBatchRenameDialog *dialog,
NautilusDirectory *directory,
@@ -1510,6 +1504,7 @@ check_conflict_for_files (NautilusBatchRenameDialog *dialog,
have_conflict = TRUE;
}
}
+
if (!have_conflict)
{
tag_present = g_hash_table_lookup (names_conflicts_table, new_name->str) != NULL;
@@ -1531,59 +1526,154 @@ check_conflict_for_files (NautilusBatchRenameDialog *dialog,
g_free (parent_uri);
}
- /* check if this is the last call of the callback. Update
- * the listbox with the conflicts if it is. */
- if (dialog->checked_parents == g_list_length (dialog->distinct_parents) - 1)
- {
- dialog->duplicates = g_list_reverse (dialog->duplicates);
-
- dialog->checking_conflicts = FALSE;
-
- update_listbox (dialog);
- }
-
- dialog->checked_parents++;
-
g_free (current_directory);
g_hash_table_destroy (directory_files_table);
g_hash_table_destroy (new_names_table);
g_hash_table_destroy (names_conflicts_table);
}
+static gboolean
+file_names_list_has_duplicates_finish (NautilusBatchRenameDialog *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
static void
-file_names_list_has_duplicates_callback (GObject *object,
- GAsyncResult *res,
- gpointer user_data)
+on_file_names_list_has_duplicates (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
{
- NautilusBatchRenameDialog *dialog;
+ NautilusBatchRenameDialog *self;
+ GError *error = NULL;
+ gboolean success;
- dialog = NAUTILUS_BATCH_RENAME_DIALOG (object);
+ self = NAUTILUS_BATCH_RENAME_DIALOG (object);
+ success = file_names_list_has_duplicates_finish (self, res, &error);
+
+ if (!success)
+ {
+ return;
+ }
+
+ update_listbox (self);
+}
- if (g_cancellable_is_cancelled (dialog->conflict_cancellable))
+static void
+on_file_names_list_has_duplicates_distinct_parents (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NautilusBatchRenameDialog *self;
+ GError *error = NULL;
+ gboolean success;
+
+ self = NAUTILUS_BATCH_RENAME_DIALOG (object);
+ success = file_names_list_has_duplicates_finish (self, res, &error);
+
+ if (!success)
{
return;
}
- if (dialog->same_parent)
+ self->duplicates = g_list_reverse (self->duplicates);
+ self->checking_conflicts = FALSE;
+ update_listbox (self);
+}
+
+typedef struct
+{
+ GList *directories;
+ GMutex wait_ready_mutex;
+ GCond wait_ready_condition;
+ gboolean directory_conflicts_ready;
+} CheckConflictsData;
+
+static void
+on_directory_conflicts_ready (NautilusDirectory *conflict_directory,
+ GList *files,
+ gpointer callback_data)
+{
+ NautilusBatchRenameDialog *self;
+ GTask *task;
+ CheckConflictsData *task_data;
+ GCancellable *cancellable;
+
+ task = G_TASK (callback_data);
+ task_data = g_task_get_task_data (task);
+ cancellable = g_task_get_cancellable (task);
+ self = NAUTILUS_BATCH_RENAME_DIALOG (g_task_get_source_object (task));
+ if (!g_cancellable_is_cancelled (cancellable))
{
- update_listbox (dialog);
+ check_conflict_for_files (self, conflict_directory, files);
}
+
+ g_mutex_lock (&task_data->wait_ready_mutex);
+ task_data->directory_conflicts_ready = TRUE;
+ g_cond_signal (&task_data->wait_ready_condition);
+ g_mutex_unlock (&task_data->wait_ready_mutex);
}
static void
-on_call_when_ready (NautilusDirectory *directory,
- GList *files,
- gpointer callback_data)
+file_names_list_has_duplicates_distinct_parents (GTask *task)
{
- check_conflict_for_files (NAUTILUS_BATCH_RENAME_DIALOG (callback_data),
- directory,
- files);
+ NautilusBatchRenameDialog *self;
+ CheckConflictsData *task_data;
+ NautilusDirectory *conflict_directory;
+ GList *directories;
+ GList *l;
+ const gchar *directory_conflict_uri = NULL;
+
+ self = g_task_get_source_object (task);
+ task_data = g_task_get_task_data (task);
+
+ g_mutex_init (&task_data->wait_ready_mutex);
+ g_cond_init (&task_data->wait_ready_condition);
+
+ directories = batch_rename_files_get_distinct_parents (self->selection);
+ /* check if this is the last call of the callback */
+ for (l = directories; l != NULL; l = l->next)
+ {
+ if (g_task_return_error_if_cancelled (task))
+ {
+ return;
+ }
+
+ g_mutex_lock (&task_data->wait_ready_mutex);
+ task_data->directory_conflicts_ready = FALSE;
+
+ directory_conflict_uri = l->data;
+ conflict_directory = nautilus_directory_get_by_uri (directory_conflict_uri);
+
+ nautilus_directory_call_when_ready (conflict_directory,
+ NAUTILUS_FILE_ATTRIBUTE_INFO,
+ TRUE,
+ on_directory_conflicts_ready,
+ task);
+
+ /* We need to block this thread until the call_when_ready call is done,
+ * if not the GTask would finalize. */
+ while (!task_data->directory_conflicts_ready)
+ {
+ g_cond_wait (&task_data->wait_ready_condition,
+ &task_data->wait_ready_mutex);
+ }
+
+ g_mutex_unlock (&task_data->wait_ready_mutex);
+
+ nautilus_directory_unref (conflict_directory);
+ }
+
+ g_task_return_boolean (task, TRUE);
}
static void
file_names_list_has_duplicates_async_thread (GTask *task,
gpointer object,
- gpointer task_data,
+ gpointer data,
GCancellable *cancellable)
{
NautilusBatchRenameDialog *dialog;
@@ -1594,15 +1684,16 @@ file_names_list_has_duplicates_async_thread (GTask *task,
NautilusFile *file;
GString *file_name;
GString *new_name;
- NautilusDirectory *parent;
gboolean have_conflict;
gboolean hash_table_insertion;
+ gboolean same_parent;
gchar *name;
GHashTable *directory_names_table;
GHashTable *new_names_table;
GHashTable *names_conflicts_table;
gint exists;
ConflictData *conflict_data;
+ g_autoptr (GSource) chained_call_source = NULL;
dialog = NAUTILUS_BATCH_RENAME_DIALOG (object);
@@ -1617,25 +1708,11 @@ file_names_list_has_duplicates_async_thread (GTask *task,
/* If the batch rename is launched in a search, then for each file we have to check for
* conflicts with each file in the file's parent directory */
- if (dialog->distinct_parents != NULL)
+ same_parent = !NAUTILUS_IS_SEARCH_DIRECTORY (dialog->directory);
+ if (!same_parent)
{
- for (l1 = dialog->distinct_parents; l1 != NULL; l1 = l1->next)
- {
- if (g_cancellable_is_cancelled (cancellable))
- {
- return;
- }
-
- parent = nautilus_directory_get_by_uri (l1->data);
+ file_names_list_has_duplicates_distinct_parents (task);
- nautilus_directory_call_when_ready (parent,
- NAUTILUS_FILE_ATTRIBUTE_INFO,
- TRUE,
- on_call_when_ready,
- dialog);
- }
-
- g_task_return_pointer (task, object, NULL);
return;
}
@@ -1744,7 +1821,28 @@ file_names_list_has_duplicates_async_thread (GTask *task,
dialog->checking_conflicts = FALSE;
- g_task_return_pointer (task, object, NULL);
+ g_task_return_boolean (task, TRUE);
+}
+
+static void
+destroy_conflicts_task_data (gpointer data)
+{
+ CheckConflictsData *task_data = data;
+
+ if (task_data->directories)
+ {
+ g_list_free (task_data->directories);
+ }
+
+ if (&task_data->wait_ready_mutex)
+ {
+ g_mutex_clear (&task_data->wait_ready_mutex);
+ }
+
+ if (&task_data->wait_ready_condition)
+ {
+ g_cond_clear (&task_data->wait_ready_condition);
+ }
}
static void
@@ -1752,19 +1850,23 @@ file_names_list_has_duplicates_async (NautilusBatchRenameDialog *dialog,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ g_autoptr (GTask) task = NULL;
+ CheckConflictsData *task_data;
+
if (dialog->checking_conflicts == TRUE)
{
g_cancellable_cancel (dialog->conflict_cancellable);
+ g_clear_object (&dialog->conflict_cancellable);
}
dialog->conflict_cancellable = g_cancellable_new ();
dialog->checking_conflicts = TRUE;
- dialog->conflicts_task = g_task_new (dialog, dialog->conflict_cancellable, callback, user_data);
-
- g_task_run_in_thread (dialog->conflicts_task, file_names_list_has_duplicates_async_thread);
- g_object_unref (dialog->conflicts_task);
+ task = g_task_new (dialog, dialog->conflict_cancellable, callback, user_data);
+ task_data = g_new0(CheckConflictsData, 1);
+ g_task_set_task_data (task, task_data, destroy_conflicts_task_data);
+ g_task_run_in_thread (task, file_names_list_has_duplicates_async_thread);
}
static void
@@ -2060,6 +2162,7 @@ update_display_text (NautilusBatchRenameDialog *dialog)
TagData *tag_data;
TagData *tag_data0;
TagData *tag_data00;
+ gboolean same_parent;
tag_data = g_hash_table_lookup (dialog->tag_info_table, NUMBERING);
tag_data0 = g_hash_table_lookup (dialog->tag_info_table, NUMBERING0);
@@ -2100,16 +2203,25 @@ update_display_text (NautilusBatchRenameDialog *dialog)
}
dialog->new_names = batch_rename_dialog_get_new_names (dialog);
- dialog->checked_parents = 0;
if (have_unallowed_character (dialog))
{
return;
}
- file_names_list_has_duplicates_async (dialog,
- file_names_list_has_duplicates_callback,
- NULL);
+ same_parent = !NAUTILUS_IS_SEARCH_DIRECTORY (dialog->directory);
+ if (same_parent)
+ {
+ file_names_list_has_duplicates_async (dialog,
+ on_file_names_list_has_duplicates,
+ NULL);
+ }
+ else
+ {
+ file_names_list_has_duplicates_async (dialog,
+ on_file_names_list_has_duplicates_distinct_parents,
+ NULL);
+ }
}
static void
@@ -3172,7 +3284,6 @@ nautilus_batch_rename_dialog_finalize (GObject *object)
g_hash_table_destroy (dialog->create_date);
}
- g_list_free_full (dialog->distinct_parents, g_free);
g_list_free_full (dialog->new_names, string_free);
g_list_free_full (dialog->duplicates, conflict_data_free);
@@ -3256,17 +3367,6 @@ nautilus_batch_rename_dialog_new (GList *selection,
nautilus_batch_rename_dialog_initialize_actions (dialog);
- dialog->same_parent = !NAUTILUS_IS_SEARCH_DIRECTORY (directory);
-
- if (!dialog->same_parent)
- {
- dialog->distinct_parents = batch_rename_files_get_distinct_parents (dialog->selection);
- }
- else
- {
- dialog->distinct_parents = NULL;
- }
-
update_display_text (dialog);
fill_display_listbox (dialog);