/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Pix * * Copyright (C) 2009 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "gth-rename-task.h" struct _GthRenameTaskPrivate { GList *old_files; GList *new_files; GList *current_old; GList *current_new; int n_files; int n_current; GFile *source; GFile *destination; GthOverwriteResponse default_response; }; G_DEFINE_TYPE_WITH_CODE (GthRenameTask, gth_rename_task, GTH_TYPE_TASK, G_ADD_PRIVATE (GthRenameTask)) static void gth_rename_task_finalize (GObject *object) { GthRenameTask *self; self = GTH_RENAME_TASK (object); _g_object_unref (self->priv->source); _g_object_unref (self->priv->destination); _g_object_list_unref (self->priv->old_files); _g_object_list_unref (self->priv->new_files); G_OBJECT_CLASS (gth_rename_task_parent_class)->finalize (object); } static void _gth_rename_task_exec (GthRenameTask *self); static void _gth_rename_task_exec_next_file (GthRenameTask *self) { self->priv->current_old = self->priv->current_old->next; self->priv->current_new = self->priv->current_new->next; self->priv->n_current++; if (self->priv->current_old == NULL) gth_task_completed (GTH_TASK (self), NULL); else _gth_rename_task_exec (self); } static void _gth_rename_task_try_rename (GthRenameTask *self, GFile *source, GFile *destination, GFileCopyFlags copy_flags); static void overwrite_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user_data) { GthRenameTask *self = user_data; if (response_id != GTK_RESPONSE_OK) self->priv->default_response = GTH_OVERWRITE_RESPONSE_CANCEL; else self->priv->default_response = gth_overwrite_dialog_get_response (GTH_OVERWRITE_DIALOG (dialog)); gtk_widget_hide (GTK_WIDGET (dialog)); gth_task_dialog (GTH_TASK (self), FALSE, NULL); switch (self->priv->default_response) { case GTH_OVERWRITE_RESPONSE_NO: case GTH_OVERWRITE_RESPONSE_ALWAYS_NO: case GTH_OVERWRITE_RESPONSE_UNSPECIFIED: _gth_rename_task_exec_next_file (self); break; case GTH_OVERWRITE_RESPONSE_YES: case GTH_OVERWRITE_RESPONSE_ALWAYS_YES: _gth_rename_task_try_rename (self, self->priv->source, self->priv->destination, G_FILE_COPY_OVERWRITE); break; case GTH_OVERWRITE_RESPONSE_RENAME: { GFile *parent; GFile *new_destination; parent = g_file_get_parent (self->priv->destination); new_destination = g_file_get_child_for_display_name (parent, gth_overwrite_dialog_get_filename (GTH_OVERWRITE_DIALOG (dialog)), NULL); _gth_rename_task_try_rename (self, self->priv->source, new_destination, 0); g_object_unref (new_destination); g_object_unref (parent); } break; case GTH_OVERWRITE_RESPONSE_CANCEL: { GError *error; error = g_error_new_literal (GTH_TASK_ERROR, GTH_TASK_ERROR_CANCELLED, ""); gth_task_completed (GTH_TASK (self), error); } break; } gtk_widget_destroy (GTK_WIDGET (dialog)); } static void _gth_rename_task_try_rename (GthRenameTask *self, GFile *source, GFile *destination, GFileCopyFlags copy_flags) { char *source_name; char *destination_name; char *details; GError *error = NULL; if (g_cancellable_set_error_if_cancelled (gth_task_get_cancellable (GTH_TASK (self)), &error)) { gth_task_completed (GTH_TASK (self), error); return; } g_object_ref (source); _g_object_unref (self->priv->source); self->priv->source = source; g_object_ref (destination); _g_object_unref (self->priv->destination); self->priv->destination = destination; source_name = g_file_get_parse_name (source); destination_name = g_file_get_parse_name (destination); details = g_strdup_printf ("Renaming '%s' as '%s'", source_name, destination_name); gth_task_progress (GTH_TASK (self), _("Renaming files"), details, FALSE, (double) self->priv->n_current / (self->priv->n_files + 1)); g_free (destination_name); g_free (source_name); if (self->priv->default_response == GTH_OVERWRITE_RESPONSE_ALWAYS_YES) copy_flags = G_FILE_COPY_OVERWRITE; if (! _g_file_move (source, destination, G_FILE_COPY_ALL_METADATA | copy_flags, gth_task_get_cancellable (GTH_TASK (self)), NULL, NULL, &error)) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) { if (self->priv->default_response != GTH_OVERWRITE_RESPONSE_ALWAYS_NO) { GtkWidget *dialog; dialog = gth_overwrite_dialog_new (source, NULL, destination, self->priv->default_response, self->priv->n_files == 1); g_signal_connect (dialog, "response", G_CALLBACK (overwrite_dialog_response_cb), self); gtk_widget_show (dialog); gth_task_dialog (GTH_TASK (self), TRUE, dialog); return; } } else { gth_task_completed (GTH_TASK (self), error); return; } } else gth_monitor_file_renamed (gth_main_get_default_monitor (), source, destination); _gth_rename_task_exec_next_file (self); } static void _gth_rename_task_exec (GthRenameTask *self) { GFile *source; GFile *destination; if (self->priv->current_old == NULL) { gth_task_completed (GTH_TASK (self), NULL); return; } source = (GFile *) self->priv->current_old->data; destination = (GFile *) self->priv->current_new->data; _gth_rename_task_try_rename (self, source, destination, 0); } static void gth_rename_task_exec (GthTask *task) { _gth_rename_task_exec (GTH_RENAME_TASK (task)); } static void gth_rename_task_class_init (GthRenameTaskClass *klass) { GObjectClass *object_class; GthTaskClass *task_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = gth_rename_task_finalize; task_class = GTH_TASK_CLASS (klass); task_class->exec = gth_rename_task_exec; } static void gth_rename_task_init (GthRenameTask *self) { self->priv = gth_rename_task_get_instance_private (self); self->priv->default_response = GTH_OVERWRITE_RESPONSE_UNSPECIFIED; } GthTask * gth_rename_task_new (GList *old_files, GList *new_files) { GthRenameTask *self; self = GTH_RENAME_TASK (g_object_new (GTH_TYPE_RENAME_TASK, NULL)); self->priv->old_files = _g_object_list_ref (old_files); self->priv->new_files = _g_object_list_ref (new_files); self->priv->current_old = self->priv->old_files; self->priv->current_new = self->priv->new_files; self->priv->n_files = g_list_length (self->priv->old_files); self->priv->n_current = 1; return (GthTask *) self; }