1 /* nautilus-file-undo-operations.c - Manages undo/redo of file operations
2 *
3 * Copyright (C) 2007-2011 Amos Brocco
4 * Copyright (C) 2010, 2012 Red Hat, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 *
19 * Authors: Amos Brocco <amos.brocco@gmail.com>
20 * Cosimo Cecchi <cosimoc@redhat.com>
21 *
22 */
23
24 #include <stdlib.h>
25
26 #include "nautilus-file-undo-operations.h"
27
28 #include <glib/gi18n.h>
29
30 #include "nautilus-file-operations.h"
31 #include "nautilus-file.h"
32 #include "nautilus-file-undo-manager.h"
33 #include "nautilus-batch-rename-dialog.h"
34 #include "nautilus-batch-rename-utilities.h"
35 #include "nautilus-tag-manager.h"
36
37
38 /* Since we use g_get_current_time for setting "orig_trash_time" in the undo
39 * info, there are situations where the difference between this value and the
40 * real deletion time can differ enough to make the rounding a difference of 1
41 * second, failing the equality check. To make sure we avoid this, and to be
42 * preventive, use 2 seconds epsilon.
43 */
44 #define TRASH_TIME_EPSILON 2
45
46 typedef struct
47 {
48 NautilusFileUndoOp op_type;
49 guint count; /* Number of items */
50
51 GTask *apply_async_task;
52
53 gchar *undo_label;
54 gchar *redo_label;
55 gchar *undo_description;
56 gchar *redo_description;
57 } NautilusFileUndoInfoPrivate;
58
59 G_DEFINE_TYPE_WITH_PRIVATE (NautilusFileUndoInfo, nautilus_file_undo_info, G_TYPE_OBJECT)
60
61 enum
62 {
63 PROP_OP_TYPE = 1,
64 PROP_ITEM_COUNT,
65 N_PROPERTIES
66 };
67
68 static GParamSpec *properties[N_PROPERTIES] = { NULL, };
69
70 /* description helpers */
71 static void
nautilus_file_undo_info_init(NautilusFileUndoInfo * self)72 nautilus_file_undo_info_init (NautilusFileUndoInfo *self)
73 {
74 NautilusFileUndoInfoPrivate *priv;
75
76 priv = nautilus_file_undo_info_get_instance_private (self);
77
78 priv->apply_async_task = NULL;
79 }
80
81 static void
nautilus_file_undo_info_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)82 nautilus_file_undo_info_get_property (GObject *object,
83 guint property_id,
84 GValue *value,
85 GParamSpec *pspec)
86 {
87 NautilusFileUndoInfo *self;
88 NautilusFileUndoInfoPrivate *priv;
89
90 self = NAUTILUS_FILE_UNDO_INFO (object);
91 priv = nautilus_file_undo_info_get_instance_private (self);
92
93 switch (property_id)
94 {
95 case PROP_OP_TYPE:
96 {
97 g_value_set_int (value, priv->op_type);
98 }
99 break;
100
101 case PROP_ITEM_COUNT:
102 {
103 g_value_set_int (value, priv->count);
104 }
105 break;
106
107 default:
108 {
109 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
110 }
111 break;
112 }
113 }
114
115 static void
nautilus_file_undo_info_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)116 nautilus_file_undo_info_set_property (GObject *object,
117 guint property_id,
118 const GValue *value,
119 GParamSpec *pspec)
120 {
121 NautilusFileUndoInfo *self;
122 NautilusFileUndoInfoPrivate *priv;
123
124 self = NAUTILUS_FILE_UNDO_INFO (object);
125 priv = nautilus_file_undo_info_get_instance_private (self);
126
127 switch (property_id)
128 {
129 case PROP_OP_TYPE:
130 {
131 priv->op_type = g_value_get_int (value);
132 }
133 break;
134
135 case PROP_ITEM_COUNT:
136 {
137 priv->count = g_value_get_int (value);
138 }
139 break;
140
141 default:
142 {
143 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
144 }
145 break;
146 }
147 }
148
149 static void
nautilus_file_redo_info_warn_redo(NautilusFileUndoInfo * self,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)150 nautilus_file_redo_info_warn_redo (NautilusFileUndoInfo *self,
151 GtkWindow *parent_window,
152 NautilusFileOperationsDBusData *dbus_data)
153 {
154 g_critical ("Object %p of type %s does not implement redo_func!!",
155 self, G_OBJECT_TYPE_NAME (self));
156 }
157
158 static void
nautilus_file_undo_info_warn_undo(NautilusFileUndoInfo * self,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)159 nautilus_file_undo_info_warn_undo (NautilusFileUndoInfo *self,
160 GtkWindow *parent_window,
161 NautilusFileOperationsDBusData *dbus_data)
162 {
163 g_critical ("Object %p of type %s does not implement undo_func!!",
164 self, G_OBJECT_TYPE_NAME (self));
165 }
166
167 static void
nautilus_file_undo_info_strings_func(NautilusFileUndoInfo * self,gchar ** undo_label,gchar ** undo_description,gchar ** redo_label,gchar ** redo_description)168 nautilus_file_undo_info_strings_func (NautilusFileUndoInfo *self,
169 gchar **undo_label,
170 gchar **undo_description,
171 gchar **redo_label,
172 gchar **redo_description)
173 {
174 if (undo_label != NULL)
175 {
176 *undo_label = g_strdup (_("Undo"));
177 }
178 if (undo_description != NULL)
179 {
180 *undo_description = g_strdup (_("Undo last action"));
181 }
182
183 if (redo_label != NULL)
184 {
185 *redo_label = g_strdup (_("Redo"));
186 }
187 if (redo_description != NULL)
188 {
189 *redo_description = g_strdup (_("Redo last undone action"));
190 }
191 }
192
193 static void
nautilus_file_undo_info_finalize(GObject * object)194 nautilus_file_undo_info_finalize (GObject *object)
195 {
196 NautilusFileUndoInfo *self;
197 NautilusFileUndoInfoPrivate *priv;
198
199 self = NAUTILUS_FILE_UNDO_INFO (object);
200 priv = nautilus_file_undo_info_get_instance_private (self);
201
202 g_clear_object (&priv->apply_async_task);
203
204 G_OBJECT_CLASS (nautilus_file_undo_info_parent_class)->finalize (object);
205 }
206
207 static void
nautilus_file_undo_info_class_init(NautilusFileUndoInfoClass * klass)208 nautilus_file_undo_info_class_init (NautilusFileUndoInfoClass *klass)
209 {
210 GObjectClass *oclass = G_OBJECT_CLASS (klass);
211
212 oclass->finalize = nautilus_file_undo_info_finalize;
213 oclass->get_property = nautilus_file_undo_info_get_property;
214 oclass->set_property = nautilus_file_undo_info_set_property;
215
216 klass->undo_func = nautilus_file_undo_info_warn_undo;
217 klass->redo_func = nautilus_file_redo_info_warn_redo;
218 klass->strings_func = nautilus_file_undo_info_strings_func;
219
220 properties[PROP_OP_TYPE] =
221 g_param_spec_int ("op-type",
222 "Undo info op type",
223 "Type of undo operation",
224 0, NAUTILUS_FILE_UNDO_OP_NUM_TYPES - 1, 0,
225 G_PARAM_READWRITE |
226 G_PARAM_CONSTRUCT_ONLY);
227 properties[PROP_ITEM_COUNT] =
228 g_param_spec_int ("item-count",
229 "Number of items",
230 "Number of items",
231 0, G_MAXINT, 0,
232 G_PARAM_READWRITE |
233 G_PARAM_CONSTRUCT_ONLY);
234
235 g_object_class_install_properties (oclass, N_PROPERTIES, properties);
236 }
237
238 NautilusFileUndoOp
nautilus_file_undo_info_get_op_type(NautilusFileUndoInfo * self)239 nautilus_file_undo_info_get_op_type (NautilusFileUndoInfo *self)
240 {
241 NautilusFileUndoInfoPrivate *priv;
242
243 g_return_val_if_fail (NAUTILUS_IS_FILE_UNDO_INFO (self), NAUTILUS_FILE_UNDO_OP_INVALID);
244
245 priv = nautilus_file_undo_info_get_instance_private (self);
246
247 return priv->op_type;
248 }
249
250 static gint
nautilus_file_undo_info_get_item_count(NautilusFileUndoInfo * self)251 nautilus_file_undo_info_get_item_count (NautilusFileUndoInfo *self)
252 {
253 NautilusFileUndoInfoPrivate *priv;
254
255 priv = nautilus_file_undo_info_get_instance_private (self);
256
257 return priv->count;
258 }
259
260 void
nautilus_file_undo_info_apply_async(NautilusFileUndoInfo * self,gboolean undo,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data,GAsyncReadyCallback callback,gpointer user_data)261 nautilus_file_undo_info_apply_async (NautilusFileUndoInfo *self,
262 gboolean undo,
263 GtkWindow *parent_window,
264 NautilusFileOperationsDBusData *dbus_data,
265 GAsyncReadyCallback callback,
266 gpointer user_data)
267 {
268 NautilusFileUndoInfoPrivate *priv;
269
270 g_return_if_fail (NAUTILUS_IS_FILE_UNDO_INFO (self));
271
272 priv = nautilus_file_undo_info_get_instance_private (self);
273
274 g_assert (priv->apply_async_task == NULL);
275
276 priv->apply_async_task = g_task_new (G_OBJECT (self),
277 NULL,
278 callback,
279 user_data);
280
281 if (undo)
282 {
283 NAUTILUS_FILE_UNDO_INFO_CLASS (G_OBJECT_GET_CLASS (self))->undo_func (self,
284 parent_window,
285 dbus_data);
286 }
287 else
288 {
289 NAUTILUS_FILE_UNDO_INFO_CLASS (G_OBJECT_GET_CLASS (self))->redo_func (self,
290 parent_window,
291 dbus_data);
292 }
293 }
294
295 typedef struct
296 {
297 gboolean success;
298 gboolean user_cancel;
299 } FileUndoInfoOpRes;
300
301 static void
file_undo_info_op_res_free(gpointer data)302 file_undo_info_op_res_free (gpointer data)
303 {
304 g_slice_free (FileUndoInfoOpRes, data);
305 }
306
307 gboolean
nautilus_file_undo_info_apply_finish(NautilusFileUndoInfo * self,GAsyncResult * res,gboolean * user_cancel,GError ** error)308 nautilus_file_undo_info_apply_finish (NautilusFileUndoInfo *self,
309 GAsyncResult *res,
310 gboolean *user_cancel,
311 GError **error)
312 {
313 FileUndoInfoOpRes *op_res;
314 gboolean success = FALSE;
315
316 op_res = g_task_propagate_pointer (G_TASK (res), error);
317
318 if (op_res != NULL)
319 {
320 *user_cancel = op_res->user_cancel;
321 success = op_res->success;
322
323 file_undo_info_op_res_free (op_res);
324 }
325
326 return success;
327 }
328
329 void
nautilus_file_undo_info_get_strings(NautilusFileUndoInfo * self,gchar ** undo_label,gchar ** undo_description,gchar ** redo_label,gchar ** redo_description)330 nautilus_file_undo_info_get_strings (NautilusFileUndoInfo *self,
331 gchar **undo_label,
332 gchar **undo_description,
333 gchar **redo_label,
334 gchar **redo_description)
335 {
336 NAUTILUS_FILE_UNDO_INFO_CLASS (G_OBJECT_GET_CLASS (self))->strings_func (self,
337 undo_label, undo_description,
338 redo_label, redo_description);
339 }
340
341 static void
file_undo_info_complete_apply(NautilusFileUndoInfo * self,gboolean success,gboolean user_cancel)342 file_undo_info_complete_apply (NautilusFileUndoInfo *self,
343 gboolean success,
344 gboolean user_cancel)
345 {
346 NautilusFileUndoInfoPrivate *priv;
347 FileUndoInfoOpRes *op_res;
348
349 priv = nautilus_file_undo_info_get_instance_private (self);
350 op_res = g_slice_new0 (FileUndoInfoOpRes);
351
352 op_res->user_cancel = user_cancel;
353 op_res->success = success;
354
355 g_task_return_pointer (priv->apply_async_task, op_res,
356 file_undo_info_op_res_free);
357
358 g_clear_object (&priv->apply_async_task);
359 }
360
361 static void
file_undo_info_transfer_callback(GHashTable * debuting_uris,gboolean success,gpointer user_data)362 file_undo_info_transfer_callback (GHashTable *debuting_uris,
363 gboolean success,
364 gpointer user_data)
365 {
366 NautilusFileUndoInfo *self = user_data;
367
368 /* TODO: we need to forward the cancelled state from
369 * the file operation to the file undo info object.
370 */
371 file_undo_info_complete_apply (self, success, FALSE);
372 }
373
374 static void
file_undo_info_operation_callback(NautilusFile * file,GFile * result_location,GError * error,gpointer user_data)375 file_undo_info_operation_callback (NautilusFile *file,
376 GFile *result_location,
377 GError *error,
378 gpointer user_data)
379 {
380 NautilusFileUndoInfo *self = user_data;
381
382 file_undo_info_complete_apply (self, (error == NULL),
383 g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED));
384 }
385
386 static void
file_undo_info_delete_callback(GHashTable * debuting_uris,gboolean user_cancel,gpointer user_data)387 file_undo_info_delete_callback (GHashTable *debuting_uris,
388 gboolean user_cancel,
389 gpointer user_data)
390 {
391 NautilusFileUndoInfo *self = user_data;
392
393 file_undo_info_complete_apply (self,
394 !user_cancel,
395 user_cancel);
396 }
397
398 /* copy/move/duplicate/link/restore from trash */
399 struct _NautilusFileUndoInfoExt
400 {
401 NautilusFileUndoInfo parent_instance;
402
403 GFile *src_dir;
404 GFile *dest_dir;
405 GQueue *sources; /* Relative to src_dir */
406 GQueue *destinations; /* Relative to dest_dir */
407 };
408
G_DEFINE_TYPE(NautilusFileUndoInfoExt,nautilus_file_undo_info_ext,NAUTILUS_TYPE_FILE_UNDO_INFO)409 G_DEFINE_TYPE (NautilusFileUndoInfoExt, nautilus_file_undo_info_ext, NAUTILUS_TYPE_FILE_UNDO_INFO)
410
411 static char *
412 ext_get_first_target_short_name (NautilusFileUndoInfoExt *self)
413 {
414 GList *targets_first;
415 char *file_name = NULL;
416
417 targets_first = g_queue_peek_head_link (self->destinations);
418
419 if (targets_first != NULL &&
420 targets_first->data != NULL)
421 {
422 file_name = g_file_get_basename (targets_first->data);
423 }
424
425 return file_name;
426 }
427
428 static void
ext_strings_func(NautilusFileUndoInfo * info,gchar ** undo_label,gchar ** undo_description,gchar ** redo_label,gchar ** redo_description)429 ext_strings_func (NautilusFileUndoInfo *info,
430 gchar **undo_label,
431 gchar **undo_description,
432 gchar **redo_label,
433 gchar **redo_description)
434 {
435 NautilusFileUndoInfoExt *self = NAUTILUS_FILE_UNDO_INFO_EXT (info);
436 NautilusFileUndoOp op_type = nautilus_file_undo_info_get_op_type (info);
437 gint count = nautilus_file_undo_info_get_item_count (info);
438 gchar *name = NULL, *source, *destination;
439
440 source = g_file_get_path (self->src_dir);
441 destination = g_file_get_path (self->dest_dir);
442
443 if (count <= 1)
444 {
445 name = ext_get_first_target_short_name (self);
446 }
447
448 if (op_type == NAUTILUS_FILE_UNDO_OP_MOVE)
449 {
450 if (count > 1)
451 {
452 *undo_description = g_strdup_printf (ngettext ("Move %d item back to “%s”",
453 "Move %d items back to “%s”", count),
454 count, source);
455 *redo_description = g_strdup_printf (ngettext ("Move %d item to “%s”",
456 "Move %d items to “%s”", count),
457 count, destination);
458
459 *undo_label = g_strdup_printf (ngettext ("_Undo Move %d item",
460 "_Undo Move %d items", count),
461 count);
462 *redo_label = g_strdup_printf (ngettext ("_Redo Move %d item",
463 "_Redo Move %d items", count),
464 count);
465 }
466 else
467 {
468 *undo_description = g_strdup_printf (_("Move “%s” back to “%s”"), name, source);
469 *redo_description = g_strdup_printf (_("Move “%s” to “%s”"), name, destination);
470
471 *undo_label = g_strdup (_("_Undo Move"));
472 *redo_label = g_strdup (_("_Redo Move"));
473 }
474 }
475 else if (op_type == NAUTILUS_FILE_UNDO_OP_RESTORE_FROM_TRASH)
476 {
477 *undo_label = g_strdup (_("_Undo Restore from Trash"));
478 *redo_label = g_strdup (_("_Redo Restore from Trash"));
479
480 if (count > 1)
481 {
482 *undo_description = g_strdup_printf (ngettext ("Move %d item back to trash",
483 "Move %d items back to trash", count),
484 count);
485 *redo_description = g_strdup_printf (ngettext ("Restore %d item from trash",
486 "Restore %d items from trash", count),
487 count);
488 }
489 else
490 {
491 *undo_description = g_strdup_printf (_("Move “%s” back to trash"), name);
492 *redo_description = g_strdup_printf (_("Restore “%s” from trash"), name);
493 }
494 }
495 else if (op_type == NAUTILUS_FILE_UNDO_OP_COPY)
496 {
497 if (count > 1)
498 {
499 *undo_description = g_strdup_printf (ngettext ("Delete %d copied item",
500 "Delete %d copied items", count),
501 count);
502 *redo_description = g_strdup_printf (ngettext ("Copy %d item to “%s”",
503 "Copy %d items to “%s”", count),
504 count, destination);
505
506 *undo_label = g_strdup_printf (ngettext ("_Undo Copy %d item",
507 "_Undo Copy %d items", count),
508 count);
509 *redo_label = g_strdup_printf (ngettext ("_Redo Copy %d item",
510 "_Redo Copy %d items", count),
511 count);
512 }
513 else
514 {
515 *undo_description = g_strdup_printf (_("Delete “%s”"), name);
516 *redo_description = g_strdup_printf (_("Copy “%s” to “%s”"), name, destination);
517
518 *undo_label = g_strdup (_("_Undo Copy"));
519 *redo_label = g_strdup (_("_Redo Copy"));
520 }
521 }
522 else if (op_type == NAUTILUS_FILE_UNDO_OP_DUPLICATE)
523 {
524 if (count > 1)
525 {
526 *undo_description = g_strdup_printf (ngettext ("Delete %d duplicated item",
527 "Delete %d duplicated items", count),
528 count);
529 *redo_description = g_strdup_printf (ngettext ("Duplicate %d item in “%s”",
530 "Duplicate %d items in “%s”", count),
531 count, destination);
532
533 *undo_label = g_strdup_printf (ngettext ("_Undo Duplicate %d item",
534 "_Undo Duplicate %d items", count),
535 count);
536 *redo_label = g_strdup_printf (ngettext ("_Redo Duplicate %d item",
537 "_Redo Duplicate %d items", count),
538 count);
539 }
540 else
541 {
542 *undo_description = g_strdup_printf (_("Delete “%s”"), name);
543 *redo_description = g_strdup_printf (_("Duplicate “%s” in “%s”"),
544 name, destination);
545
546 *undo_label = g_strdup (_("_Undo Duplicate"));
547 *redo_label = g_strdup (_("_Redo Duplicate"));
548 }
549 }
550 else if (op_type == NAUTILUS_FILE_UNDO_OP_CREATE_LINK)
551 {
552 if (count > 1)
553 {
554 *undo_description = g_strdup_printf (ngettext ("Delete links to %d item",
555 "Delete links to %d items", count),
556 count);
557 *redo_description = g_strdup_printf (ngettext ("Create links to %d item",
558 "Create links to %d items", count),
559 count);
560 }
561 else
562 {
563 *undo_description = g_strdup_printf (_("Delete link to “%s”"), name);
564 *redo_description = g_strdup_printf (_("Create link to “%s”"), name);
565
566 *undo_label = g_strdup (_("_Undo Create Link"));
567 *redo_label = g_strdup (_("_Redo Create Link"));
568 }
569 }
570 else
571 {
572 g_assert_not_reached ();
573 }
574
575 g_free (name);
576 g_free (source);
577 g_free (destination);
578 }
579
580 static void
ext_create_link_redo_func(NautilusFileUndoInfoExt * self,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)581 ext_create_link_redo_func (NautilusFileUndoInfoExt *self,
582 GtkWindow *parent_window,
583 NautilusFileOperationsDBusData *dbus_data)
584 {
585 nautilus_file_operations_link (g_queue_peek_head_link (self->sources),
586 self->dest_dir,
587 parent_window,
588 dbus_data,
589 file_undo_info_transfer_callback,
590 self);
591 }
592
593 static void
ext_duplicate_redo_func(NautilusFileUndoInfoExt * self,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)594 ext_duplicate_redo_func (NautilusFileUndoInfoExt *self,
595 GtkWindow *parent_window,
596 NautilusFileOperationsDBusData *dbus_data)
597 {
598 nautilus_file_operations_duplicate (g_queue_peek_head_link (self->sources),
599 parent_window,
600 dbus_data,
601 file_undo_info_transfer_callback,
602 self);
603 }
604
605 static void
ext_copy_redo_func(NautilusFileUndoInfoExt * self,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)606 ext_copy_redo_func (NautilusFileUndoInfoExt *self,
607 GtkWindow *parent_window,
608 NautilusFileOperationsDBusData *dbus_data)
609 {
610 nautilus_file_operations_copy_async (g_queue_peek_head_link (self->sources),
611 self->dest_dir,
612 parent_window,
613 dbus_data,
614 file_undo_info_transfer_callback,
615 self);
616 }
617
618 static void
ext_move_restore_redo_func(NautilusFileUndoInfoExt * self,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)619 ext_move_restore_redo_func (NautilusFileUndoInfoExt *self,
620 GtkWindow *parent_window,
621 NautilusFileOperationsDBusData *dbus_data)
622 {
623 nautilus_file_operations_move_async (g_queue_peek_head_link (self->sources),
624 self->dest_dir,
625 parent_window,
626 dbus_data,
627 file_undo_info_transfer_callback,
628 self);
629 }
630
631 static void
ext_redo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)632 ext_redo_func (NautilusFileUndoInfo *info,
633 GtkWindow *parent_window,
634 NautilusFileOperationsDBusData *dbus_data)
635 {
636 NautilusFileUndoInfoExt *self = NAUTILUS_FILE_UNDO_INFO_EXT (info);
637 NautilusFileUndoOp op_type = nautilus_file_undo_info_get_op_type (info);
638
639 if (op_type == NAUTILUS_FILE_UNDO_OP_MOVE ||
640 op_type == NAUTILUS_FILE_UNDO_OP_RESTORE_FROM_TRASH)
641 {
642 ext_move_restore_redo_func (self, parent_window, dbus_data);
643 }
644 else if (op_type == NAUTILUS_FILE_UNDO_OP_COPY)
645 {
646 ext_copy_redo_func (self, parent_window, dbus_data);
647 }
648 else if (op_type == NAUTILUS_FILE_UNDO_OP_DUPLICATE)
649 {
650 ext_duplicate_redo_func (self, parent_window, dbus_data);
651 }
652 else if (op_type == NAUTILUS_FILE_UNDO_OP_CREATE_LINK)
653 {
654 ext_create_link_redo_func (self, parent_window, dbus_data);
655 }
656 else
657 {
658 g_assert_not_reached ();
659 }
660 }
661
662 static void
ext_restore_undo_func(NautilusFileUndoInfoExt * self,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)663 ext_restore_undo_func (NautilusFileUndoInfoExt *self,
664 GtkWindow *parent_window,
665 NautilusFileOperationsDBusData *dbus_data)
666 {
667 nautilus_file_operations_trash_or_delete_async (g_queue_peek_head_link (self->destinations),
668 parent_window,
669 dbus_data,
670 file_undo_info_delete_callback,
671 self);
672 }
673
674
675 static void
ext_move_undo_func(NautilusFileUndoInfoExt * self,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)676 ext_move_undo_func (NautilusFileUndoInfoExt *self,
677 GtkWindow *parent_window,
678 NautilusFileOperationsDBusData *dbus_data)
679 {
680 nautilus_file_operations_move_async (g_queue_peek_head_link (self->destinations),
681 self->src_dir,
682 parent_window,
683 dbus_data,
684 file_undo_info_transfer_callback,
685 self);
686 }
687
688 static void
ext_copy_duplicate_undo_func(NautilusFileUndoInfoExt * self,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)689 ext_copy_duplicate_undo_func (NautilusFileUndoInfoExt *self,
690 GtkWindow *parent_window,
691 NautilusFileOperationsDBusData *dbus_data)
692 {
693 GList *files;
694
695 files = g_list_copy (g_queue_peek_head_link (self->destinations));
696 files = g_list_reverse (files); /* Deleting must be done in reverse */
697
698 nautilus_file_operations_delete_async (files, parent_window,
699 dbus_data,
700 file_undo_info_delete_callback, self);
701
702 g_list_free (files);
703 }
704
705 static void
ext_undo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)706 ext_undo_func (NautilusFileUndoInfo *info,
707 GtkWindow *parent_window,
708 NautilusFileOperationsDBusData *dbus_data)
709 {
710 NautilusFileUndoInfoExt *self = NAUTILUS_FILE_UNDO_INFO_EXT (info);
711 NautilusFileUndoOp op_type = nautilus_file_undo_info_get_op_type (info);
712
713 if (op_type == NAUTILUS_FILE_UNDO_OP_COPY ||
714 op_type == NAUTILUS_FILE_UNDO_OP_DUPLICATE ||
715 op_type == NAUTILUS_FILE_UNDO_OP_CREATE_LINK)
716 {
717 ext_copy_duplicate_undo_func (self, parent_window, dbus_data);
718 }
719 else if (op_type == NAUTILUS_FILE_UNDO_OP_MOVE)
720 {
721 ext_move_undo_func (self, parent_window, dbus_data);
722 }
723 else if (op_type == NAUTILUS_FILE_UNDO_OP_RESTORE_FROM_TRASH)
724 {
725 ext_restore_undo_func (self, parent_window, dbus_data);
726 }
727 else
728 {
729 g_assert_not_reached ();
730 }
731 }
732
733 static void
nautilus_file_undo_info_ext_init(NautilusFileUndoInfoExt * self)734 nautilus_file_undo_info_ext_init (NautilusFileUndoInfoExt *self)
735 {
736 }
737
738 static void
nautilus_file_undo_info_ext_finalize(GObject * obj)739 nautilus_file_undo_info_ext_finalize (GObject *obj)
740 {
741 NautilusFileUndoInfoExt *self = NAUTILUS_FILE_UNDO_INFO_EXT (obj);
742
743 if (self->sources)
744 {
745 g_queue_free_full (self->sources, g_object_unref);
746 }
747
748 if (self->destinations)
749 {
750 g_queue_free_full (self->destinations, g_object_unref);
751 }
752
753 g_clear_object (&self->src_dir);
754 g_clear_object (&self->dest_dir);
755
756 G_OBJECT_CLASS (nautilus_file_undo_info_ext_parent_class)->finalize (obj);
757 }
758
759 static void
nautilus_file_undo_info_ext_class_init(NautilusFileUndoInfoExtClass * klass)760 nautilus_file_undo_info_ext_class_init (NautilusFileUndoInfoExtClass *klass)
761 {
762 GObjectClass *oclass = G_OBJECT_CLASS (klass);
763 NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
764
765 oclass->finalize = nautilus_file_undo_info_ext_finalize;
766
767 iclass->undo_func = ext_undo_func;
768 iclass->redo_func = ext_redo_func;
769 iclass->strings_func = ext_strings_func;
770 }
771
772 NautilusFileUndoInfo *
nautilus_file_undo_info_ext_new(NautilusFileUndoOp op_type,gint item_count,GFile * src_dir,GFile * target_dir)773 nautilus_file_undo_info_ext_new (NautilusFileUndoOp op_type,
774 gint item_count,
775 GFile *src_dir,
776 GFile *target_dir)
777 {
778 NautilusFileUndoInfoExt *self;
779
780 self = g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_EXT,
781 "op-type", op_type,
782 "item-count", item_count,
783 NULL);
784
785 self->src_dir = g_object_ref (src_dir);
786 self->dest_dir = g_object_ref (target_dir);
787 self->sources = g_queue_new ();
788 self->destinations = g_queue_new ();
789
790 return NAUTILUS_FILE_UNDO_INFO (self);
791 }
792
793 void
nautilus_file_undo_info_ext_add_origin_target_pair(NautilusFileUndoInfoExt * self,GFile * origin,GFile * target)794 nautilus_file_undo_info_ext_add_origin_target_pair (NautilusFileUndoInfoExt *self,
795 GFile *origin,
796 GFile *target)
797 {
798 g_queue_push_tail (self->sources, g_object_ref (origin));
799 g_queue_push_tail (self->destinations, g_object_ref (target));
800 }
801
802 /* create new file/folder */
803 struct _NautilusFileUndoInfoCreate
804 {
805 NautilusFileUndoInfo parent_instance;
806
807 char *template;
808 GFile *target_file;
809 gint length;
810 };
811
G_DEFINE_TYPE(NautilusFileUndoInfoCreate,nautilus_file_undo_info_create,NAUTILUS_TYPE_FILE_UNDO_INFO)812 G_DEFINE_TYPE (NautilusFileUndoInfoCreate, nautilus_file_undo_info_create, NAUTILUS_TYPE_FILE_UNDO_INFO)
813
814 static void
815 create_strings_func (NautilusFileUndoInfo *info,
816 gchar **undo_label,
817 gchar **undo_description,
818 gchar **redo_label,
819 gchar **redo_description)
820 {
821 NautilusFileUndoInfoCreate *self = NAUTILUS_FILE_UNDO_INFO_CREATE (info);
822 NautilusFileUndoOp op_type = nautilus_file_undo_info_get_op_type (info);
823 char *name;
824
825 name = g_file_get_parse_name (self->target_file);
826 *undo_description = g_strdup_printf (_("Delete “%s”"), name);
827
828 if (op_type == NAUTILUS_FILE_UNDO_OP_CREATE_EMPTY_FILE)
829 {
830 *redo_description = g_strdup_printf (_("Create an empty file “%s”"), name);
831
832 *undo_label = g_strdup (_("_Undo Create Empty File"));
833 *redo_label = g_strdup (_("_Redo Create Empty File"));
834 }
835 else if (op_type == NAUTILUS_FILE_UNDO_OP_CREATE_FOLDER)
836 {
837 *redo_description = g_strdup_printf (_("Create a new folder “%s”"), name);
838
839 *undo_label = g_strdup (_("_Undo Create Folder"));
840 *redo_label = g_strdup (_("_Redo Create Folder"));
841 }
842 else if (op_type == NAUTILUS_FILE_UNDO_OP_CREATE_FILE_FROM_TEMPLATE)
843 {
844 *redo_description = g_strdup_printf (_("Create new file “%s” from template "), name);
845
846 *undo_label = g_strdup (_("_Undo Create from Template"));
847 *redo_label = g_strdup (_("_Redo Create from Template"));
848 }
849 else
850 {
851 g_assert_not_reached ();
852 }
853
854 g_free (name);
855 }
856
857 static void
create_callback(GFile * new_file,gboolean success,gpointer callback_data)858 create_callback (GFile *new_file,
859 gboolean success,
860 gpointer callback_data)
861 {
862 file_undo_info_transfer_callback (NULL, success, callback_data);
863 }
864
865 static void
create_from_template_redo_func(NautilusFileUndoInfoCreate * self,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)866 create_from_template_redo_func (NautilusFileUndoInfoCreate *self,
867 GtkWindow *parent_window,
868 NautilusFileOperationsDBusData *dbus_data)
869 {
870 GFile *parent;
871 gchar *parent_uri, *new_name;
872
873 parent = g_file_get_parent (self->target_file);
874 parent_uri = g_file_get_uri (parent);
875 new_name = g_file_get_parse_name (self->target_file);
876 nautilus_file_operations_new_file_from_template (NULL,
877 parent_uri, new_name,
878 self->template,
879 create_callback, self);
880
881 g_free (parent_uri);
882 g_free (new_name);
883 g_object_unref (parent);
884 }
885
886 static void
create_folder_redo_func(NautilusFileUndoInfoCreate * self,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)887 create_folder_redo_func (NautilusFileUndoInfoCreate *self,
888 GtkWindow *parent_window,
889 NautilusFileOperationsDBusData *dbus_data)
890 {
891 GFile *parent;
892 gchar *parent_uri;
893 gchar *name;
894
895 name = g_file_get_basename (self->target_file);
896 parent = g_file_get_parent (self->target_file);
897 parent_uri = g_file_get_uri (parent);
898 nautilus_file_operations_new_folder (NULL,
899 dbus_data,
900 parent_uri, name,
901 create_callback, self);
902
903 g_free (name);
904 g_free (parent_uri);
905 g_object_unref (parent);
906 }
907
908 static void
create_empty_redo_func(NautilusFileUndoInfoCreate * self,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)909 create_empty_redo_func (NautilusFileUndoInfoCreate *self,
910 GtkWindow *parent_window,
911 NautilusFileOperationsDBusData *dbus_data)
912 {
913 GFile *parent;
914 gchar *parent_uri;
915 gchar *new_name;
916
917 parent = g_file_get_parent (self->target_file);
918 parent_uri = g_file_get_uri (parent);
919 new_name = g_file_get_parse_name (self->target_file);
920 nautilus_file_operations_new_file (NULL, parent_uri,
921 new_name,
922 self->template,
923 self->length,
924 create_callback, self);
925
926 g_free (parent_uri);
927 g_free (new_name);
928 g_object_unref (parent);
929 }
930
931 static void
create_redo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)932 create_redo_func (NautilusFileUndoInfo *info,
933 GtkWindow *parent_window,
934 NautilusFileOperationsDBusData *dbus_data)
935 {
936 NautilusFileUndoInfoCreate *self = NAUTILUS_FILE_UNDO_INFO_CREATE (info);
937 NautilusFileUndoOp op_type = nautilus_file_undo_info_get_op_type (info);
938
939 if (op_type == NAUTILUS_FILE_UNDO_OP_CREATE_EMPTY_FILE)
940 {
941 create_empty_redo_func (self, parent_window, dbus_data);
942 }
943 else if (op_type == NAUTILUS_FILE_UNDO_OP_CREATE_FOLDER)
944 {
945 create_folder_redo_func (self, parent_window, dbus_data);
946 }
947 else if (op_type == NAUTILUS_FILE_UNDO_OP_CREATE_FILE_FROM_TEMPLATE)
948 {
949 create_from_template_redo_func (self, parent_window, dbus_data);
950 }
951 else
952 {
953 g_assert_not_reached ();
954 }
955 }
956
957 static void
create_undo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)958 create_undo_func (NautilusFileUndoInfo *info,
959 GtkWindow *parent_window,
960 NautilusFileOperationsDBusData *dbus_data)
961 {
962 NautilusFileUndoInfoCreate *self = NAUTILUS_FILE_UNDO_INFO_CREATE (info);
963 GList *files = NULL;
964
965 files = g_list_append (files, g_object_ref (self->target_file));
966 nautilus_file_operations_delete_async (files, parent_window,
967 dbus_data,
968 file_undo_info_delete_callback, self);
969
970 g_list_free_full (files, g_object_unref);
971 }
972
973 static void
nautilus_file_undo_info_create_init(NautilusFileUndoInfoCreate * self)974 nautilus_file_undo_info_create_init (NautilusFileUndoInfoCreate *self)
975 {
976 }
977
978 static void
nautilus_file_undo_info_create_finalize(GObject * obj)979 nautilus_file_undo_info_create_finalize (GObject *obj)
980 {
981 NautilusFileUndoInfoCreate *self = NAUTILUS_FILE_UNDO_INFO_CREATE (obj);
982 g_clear_object (&self->target_file);
983 g_free (self->template);
984
985 G_OBJECT_CLASS (nautilus_file_undo_info_create_parent_class)->finalize (obj);
986 }
987
988 static void
nautilus_file_undo_info_create_class_init(NautilusFileUndoInfoCreateClass * klass)989 nautilus_file_undo_info_create_class_init (NautilusFileUndoInfoCreateClass *klass)
990 {
991 GObjectClass *oclass = G_OBJECT_CLASS (klass);
992 NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
993
994 oclass->finalize = nautilus_file_undo_info_create_finalize;
995
996 iclass->undo_func = create_undo_func;
997 iclass->redo_func = create_redo_func;
998 iclass->strings_func = create_strings_func;
999 }
1000
1001 NautilusFileUndoInfo *
nautilus_file_undo_info_create_new(NautilusFileUndoOp op_type)1002 nautilus_file_undo_info_create_new (NautilusFileUndoOp op_type)
1003 {
1004 return g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_CREATE,
1005 "op-type", op_type,
1006 "item-count", 1,
1007 NULL);
1008 }
1009
1010 void
nautilus_file_undo_info_create_set_data(NautilusFileUndoInfoCreate * self,GFile * file,const char * template,gint length)1011 nautilus_file_undo_info_create_set_data (NautilusFileUndoInfoCreate *self,
1012 GFile *file,
1013 const char *template,
1014 gint length)
1015 {
1016 self->target_file = g_object_ref (file);
1017 self->template = g_strdup (template);
1018 self->length = length;
1019 }
1020
1021 /* rename */
1022 struct _NautilusFileUndoInfoRename
1023 {
1024 NautilusFileUndoInfo parent_instance;
1025
1026 GFile *old_file;
1027 GFile *new_file;
1028 gchar *old_display_name;
1029 gchar *new_display_name;
1030 };
1031
G_DEFINE_TYPE(NautilusFileUndoInfoRename,nautilus_file_undo_info_rename,NAUTILUS_TYPE_FILE_UNDO_INFO)1032 G_DEFINE_TYPE (NautilusFileUndoInfoRename, nautilus_file_undo_info_rename, NAUTILUS_TYPE_FILE_UNDO_INFO)
1033
1034 static void
1035 rename_strings_func (NautilusFileUndoInfo *info,
1036 gchar **undo_label,
1037 gchar **undo_description,
1038 gchar **redo_label,
1039 gchar **redo_description)
1040 {
1041 NautilusFileUndoInfoRename *self = NAUTILUS_FILE_UNDO_INFO_RENAME (info);
1042 gchar *new_name, *old_name;
1043
1044 new_name = g_file_get_parse_name (self->new_file);
1045 old_name = g_file_get_parse_name (self->old_file);
1046
1047 *undo_description = g_strdup_printf (_("Rename “%s” as “%s”"), new_name, old_name);
1048 *redo_description = g_strdup_printf (_("Rename “%s” as “%s”"), old_name, new_name);
1049
1050 *undo_label = g_strdup (_("_Undo Rename"));
1051 *redo_label = g_strdup (_("_Redo Rename"));
1052
1053 g_free (old_name);
1054 g_free (new_name);
1055 }
1056
1057 static void
rename_redo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)1058 rename_redo_func (NautilusFileUndoInfo *info,
1059 GtkWindow *parent_window,
1060 NautilusFileOperationsDBusData *dbus_data)
1061 {
1062 NautilusFileUndoInfoRename *self = NAUTILUS_FILE_UNDO_INFO_RENAME (info);
1063 NautilusFile *file;
1064
1065 file = nautilus_file_get (self->old_file);
1066 nautilus_file_rename (file, self->new_display_name,
1067 file_undo_info_operation_callback, self);
1068
1069 nautilus_file_unref (file);
1070 }
1071
1072 static void
rename_undo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)1073 rename_undo_func (NautilusFileUndoInfo *info,
1074 GtkWindow *parent_window,
1075 NautilusFileOperationsDBusData *dbus_data)
1076 {
1077 NautilusFileUndoInfoRename *self = NAUTILUS_FILE_UNDO_INFO_RENAME (info);
1078 NautilusFile *file;
1079
1080 file = nautilus_file_get (self->new_file);
1081 nautilus_file_rename (file, self->old_display_name,
1082 file_undo_info_operation_callback, self);
1083
1084 nautilus_file_unref (file);
1085 }
1086
1087 static void
nautilus_file_undo_info_rename_init(NautilusFileUndoInfoRename * self)1088 nautilus_file_undo_info_rename_init (NautilusFileUndoInfoRename *self)
1089 {
1090 }
1091
1092 static void
nautilus_file_undo_info_rename_finalize(GObject * obj)1093 nautilus_file_undo_info_rename_finalize (GObject *obj)
1094 {
1095 NautilusFileUndoInfoRename *self = NAUTILUS_FILE_UNDO_INFO_RENAME (obj);
1096 g_clear_object (&self->old_file);
1097 g_clear_object (&self->new_file);
1098 g_free (self->old_display_name);
1099 g_free (self->new_display_name);
1100
1101 G_OBJECT_CLASS (nautilus_file_undo_info_rename_parent_class)->finalize (obj);
1102 }
1103
1104 static void
nautilus_file_undo_info_rename_class_init(NautilusFileUndoInfoRenameClass * klass)1105 nautilus_file_undo_info_rename_class_init (NautilusFileUndoInfoRenameClass *klass)
1106 {
1107 GObjectClass *oclass = G_OBJECT_CLASS (klass);
1108 NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
1109
1110 oclass->finalize = nautilus_file_undo_info_rename_finalize;
1111
1112 iclass->undo_func = rename_undo_func;
1113 iclass->redo_func = rename_redo_func;
1114 iclass->strings_func = rename_strings_func;
1115 }
1116
1117 NautilusFileUndoInfo *
nautilus_file_undo_info_rename_new(void)1118 nautilus_file_undo_info_rename_new (void)
1119 {
1120 return g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_RENAME,
1121 "op-type", NAUTILUS_FILE_UNDO_OP_RENAME,
1122 "item-count", 1,
1123 NULL);
1124 }
1125
1126 void
nautilus_file_undo_info_rename_set_data_pre(NautilusFileUndoInfoRename * self,GFile * old_file,gchar * old_display_name,gchar * new_display_name)1127 nautilus_file_undo_info_rename_set_data_pre (NautilusFileUndoInfoRename *self,
1128 GFile *old_file,
1129 gchar *old_display_name,
1130 gchar *new_display_name)
1131 {
1132 self->old_file = g_object_ref (old_file);
1133 self->old_display_name = g_strdup (old_display_name);
1134 self->new_display_name = g_strdup (new_display_name);
1135 }
1136
1137 void
nautilus_file_undo_info_rename_set_data_post(NautilusFileUndoInfoRename * self,GFile * new_file)1138 nautilus_file_undo_info_rename_set_data_post (NautilusFileUndoInfoRename *self,
1139 GFile *new_file)
1140 {
1141 self->new_file = g_object_ref (new_file);
1142 }
1143
1144 /* batch rename */
1145 struct _NautilusFileUndoInfoBatchRename
1146 {
1147 NautilusFileUndoInfo parent_instance;
1148
1149 GList *old_files;
1150 GList *new_files;
1151 GList *old_display_names;
1152 GList *new_display_names;
1153 };
1154
1155 G_DEFINE_TYPE (NautilusFileUndoInfoBatchRename, nautilus_file_undo_info_batch_rename, NAUTILUS_TYPE_FILE_UNDO_INFO);
1156
1157 static void
batch_rename_strings_func(NautilusFileUndoInfo * info,gchar ** undo_label,gchar ** undo_description,gchar ** redo_label,gchar ** redo_description)1158 batch_rename_strings_func (NautilusFileUndoInfo *info,
1159 gchar **undo_label,
1160 gchar **undo_description,
1161 gchar **redo_label,
1162 gchar **redo_description)
1163 {
1164 NautilusFileUndoInfoBatchRename *self = NAUTILUS_FILE_UNDO_INFO_BATCH_RENAME (info);
1165
1166 *undo_description = g_strdup_printf (ngettext ("Batch rename %d file",
1167 "Batch rename %d files",
1168 g_list_length (self->new_files)),
1169 g_list_length (self->new_files));
1170 *redo_description = g_strdup_printf (ngettext ("Batch rename %d file",
1171 "Batch rename %d files",
1172 g_list_length (self->new_files)),
1173 g_list_length (self->new_files));
1174
1175 *undo_label = g_strdup (_("_Undo Batch Rename"));
1176 *redo_label = g_strdup (_("_Redo Batch Rename"));
1177 }
1178
1179 static void
batch_rename_redo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)1180 batch_rename_redo_func (NautilusFileUndoInfo *info,
1181 GtkWindow *parent_window,
1182 NautilusFileOperationsDBusData *dbus_data)
1183 {
1184 NautilusFileUndoInfoBatchRename *self = NAUTILUS_FILE_UNDO_INFO_BATCH_RENAME (info);
1185
1186 GList *l, *files;
1187 NautilusFile *file;
1188 GFile *old_file;
1189
1190 files = NULL;
1191
1192 for (l = self->old_files; l != NULL; l = l->next)
1193 {
1194 old_file = l->data;
1195
1196 file = nautilus_file_get (old_file);
1197 files = g_list_prepend (files, file);
1198 }
1199
1200 files = g_list_reverse (files);
1201
1202 batch_rename_sort_lists_for_rename (&files,
1203 &self->new_display_names,
1204 &self->old_display_names,
1205 &self->new_files,
1206 &self->old_files,
1207 TRUE);
1208
1209 nautilus_file_batch_rename (files, self->new_display_names, file_undo_info_operation_callback, self);
1210 }
1211
1212 static void
batch_rename_undo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)1213 batch_rename_undo_func (NautilusFileUndoInfo *info,
1214 GtkWindow *parent_window,
1215 NautilusFileOperationsDBusData *dbus_data)
1216 {
1217 NautilusFileUndoInfoBatchRename *self = NAUTILUS_FILE_UNDO_INFO_BATCH_RENAME (info);
1218
1219 GList *l, *files;
1220 NautilusFile *file;
1221 GFile *new_file;
1222
1223 files = NULL;
1224
1225 for (l = self->new_files; l != NULL; l = l->next)
1226 {
1227 new_file = l->data;
1228
1229 file = nautilus_file_get (new_file);
1230 files = g_list_prepend (files, file);
1231 }
1232
1233 files = g_list_reverse (files);
1234
1235 batch_rename_sort_lists_for_rename (&files,
1236 &self->old_display_names,
1237 &self->new_display_names,
1238 &self->old_files,
1239 &self->new_files,
1240 TRUE);
1241
1242 nautilus_file_batch_rename (files, self->old_display_names, file_undo_info_operation_callback, self);
1243 }
1244
1245 static void
nautilus_file_undo_info_batch_rename_init(NautilusFileUndoInfoBatchRename * self)1246 nautilus_file_undo_info_batch_rename_init (NautilusFileUndoInfoBatchRename *self)
1247 {
1248 }
1249
1250 static void
nautilus_file_undo_info_batch_rename_finalize(GObject * obj)1251 nautilus_file_undo_info_batch_rename_finalize (GObject *obj)
1252 {
1253 GList *l;
1254 GFile *file;
1255 GString *string;
1256 NautilusFileUndoInfoBatchRename *self = NAUTILUS_FILE_UNDO_INFO_BATCH_RENAME (obj);
1257
1258 for (l = self->new_files; l != NULL; l = l->next)
1259 {
1260 file = l->data;
1261
1262 g_clear_object (&file);
1263 }
1264
1265 for (l = self->old_files; l != NULL; l = l->next)
1266 {
1267 file = l->data;
1268
1269 g_clear_object (&file);
1270 }
1271
1272 for (l = self->new_display_names; l != NULL; l = l->next)
1273 {
1274 string = l->data;
1275
1276 g_string_free (string, TRUE);
1277 }
1278
1279 for (l = self->old_display_names; l != NULL; l = l->next)
1280 {
1281 string = l->data;
1282
1283 g_string_free (string, TRUE);
1284 }
1285
1286 g_list_free (self->new_files);
1287 g_list_free (self->old_files);
1288 g_list_free (self->new_display_names);
1289 g_list_free (self->old_display_names);
1290
1291 G_OBJECT_CLASS (nautilus_file_undo_info_batch_rename_parent_class)->finalize (obj);
1292 }
1293
1294 static void
nautilus_file_undo_info_batch_rename_class_init(NautilusFileUndoInfoBatchRenameClass * klass)1295 nautilus_file_undo_info_batch_rename_class_init (NautilusFileUndoInfoBatchRenameClass *klass)
1296 {
1297 GObjectClass *oclass = G_OBJECT_CLASS (klass);
1298 NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
1299
1300 oclass->finalize = nautilus_file_undo_info_batch_rename_finalize;
1301
1302 iclass->undo_func = batch_rename_undo_func;
1303 iclass->redo_func = batch_rename_redo_func;
1304 iclass->strings_func = batch_rename_strings_func;
1305 }
1306
1307 NautilusFileUndoInfo *
nautilus_file_undo_info_batch_rename_new(gint item_count)1308 nautilus_file_undo_info_batch_rename_new (gint item_count)
1309 {
1310 return g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_BATCH_RENAME,
1311 "op-type", NAUTILUS_FILE_UNDO_OP_BATCH_RENAME,
1312 "item-count", item_count,
1313 NULL);
1314 }
1315
1316 void
nautilus_file_undo_info_batch_rename_set_data_pre(NautilusFileUndoInfoBatchRename * self,GList * old_files)1317 nautilus_file_undo_info_batch_rename_set_data_pre (NautilusFileUndoInfoBatchRename *self,
1318 GList *old_files)
1319 {
1320 GList *l;
1321 GString *old_name;
1322 GFile *file;
1323
1324 self->old_files = old_files;
1325 self->old_display_names = NULL;
1326
1327 for (l = old_files; l != NULL; l = l->next)
1328 {
1329 file = l->data;
1330
1331 old_name = g_string_new (g_file_get_basename (file));
1332
1333 self->old_display_names = g_list_prepend (self->old_display_names, old_name);
1334 }
1335
1336 self->old_display_names = g_list_reverse (self->old_display_names);
1337 }
1338
1339 void
nautilus_file_undo_info_batch_rename_set_data_post(NautilusFileUndoInfoBatchRename * self,GList * new_files)1340 nautilus_file_undo_info_batch_rename_set_data_post (NautilusFileUndoInfoBatchRename *self,
1341 GList *new_files)
1342 {
1343 GList *l;
1344 GString *new_name;
1345 GFile *file;
1346
1347 self->new_files = new_files;
1348 self->new_display_names = NULL;
1349
1350 for (l = new_files; l != NULL; l = l->next)
1351 {
1352 file = l->data;
1353
1354 new_name = g_string_new (g_file_get_basename (file));
1355
1356 self->new_display_names = g_list_prepend (self->new_display_names, new_name);
1357 }
1358
1359 self->new_display_names = g_list_reverse (self->new_display_names);
1360 }
1361
1362 /* starred files */
1363 struct _NautilusFileUndoInfoStarred
1364 {
1365 NautilusFileUndoInfo parent_instance;
1366
1367 GList *files;
1368 /* Whether the action was starring or unstarring */
1369 gboolean starred;
1370 };
1371
1372 G_DEFINE_TYPE (NautilusFileUndoInfoStarred, nautilus_file_undo_info_starred, NAUTILUS_TYPE_FILE_UNDO_INFO);
1373
1374 enum
1375 {
1376 PROP_FILES = 1,
1377 PROP_STARRED,
1378 NUM_PROPERTIES
1379 };
1380
1381 static void
starred_strings_func(NautilusFileUndoInfo * info,gchar ** undo_label,gchar ** undo_description,gchar ** redo_label,gchar ** redo_description)1382 starred_strings_func (NautilusFileUndoInfo *info,
1383 gchar **undo_label,
1384 gchar **undo_description,
1385 gchar **redo_label,
1386 gchar **redo_description)
1387 {
1388 NautilusFileUndoInfoStarred *self = NAUTILUS_FILE_UNDO_INFO_STARRED (info);
1389
1390 if (self->starred)
1391 {
1392 *undo_description = g_strdup_printf (ngettext ("Unstar %d file",
1393 "Unstar %d files",
1394 g_list_length (self->files)),
1395 g_list_length (self->files));
1396 *redo_description = g_strdup_printf (ngettext ("Star %d file",
1397 "Star %d files",
1398 g_list_length (self->files)),
1399 g_list_length (self->files));
1400 *undo_label = g_strdup (_("_Undo Starring"));
1401 *redo_label = g_strdup (_("_Redo Starring"));
1402 }
1403 else
1404 {
1405 *undo_description = g_strdup_printf (ngettext ("Star %d file",
1406 "Star %d files",
1407 g_list_length (self->files)),
1408 g_list_length (self->files));
1409 *redo_description = g_strdup_printf (ngettext ("Unstar %d file",
1410 "Unstar %d files",
1411 g_list_length (self->files)),
1412 g_list_length (self->files));
1413 *undo_label = g_strdup (_("_Undo Unstarring"));
1414 *redo_label = g_strdup (_("_Redo Unstarring"));
1415 }
1416 }
1417
1418 static void
on_undo_starred_tags_updated(GObject * object,GAsyncResult * res,gpointer user_data)1419 on_undo_starred_tags_updated (GObject *object,
1420 GAsyncResult *res,
1421 gpointer user_data)
1422 {
1423 GTask *task;
1424 NautilusFileUndoInfo *undo_info;
1425
1426 undo_info = NAUTILUS_FILE_UNDO_INFO (object);
1427
1428 task = user_data;
1429 g_clear_object (&task);
1430
1431 file_undo_info_operation_callback (NULL, NULL, NULL, undo_info);
1432 }
1433
1434 static void
starred_redo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)1435 starred_redo_func (NautilusFileUndoInfo *info,
1436 GtkWindow *parent_window,
1437 NautilusFileOperationsDBusData *dbus_data)
1438 {
1439 NautilusFileUndoInfoStarred *self = NAUTILUS_FILE_UNDO_INFO_STARRED (info);
1440 g_autoptr (NautilusTagManager) tag_manager = nautilus_tag_manager_get ();
1441
1442 if (self->starred)
1443 {
1444 nautilus_tag_manager_star_files (tag_manager,
1445 G_OBJECT (info),
1446 self->files,
1447 on_undo_starred_tags_updated,
1448 NULL);
1449 }
1450 else
1451 {
1452 nautilus_tag_manager_unstar_files (tag_manager,
1453 G_OBJECT (info),
1454 self->files,
1455 on_undo_starred_tags_updated,
1456 NULL);
1457 }
1458 }
1459
1460 static void
starred_undo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)1461 starred_undo_func (NautilusFileUndoInfo *info,
1462 GtkWindow *parent_window,
1463 NautilusFileOperationsDBusData *dbus_data)
1464 {
1465 NautilusFileUndoInfoStarred *self = NAUTILUS_FILE_UNDO_INFO_STARRED (info);
1466 g_autoptr (NautilusTagManager) tag_manager = nautilus_tag_manager_get ();
1467
1468 if (self->starred)
1469 {
1470 nautilus_tag_manager_unstar_files (tag_manager,
1471 G_OBJECT (info),
1472 self->files,
1473 on_undo_starred_tags_updated,
1474 NULL);
1475 }
1476 else
1477 {
1478 nautilus_tag_manager_star_files (tag_manager,
1479 G_OBJECT (info),
1480 self->files,
1481 on_undo_starred_tags_updated,
1482 NULL);
1483 }
1484 }
1485
1486 static void
nautilus_file_undo_info_starred_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1487 nautilus_file_undo_info_starred_set_property (GObject *object,
1488 guint prop_id,
1489 const GValue *value,
1490 GParamSpec *pspec)
1491 {
1492 NautilusFileUndoInfoStarred *self = NAUTILUS_FILE_UNDO_INFO_STARRED (object);
1493
1494 switch (prop_id)
1495 {
1496 case PROP_FILES:
1497 {
1498 self->files = nautilus_file_list_copy (g_value_get_pointer (value));
1499 }
1500 break;
1501
1502 case PROP_STARRED:
1503 {
1504 self->starred = g_value_get_boolean (value);
1505 }
1506 break;
1507
1508 default:
1509 {
1510 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1511 }
1512 }
1513 }
1514
1515 static void
nautilus_file_undo_info_starred_init(NautilusFileUndoInfoStarred * self)1516 nautilus_file_undo_info_starred_init (NautilusFileUndoInfoStarred *self)
1517 {
1518 }
1519
1520 static void
nautilus_file_undo_info_starred_finalize(GObject * obj)1521 nautilus_file_undo_info_starred_finalize (GObject *obj)
1522 {
1523 NautilusFileUndoInfoStarred *self = NAUTILUS_FILE_UNDO_INFO_STARRED (obj);
1524
1525 nautilus_file_list_free (self->files);
1526
1527 G_OBJECT_CLASS (nautilus_file_undo_info_starred_parent_class)->finalize (obj);
1528 }
1529
1530 static void
nautilus_file_undo_info_starred_class_init(NautilusFileUndoInfoStarredClass * klass)1531 nautilus_file_undo_info_starred_class_init (NautilusFileUndoInfoStarredClass *klass)
1532 {
1533 GObjectClass *oclass = G_OBJECT_CLASS (klass);
1534 NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
1535
1536 oclass->finalize = nautilus_file_undo_info_starred_finalize;
1537 oclass->set_property = nautilus_file_undo_info_starred_set_property;
1538
1539 iclass->undo_func = starred_undo_func;
1540 iclass->redo_func = starred_redo_func;
1541 iclass->strings_func = starred_strings_func;
1542
1543 g_object_class_install_property (oclass,
1544 PROP_FILES,
1545 g_param_spec_pointer ("files",
1546 "files",
1547 "The files for which to undo star/unstar",
1548 G_PARAM_WRITABLE |
1549 G_PARAM_CONSTRUCT_ONLY));
1550 g_object_class_install_property (oclass,
1551 PROP_STARRED,
1552 g_param_spec_boolean ("starred",
1553 "starred",
1554 "Whether the files were starred or unstarred",
1555 FALSE,
1556 G_PARAM_WRITABLE |
1557 G_PARAM_CONSTRUCT_ONLY));
1558 }
1559
1560 GList *
nautilus_file_undo_info_starred_get_files(NautilusFileUndoInfoStarred * self)1561 nautilus_file_undo_info_starred_get_files (NautilusFileUndoInfoStarred *self)
1562 {
1563 return self->files;
1564 }
1565
1566 gboolean
nautilus_file_undo_info_starred_is_starred(NautilusFileUndoInfoStarred * self)1567 nautilus_file_undo_info_starred_is_starred (NautilusFileUndoInfoStarred *self)
1568 {
1569 return self->starred;
1570 }
1571
1572 NautilusFileUndoInfo *
nautilus_file_undo_info_starred_new(GList * files,gboolean starred)1573 nautilus_file_undo_info_starred_new (GList *files,
1574 gboolean starred)
1575 {
1576 NautilusFileUndoInfoStarred *self;
1577
1578 self = g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_STARRED,
1579 "op-type", NAUTILUS_FILE_UNDO_OP_STARRED,
1580 "item-count", g_list_length (files),
1581 "files", files,
1582 "starred", starred,
1583 NULL);
1584
1585 return NAUTILUS_FILE_UNDO_INFO (self);
1586 }
1587
1588 /* trash */
1589 struct _NautilusFileUndoInfoTrash
1590 {
1591 NautilusFileUndoInfo parent_instance;
1592
1593 GHashTable *trashed;
1594 };
1595
G_DEFINE_TYPE(NautilusFileUndoInfoTrash,nautilus_file_undo_info_trash,NAUTILUS_TYPE_FILE_UNDO_INFO)1596 G_DEFINE_TYPE (NautilusFileUndoInfoTrash, nautilus_file_undo_info_trash, NAUTILUS_TYPE_FILE_UNDO_INFO)
1597
1598 static void
1599 trash_strings_func (NautilusFileUndoInfo *info,
1600 gchar **undo_label,
1601 gchar **undo_description,
1602 gchar **redo_label,
1603 gchar **redo_description)
1604 {
1605 NautilusFileUndoInfoTrash *self = NAUTILUS_FILE_UNDO_INFO_TRASH (info);
1606 gint count = g_hash_table_size (self->trashed);
1607
1608 if (count != 1)
1609 {
1610 *undo_description = g_strdup_printf (ngettext ("Restore %d item from trash",
1611 "Restore %d items from trash", count),
1612 count);
1613 *redo_description = g_strdup_printf (ngettext ("Move %d item to trash",
1614 "Move %d items to trash", count),
1615 count);
1616 }
1617 else
1618 {
1619 GList *keys;
1620 char *name, *orig_path;
1621 GFile *file;
1622
1623 keys = g_hash_table_get_keys (self->trashed);
1624 file = keys->data;
1625 name = g_file_get_basename (file);
1626 orig_path = g_file_get_path (file);
1627 *undo_description = g_strdup_printf (_("Restore “%s” to “%s”"), name, orig_path);
1628
1629 g_free (name);
1630 g_free (orig_path);
1631 g_list_free (keys);
1632
1633 name = g_file_get_parse_name (file);
1634 *redo_description = g_strdup_printf (_("Move “%s” to trash"), name);
1635
1636 g_free (name);
1637 }
1638
1639 *undo_label = g_strdup (_("_Undo Trash"));
1640 *redo_label = g_strdup (_("_Redo Trash"));
1641 }
1642
1643 static void
trash_redo_func_callback(GHashTable * debuting_uris,gboolean user_cancel,gpointer user_data)1644 trash_redo_func_callback (GHashTable *debuting_uris,
1645 gboolean user_cancel,
1646 gpointer user_data)
1647 {
1648 NautilusFileUndoInfoTrash *self = user_data;
1649 GHashTable *new_trashed_files;
1650 GTimeVal current_time;
1651 gsize updated_trash_time;
1652 GFile *file;
1653 GList *keys, *l;
1654
1655 if (!user_cancel)
1656 {
1657 new_trashed_files =
1658 g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal,
1659 g_object_unref, NULL);
1660
1661 keys = g_hash_table_get_keys (self->trashed);
1662
1663 g_get_current_time (¤t_time);
1664 updated_trash_time = current_time.tv_sec;
1665
1666 for (l = keys; l != NULL; l = l->next)
1667 {
1668 file = l->data;
1669 g_hash_table_insert (new_trashed_files,
1670 g_object_ref (file), GSIZE_TO_POINTER (updated_trash_time));
1671 }
1672
1673 g_list_free (keys);
1674 g_hash_table_destroy (self->trashed);
1675
1676 self->trashed = new_trashed_files;
1677 }
1678
1679 file_undo_info_delete_callback (debuting_uris, user_cancel, user_data);
1680 }
1681
1682 static void
trash_redo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)1683 trash_redo_func (NautilusFileUndoInfo *info,
1684 GtkWindow *parent_window,
1685 NautilusFileOperationsDBusData *dbus_data)
1686 {
1687 NautilusFileUndoInfoTrash *self = NAUTILUS_FILE_UNDO_INFO_TRASH (info);
1688
1689 if (g_hash_table_size (self->trashed) > 0)
1690 {
1691 GList *locations;
1692
1693 locations = g_hash_table_get_keys (self->trashed);
1694 nautilus_file_operations_trash_or_delete_async (locations, parent_window,
1695 dbus_data,
1696 trash_redo_func_callback, self);
1697
1698 g_list_free (locations);
1699 }
1700 }
1701
1702 static void
trash_retrieve_files_to_restore_thread(GTask * task,gpointer source_object,gpointer task_data,GCancellable * cancellable)1703 trash_retrieve_files_to_restore_thread (GTask *task,
1704 gpointer source_object,
1705 gpointer task_data,
1706 GCancellable *cancellable)
1707 {
1708 NautilusFileUndoInfoTrash *self = NAUTILUS_FILE_UNDO_INFO_TRASH (source_object);
1709 GFileEnumerator *enumerator;
1710 GHashTable *to_restore;
1711 GFile *trash;
1712 GError *error = NULL;
1713
1714 to_restore = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal,
1715 g_object_unref, g_object_unref);
1716
1717 trash = g_file_new_for_uri ("trash:///");
1718
1719 enumerator = g_file_enumerate_children (trash,
1720 G_FILE_ATTRIBUTE_STANDARD_NAME ","
1721 G_FILE_ATTRIBUTE_TRASH_DELETION_DATE ","
1722 G_FILE_ATTRIBUTE_TRASH_ORIG_PATH,
1723 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1724 NULL, &error);
1725
1726 if (enumerator)
1727 {
1728 GFileInfo *info;
1729 gpointer lookupvalue;
1730 GFile *item;
1731 glong trash_time, orig_trash_time;
1732 const char *origpath;
1733 GFile *origfile;
1734
1735 while ((info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL)
1736 {
1737 /* Retrieve the original file uri */
1738 origpath = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH);
1739 origfile = g_file_new_for_path (origpath);
1740
1741 lookupvalue = g_hash_table_lookup (self->trashed, origfile);
1742
1743 if (lookupvalue)
1744 {
1745 GDateTime *date;
1746
1747 orig_trash_time = GPOINTER_TO_SIZE (lookupvalue);
1748 trash_time = 0;
1749 date = g_file_info_get_deletion_date (info);
1750 if (date)
1751 {
1752 trash_time = g_date_time_to_unix (date);
1753 g_date_time_unref (date);
1754 }
1755
1756 if (ABS (orig_trash_time - trash_time) <= TRASH_TIME_EPSILON)
1757 {
1758 /* File in the trash */
1759 item = g_file_get_child (trash, g_file_info_get_name (info));
1760 g_hash_table_insert (to_restore, item, g_object_ref (origfile));
1761 }
1762 }
1763
1764 g_object_unref (origfile);
1765 }
1766 g_file_enumerator_close (enumerator, FALSE, NULL);
1767 g_object_unref (enumerator);
1768 }
1769 g_object_unref (trash);
1770
1771 if (error != NULL)
1772 {
1773 g_task_return_error (task, error);
1774 g_hash_table_destroy (to_restore);
1775 }
1776 else
1777 {
1778 g_task_return_pointer (task, to_restore, NULL);
1779 }
1780 }
1781
1782 static void
trash_retrieve_files_to_restore_async(NautilusFileUndoInfoTrash * self,GAsyncReadyCallback callback,gpointer user_data)1783 trash_retrieve_files_to_restore_async (NautilusFileUndoInfoTrash *self,
1784 GAsyncReadyCallback callback,
1785 gpointer user_data)
1786 {
1787 GTask *task;
1788
1789 task = g_task_new (G_OBJECT (self), NULL, callback, user_data);
1790
1791 g_task_run_in_thread (task, trash_retrieve_files_to_restore_thread);
1792
1793 g_object_unref (task);
1794 }
1795
1796 static void
trash_retrieve_files_ready(GObject * source,GAsyncResult * res,gpointer user_data)1797 trash_retrieve_files_ready (GObject *source,
1798 GAsyncResult *res,
1799 gpointer user_data)
1800 {
1801 NautilusFileUndoInfoTrash *self = NAUTILUS_FILE_UNDO_INFO_TRASH (source);
1802 GHashTable *files_to_restore;
1803 GError *error = NULL;
1804
1805 files_to_restore = g_task_propagate_pointer (G_TASK (res), &error);
1806
1807 if (error == NULL && g_hash_table_size (files_to_restore) > 0)
1808 {
1809 GList *gfiles_in_trash, *l;
1810 GFile *item;
1811 GFile *dest;
1812
1813 gfiles_in_trash = g_hash_table_get_keys (files_to_restore);
1814
1815 for (l = gfiles_in_trash; l != NULL; l = l->next)
1816 {
1817 item = l->data;
1818 dest = g_hash_table_lookup (files_to_restore, item);
1819
1820 g_file_move (item, dest, G_FILE_COPY_NOFOLLOW_SYMLINKS, NULL, NULL, NULL, NULL);
1821 }
1822
1823 g_list_free (gfiles_in_trash);
1824
1825 /* Here we must do what's necessary for the callback */
1826 file_undo_info_transfer_callback (NULL, (error == NULL), self);
1827 }
1828 else
1829 {
1830 file_undo_info_transfer_callback (NULL, FALSE, self);
1831 }
1832
1833 if (files_to_restore != NULL)
1834 {
1835 g_hash_table_destroy (files_to_restore);
1836 }
1837
1838 g_clear_error (&error);
1839 }
1840
1841 static void
trash_undo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)1842 trash_undo_func (NautilusFileUndoInfo *info,
1843 GtkWindow *parent_window,
1844 NautilusFileOperationsDBusData *dbus_data)
1845 {
1846 NautilusFileUndoInfoTrash *self = NAUTILUS_FILE_UNDO_INFO_TRASH (info);
1847
1848 trash_retrieve_files_to_restore_async (self, trash_retrieve_files_ready, NULL);
1849 }
1850
1851 static void
nautilus_file_undo_info_trash_init(NautilusFileUndoInfoTrash * self)1852 nautilus_file_undo_info_trash_init (NautilusFileUndoInfoTrash *self)
1853 {
1854 self->trashed = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal,
1855 g_object_unref, NULL);
1856 }
1857
1858 static void
nautilus_file_undo_info_trash_finalize(GObject * obj)1859 nautilus_file_undo_info_trash_finalize (GObject *obj)
1860 {
1861 NautilusFileUndoInfoTrash *self = NAUTILUS_FILE_UNDO_INFO_TRASH (obj);
1862 g_hash_table_destroy (self->trashed);
1863
1864 G_OBJECT_CLASS (nautilus_file_undo_info_trash_parent_class)->finalize (obj);
1865 }
1866
1867 static void
nautilus_file_undo_info_trash_class_init(NautilusFileUndoInfoTrashClass * klass)1868 nautilus_file_undo_info_trash_class_init (NautilusFileUndoInfoTrashClass *klass)
1869 {
1870 GObjectClass *oclass = G_OBJECT_CLASS (klass);
1871 NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
1872
1873 oclass->finalize = nautilus_file_undo_info_trash_finalize;
1874
1875 iclass->undo_func = trash_undo_func;
1876 iclass->redo_func = trash_redo_func;
1877 iclass->strings_func = trash_strings_func;
1878 }
1879
1880 NautilusFileUndoInfo *
nautilus_file_undo_info_trash_new(gint item_count)1881 nautilus_file_undo_info_trash_new (gint item_count)
1882 {
1883 return g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_TRASH,
1884 "op-type", NAUTILUS_FILE_UNDO_OP_MOVE_TO_TRASH,
1885 "item-count", item_count,
1886 NULL);
1887 }
1888
1889 void
nautilus_file_undo_info_trash_add_file(NautilusFileUndoInfoTrash * self,GFile * file)1890 nautilus_file_undo_info_trash_add_file (NautilusFileUndoInfoTrash *self,
1891 GFile *file)
1892 {
1893 GTimeVal current_time;
1894 gsize orig_trash_time;
1895
1896 g_get_current_time (¤t_time);
1897 orig_trash_time = current_time.tv_sec;
1898
1899 g_hash_table_insert (self->trashed, g_object_ref (file), GSIZE_TO_POINTER (orig_trash_time));
1900 }
1901
1902 GList *
nautilus_file_undo_info_trash_get_files(NautilusFileUndoInfoTrash * self)1903 nautilus_file_undo_info_trash_get_files (NautilusFileUndoInfoTrash *self)
1904 {
1905 return g_hash_table_get_keys (self->trashed);
1906 }
1907
1908 /* recursive permissions */
1909 struct _NautilusFileUndoInfoRecPermissions
1910 {
1911 NautilusFileUndoInfo parent_instance;
1912
1913 GFile *dest_dir;
1914 GHashTable *original_permissions;
1915 guint32 dir_mask;
1916 guint32 dir_permissions;
1917 guint32 file_mask;
1918 guint32 file_permissions;
1919 };
1920
G_DEFINE_TYPE(NautilusFileUndoInfoRecPermissions,nautilus_file_undo_info_rec_permissions,NAUTILUS_TYPE_FILE_UNDO_INFO)1921 G_DEFINE_TYPE (NautilusFileUndoInfoRecPermissions, nautilus_file_undo_info_rec_permissions, NAUTILUS_TYPE_FILE_UNDO_INFO)
1922
1923 static void
1924 rec_permissions_strings_func (NautilusFileUndoInfo *info,
1925 gchar **undo_label,
1926 gchar **undo_description,
1927 gchar **redo_label,
1928 gchar **redo_description)
1929 {
1930 NautilusFileUndoInfoRecPermissions *self = NAUTILUS_FILE_UNDO_INFO_REC_PERMISSIONS (info);
1931 char *name;
1932
1933 name = g_file_get_path (self->dest_dir);
1934
1935 *undo_description = g_strdup_printf (_("Restore original permissions of items enclosed in “%s”"), name);
1936 *redo_description = g_strdup_printf (_("Set permissions of items enclosed in “%s”"), name);
1937
1938 *undo_label = g_strdup (_("_Undo Change Permissions"));
1939 *redo_label = g_strdup (_("_Redo Change Permissions"));
1940
1941 g_free (name);
1942 }
1943
1944 static void
rec_permissions_callback(gboolean success,gpointer callback_data)1945 rec_permissions_callback (gboolean success,
1946 gpointer callback_data)
1947 {
1948 file_undo_info_transfer_callback (NULL, success, callback_data);
1949 }
1950
1951 static void
rec_permissions_redo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)1952 rec_permissions_redo_func (NautilusFileUndoInfo *info,
1953 GtkWindow *parent_window,
1954 NautilusFileOperationsDBusData *dbus_data)
1955 {
1956 NautilusFileUndoInfoRecPermissions *self = NAUTILUS_FILE_UNDO_INFO_REC_PERMISSIONS (info);
1957 gchar *parent_uri;
1958
1959 parent_uri = g_file_get_uri (self->dest_dir);
1960 nautilus_file_set_permissions_recursive (parent_uri,
1961 self->file_permissions,
1962 self->file_mask,
1963 self->dir_permissions,
1964 self->dir_mask,
1965 rec_permissions_callback, self);
1966 g_free (parent_uri);
1967 }
1968
1969 static void
rec_permissions_undo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)1970 rec_permissions_undo_func (NautilusFileUndoInfo *info,
1971 GtkWindow *parent_window,
1972 NautilusFileOperationsDBusData *dbus_data)
1973 {
1974 NautilusFileUndoInfoRecPermissions *self = NAUTILUS_FILE_UNDO_INFO_REC_PERMISSIONS (info);
1975
1976 if (g_hash_table_size (self->original_permissions) > 0)
1977 {
1978 GList *gfiles_list;
1979 guint32 perm;
1980 GList *l;
1981 GFile *dest;
1982 char *item;
1983
1984 gfiles_list = g_hash_table_get_keys (self->original_permissions);
1985 for (l = gfiles_list; l != NULL; l = l->next)
1986 {
1987 item = l->data;
1988 perm = GPOINTER_TO_UINT (g_hash_table_lookup (self->original_permissions, item));
1989 dest = g_file_new_for_uri (item);
1990 g_file_set_attribute_uint32 (dest,
1991 G_FILE_ATTRIBUTE_UNIX_MODE,
1992 perm, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
1993 g_object_unref (dest);
1994 }
1995
1996 g_list_free (gfiles_list);
1997 /* Here we must do what's necessary for the callback */
1998 file_undo_info_transfer_callback (NULL, TRUE, self);
1999 }
2000 }
2001
2002 static void
nautilus_file_undo_info_rec_permissions_init(NautilusFileUndoInfoRecPermissions * self)2003 nautilus_file_undo_info_rec_permissions_init (NautilusFileUndoInfoRecPermissions *self)
2004 {
2005 self->original_permissions = g_hash_table_new_full (g_str_hash, g_str_equal,
2006 g_free, NULL);
2007 }
2008
2009 static void
nautilus_file_undo_info_rec_permissions_finalize(GObject * obj)2010 nautilus_file_undo_info_rec_permissions_finalize (GObject *obj)
2011 {
2012 NautilusFileUndoInfoRecPermissions *self = NAUTILUS_FILE_UNDO_INFO_REC_PERMISSIONS (obj);
2013
2014 g_hash_table_destroy (self->original_permissions);
2015 g_clear_object (&self->dest_dir);
2016
2017 G_OBJECT_CLASS (nautilus_file_undo_info_rec_permissions_parent_class)->finalize (obj);
2018 }
2019
2020 static void
nautilus_file_undo_info_rec_permissions_class_init(NautilusFileUndoInfoRecPermissionsClass * klass)2021 nautilus_file_undo_info_rec_permissions_class_init (NautilusFileUndoInfoRecPermissionsClass *klass)
2022 {
2023 GObjectClass *oclass = G_OBJECT_CLASS (klass);
2024 NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
2025
2026 oclass->finalize = nautilus_file_undo_info_rec_permissions_finalize;
2027
2028 iclass->undo_func = rec_permissions_undo_func;
2029 iclass->redo_func = rec_permissions_redo_func;
2030 iclass->strings_func = rec_permissions_strings_func;
2031 }
2032
2033 NautilusFileUndoInfo *
nautilus_file_undo_info_rec_permissions_new(GFile * dest,guint32 file_permissions,guint32 file_mask,guint32 dir_permissions,guint32 dir_mask)2034 nautilus_file_undo_info_rec_permissions_new (GFile *dest,
2035 guint32 file_permissions,
2036 guint32 file_mask,
2037 guint32 dir_permissions,
2038 guint32 dir_mask)
2039 {
2040 NautilusFileUndoInfoRecPermissions *self;
2041
2042 self = g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_REC_PERMISSIONS,
2043 "op-type", NAUTILUS_FILE_UNDO_OP_RECURSIVE_SET_PERMISSIONS,
2044 "item-count", 1,
2045 NULL);
2046
2047 self->dest_dir = g_object_ref (dest);
2048 self->file_permissions = file_permissions;
2049 self->file_mask = file_mask;
2050 self->dir_permissions = dir_permissions;
2051 self->dir_mask = dir_mask;
2052
2053 return NAUTILUS_FILE_UNDO_INFO (self);
2054 }
2055
2056 void
nautilus_file_undo_info_rec_permissions_add_file(NautilusFileUndoInfoRecPermissions * self,GFile * file,guint32 permission)2057 nautilus_file_undo_info_rec_permissions_add_file (NautilusFileUndoInfoRecPermissions *self,
2058 GFile *file,
2059 guint32 permission)
2060 {
2061 gchar *original_uri = g_file_get_uri (file);
2062 g_hash_table_insert (self->original_permissions, original_uri, GUINT_TO_POINTER (permission));
2063 }
2064
2065 /* single file change permissions */
2066 struct _NautilusFileUndoInfoPermissions
2067 {
2068 NautilusFileUndoInfo parent_instance;
2069
2070 GFile *target_file;
2071 guint32 current_permissions;
2072 guint32 new_permissions;
2073 };
2074
G_DEFINE_TYPE(NautilusFileUndoInfoPermissions,nautilus_file_undo_info_permissions,NAUTILUS_TYPE_FILE_UNDO_INFO)2075 G_DEFINE_TYPE (NautilusFileUndoInfoPermissions, nautilus_file_undo_info_permissions, NAUTILUS_TYPE_FILE_UNDO_INFO)
2076
2077 static void
2078 permissions_strings_func (NautilusFileUndoInfo *info,
2079 gchar **undo_label,
2080 gchar **undo_description,
2081 gchar **redo_label,
2082 gchar **redo_description)
2083 {
2084 NautilusFileUndoInfoPermissions *self = NAUTILUS_FILE_UNDO_INFO_PERMISSIONS (info);
2085 gchar *name;
2086
2087 name = g_file_get_parse_name (self->target_file);
2088 *undo_description = g_strdup_printf (_("Restore original permissions of “%s”"), name);
2089 *redo_description = g_strdup_printf (_("Set permissions of “%s”"), name);
2090
2091 *undo_label = g_strdup (_("_Undo Change Permissions"));
2092 *redo_label = g_strdup (_("_Redo Change Permissions"));
2093
2094 g_free (name);
2095 }
2096
2097 static void
permissions_real_func(NautilusFileUndoInfoPermissions * self,guint32 permissions)2098 permissions_real_func (NautilusFileUndoInfoPermissions *self,
2099 guint32 permissions)
2100 {
2101 NautilusFile *file;
2102
2103 file = nautilus_file_get (self->target_file);
2104 nautilus_file_set_permissions (file, permissions,
2105 file_undo_info_operation_callback, self);
2106
2107 nautilus_file_unref (file);
2108 }
2109
2110 static void
permissions_redo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)2111 permissions_redo_func (NautilusFileUndoInfo *info,
2112 GtkWindow *parent_window,
2113 NautilusFileOperationsDBusData *dbus_data)
2114 {
2115 NautilusFileUndoInfoPermissions *self = NAUTILUS_FILE_UNDO_INFO_PERMISSIONS (info);
2116 permissions_real_func (self, self->new_permissions);
2117 }
2118
2119 static void
permissions_undo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)2120 permissions_undo_func (NautilusFileUndoInfo *info,
2121 GtkWindow *parent_window,
2122 NautilusFileOperationsDBusData *dbus_data)
2123 {
2124 NautilusFileUndoInfoPermissions *self = NAUTILUS_FILE_UNDO_INFO_PERMISSIONS (info);
2125 permissions_real_func (self, self->current_permissions);
2126 }
2127
2128 static void
nautilus_file_undo_info_permissions_init(NautilusFileUndoInfoPermissions * self)2129 nautilus_file_undo_info_permissions_init (NautilusFileUndoInfoPermissions *self)
2130 {
2131 }
2132
2133 static void
nautilus_file_undo_info_permissions_finalize(GObject * obj)2134 nautilus_file_undo_info_permissions_finalize (GObject *obj)
2135 {
2136 NautilusFileUndoInfoPermissions *self = NAUTILUS_FILE_UNDO_INFO_PERMISSIONS (obj);
2137 g_clear_object (&self->target_file);
2138
2139 G_OBJECT_CLASS (nautilus_file_undo_info_permissions_parent_class)->finalize (obj);
2140 }
2141
2142 static void
nautilus_file_undo_info_permissions_class_init(NautilusFileUndoInfoPermissionsClass * klass)2143 nautilus_file_undo_info_permissions_class_init (NautilusFileUndoInfoPermissionsClass *klass)
2144 {
2145 GObjectClass *oclass = G_OBJECT_CLASS (klass);
2146 NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
2147
2148 oclass->finalize = nautilus_file_undo_info_permissions_finalize;
2149
2150 iclass->undo_func = permissions_undo_func;
2151 iclass->redo_func = permissions_redo_func;
2152 iclass->strings_func = permissions_strings_func;
2153 }
2154
2155 NautilusFileUndoInfo *
nautilus_file_undo_info_permissions_new(GFile * file,guint32 current_permissions,guint32 new_permissions)2156 nautilus_file_undo_info_permissions_new (GFile *file,
2157 guint32 current_permissions,
2158 guint32 new_permissions)
2159 {
2160 NautilusFileUndoInfoPermissions *self;
2161
2162 self = g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_PERMISSIONS,
2163 "op-type", NAUTILUS_FILE_UNDO_OP_SET_PERMISSIONS,
2164 "item-count", 1,
2165 NULL);
2166
2167 self->target_file = g_object_ref (file);
2168 self->current_permissions = current_permissions;
2169 self->new_permissions = new_permissions;
2170
2171 return NAUTILUS_FILE_UNDO_INFO (self);
2172 }
2173
2174 /* group and owner change */
2175 struct _NautilusFileUndoInfoOwnership
2176 {
2177 NautilusFileUndoInfo parent_instance;
2178
2179 GFile *target_file;
2180 char *original_ownership;
2181 char *new_ownership;
2182 };
2183
G_DEFINE_TYPE(NautilusFileUndoInfoOwnership,nautilus_file_undo_info_ownership,NAUTILUS_TYPE_FILE_UNDO_INFO)2184 G_DEFINE_TYPE (NautilusFileUndoInfoOwnership, nautilus_file_undo_info_ownership, NAUTILUS_TYPE_FILE_UNDO_INFO)
2185
2186 static void
2187 ownership_strings_func (NautilusFileUndoInfo *info,
2188 gchar **undo_label,
2189 gchar **undo_description,
2190 gchar **redo_label,
2191 gchar **redo_description)
2192 {
2193 NautilusFileUndoInfoOwnership *self = NAUTILUS_FILE_UNDO_INFO_OWNERSHIP (info);
2194 NautilusFileUndoOp op_type = nautilus_file_undo_info_get_op_type (info);
2195 gchar *name;
2196
2197 name = g_file_get_parse_name (self->target_file);
2198
2199 if (op_type == NAUTILUS_FILE_UNDO_OP_CHANGE_OWNER)
2200 {
2201 *undo_description = g_strdup_printf (_("Restore group of “%s” to “%s”"),
2202 name, self->original_ownership);
2203 *redo_description = g_strdup_printf (_("Set group of “%s” to “%s”"),
2204 name, self->new_ownership);
2205
2206 *undo_label = g_strdup (_("_Undo Change Group"));
2207 *redo_label = g_strdup (_("_Redo Change Group"));
2208 }
2209 else if (op_type == NAUTILUS_FILE_UNDO_OP_CHANGE_GROUP)
2210 {
2211 *undo_description = g_strdup_printf (_("Restore owner of “%s” to “%s”"),
2212 name, self->original_ownership);
2213 *redo_description = g_strdup_printf (_("Set owner of “%s” to “%s”"),
2214 name, self->new_ownership);
2215
2216 *undo_label = g_strdup (_("_Undo Change Owner"));
2217 *redo_label = g_strdup (_("_Redo Change Owner"));
2218 }
2219
2220 g_free (name);
2221 }
2222
2223 static void
ownership_real_func(NautilusFileUndoInfoOwnership * self,const gchar * ownership)2224 ownership_real_func (NautilusFileUndoInfoOwnership *self,
2225 const gchar *ownership)
2226 {
2227 NautilusFileUndoOp op_type = nautilus_file_undo_info_get_op_type (NAUTILUS_FILE_UNDO_INFO (self));
2228 NautilusFile *file;
2229
2230 file = nautilus_file_get (self->target_file);
2231
2232 if (op_type == NAUTILUS_FILE_UNDO_OP_CHANGE_OWNER)
2233 {
2234 nautilus_file_set_owner (file,
2235 ownership,
2236 file_undo_info_operation_callback, self);
2237 }
2238 else if (op_type == NAUTILUS_FILE_UNDO_OP_CHANGE_GROUP)
2239 {
2240 nautilus_file_set_group (file,
2241 ownership,
2242 file_undo_info_operation_callback, self);
2243 }
2244
2245 nautilus_file_unref (file);
2246 }
2247
2248 static void
ownership_redo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)2249 ownership_redo_func (NautilusFileUndoInfo *info,
2250 GtkWindow *parent_window,
2251 NautilusFileOperationsDBusData *dbus_data)
2252 {
2253 NautilusFileUndoInfoOwnership *self = NAUTILUS_FILE_UNDO_INFO_OWNERSHIP (info);
2254 ownership_real_func (self, self->new_ownership);
2255 }
2256
2257 static void
ownership_undo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)2258 ownership_undo_func (NautilusFileUndoInfo *info,
2259 GtkWindow *parent_window,
2260 NautilusFileOperationsDBusData *dbus_data)
2261 {
2262 NautilusFileUndoInfoOwnership *self = NAUTILUS_FILE_UNDO_INFO_OWNERSHIP (info);
2263 ownership_real_func (self, self->original_ownership);
2264 }
2265
2266 static void
nautilus_file_undo_info_ownership_init(NautilusFileUndoInfoOwnership * self)2267 nautilus_file_undo_info_ownership_init (NautilusFileUndoInfoOwnership *self)
2268 {
2269 }
2270
2271 static void
nautilus_file_undo_info_ownership_finalize(GObject * obj)2272 nautilus_file_undo_info_ownership_finalize (GObject *obj)
2273 {
2274 NautilusFileUndoInfoOwnership *self = NAUTILUS_FILE_UNDO_INFO_OWNERSHIP (obj);
2275
2276 g_clear_object (&self->target_file);
2277 g_free (self->original_ownership);
2278 g_free (self->new_ownership);
2279
2280 G_OBJECT_CLASS (nautilus_file_undo_info_ownership_parent_class)->finalize (obj);
2281 }
2282
2283 static void
nautilus_file_undo_info_ownership_class_init(NautilusFileUndoInfoOwnershipClass * klass)2284 nautilus_file_undo_info_ownership_class_init (NautilusFileUndoInfoOwnershipClass *klass)
2285 {
2286 GObjectClass *oclass = G_OBJECT_CLASS (klass);
2287 NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
2288
2289 oclass->finalize = nautilus_file_undo_info_ownership_finalize;
2290
2291 iclass->undo_func = ownership_undo_func;
2292 iclass->redo_func = ownership_redo_func;
2293 iclass->strings_func = ownership_strings_func;
2294 }
2295
2296 NautilusFileUndoInfo *
nautilus_file_undo_info_ownership_new(NautilusFileUndoOp op_type,GFile * file,const char * current_data,const char * new_data)2297 nautilus_file_undo_info_ownership_new (NautilusFileUndoOp op_type,
2298 GFile *file,
2299 const char *current_data,
2300 const char *new_data)
2301 {
2302 NautilusFileUndoInfoOwnership *self;
2303
2304 self = g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_OWNERSHIP,
2305 "item-count", 1,
2306 "op-type", op_type,
2307 NULL);
2308
2309 self->target_file = g_object_ref (file);
2310 self->original_ownership = g_strdup (current_data);
2311 self->new_ownership = g_strdup (new_data);
2312
2313 return NAUTILUS_FILE_UNDO_INFO (self);
2314 }
2315
2316 /* extract */
2317 struct _NautilusFileUndoInfoExtract
2318 {
2319 NautilusFileUndoInfo parent_instance;
2320
2321 GList *sources;
2322 GFile *destination_directory;
2323 GList *outputs;
2324 };
2325
G_DEFINE_TYPE(NautilusFileUndoInfoExtract,nautilus_file_undo_info_extract,NAUTILUS_TYPE_FILE_UNDO_INFO)2326 G_DEFINE_TYPE (NautilusFileUndoInfoExtract, nautilus_file_undo_info_extract, NAUTILUS_TYPE_FILE_UNDO_INFO)
2327
2328 static void
2329 extract_callback (GList *outputs,
2330 gpointer callback_data)
2331 {
2332 NautilusFileUndoInfoExtract *self = NAUTILUS_FILE_UNDO_INFO_EXTRACT (callback_data);
2333 gboolean success;
2334
2335 nautilus_file_undo_info_extract_set_outputs (self, outputs);
2336
2337 success = self->outputs != NULL;
2338
2339 file_undo_info_transfer_callback (NULL, success, self);
2340 }
2341
2342 static void
extract_strings_func(NautilusFileUndoInfo * info,gchar ** undo_label,gchar ** undo_description,gchar ** redo_label,gchar ** redo_description)2343 extract_strings_func (NautilusFileUndoInfo *info,
2344 gchar **undo_label,
2345 gchar **undo_description,
2346 gchar **redo_label,
2347 gchar **redo_description)
2348 {
2349 NautilusFileUndoInfoExtract *self = NAUTILUS_FILE_UNDO_INFO_EXTRACT (info);
2350 gint total_sources;
2351 gint total_outputs;
2352
2353 *undo_label = g_strdup (_("_Undo Extract"));
2354 *redo_label = g_strdup (_("_Redo Extract"));
2355
2356 total_sources = g_list_length (self->sources);
2357 total_outputs = g_list_length (self->outputs);
2358
2359 if (total_outputs == 1)
2360 {
2361 GFile *output;
2362 g_autofree gchar *name = NULL;
2363
2364 output = self->outputs->data;
2365 name = g_file_get_parse_name (output);
2366
2367 *undo_description = g_strdup_printf (_("Delete “%s”"), name);
2368 }
2369 else
2370 {
2371 *undo_description = g_strdup_printf (ngettext ("Delete %d extracted file",
2372 "Delete %d extracted files",
2373 total_outputs),
2374 total_outputs);
2375 }
2376
2377 if (total_sources == 1)
2378 {
2379 GFile *source;
2380 g_autofree gchar *name = NULL;
2381
2382 source = self->sources->data;
2383 name = g_file_get_parse_name (source);
2384
2385 *redo_description = g_strdup_printf (_("Extract “%s”"), name);
2386 }
2387 else
2388 {
2389 *redo_description = g_strdup_printf (ngettext ("Extract %d file",
2390 "Extract %d files",
2391 total_sources),
2392 total_sources);
2393 }
2394 }
2395
2396 static void
extract_redo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)2397 extract_redo_func (NautilusFileUndoInfo *info,
2398 GtkWindow *parent_window,
2399 NautilusFileOperationsDBusData *dbus_data)
2400 {
2401 NautilusFileUndoInfoExtract *self = NAUTILUS_FILE_UNDO_INFO_EXTRACT (info);
2402
2403 nautilus_file_operations_extract_files (self->sources,
2404 self->destination_directory,
2405 parent_window,
2406 dbus_data,
2407 extract_callback,
2408 self);
2409 }
2410
2411 static void
extract_undo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)2412 extract_undo_func (NautilusFileUndoInfo *info,
2413 GtkWindow *parent_window,
2414 NautilusFileOperationsDBusData *dbus_data)
2415 {
2416 NautilusFileUndoInfoExtract *self = NAUTILUS_FILE_UNDO_INFO_EXTRACT (info);
2417
2418 nautilus_file_operations_delete_async (self->outputs, parent_window,
2419 dbus_data,
2420 file_undo_info_delete_callback, self);
2421 }
2422
2423 static void
nautilus_file_undo_info_extract_init(NautilusFileUndoInfoExtract * self)2424 nautilus_file_undo_info_extract_init (NautilusFileUndoInfoExtract *self)
2425 {
2426 }
2427
2428 static void
nautilus_file_undo_info_extract_finalize(GObject * obj)2429 nautilus_file_undo_info_extract_finalize (GObject *obj)
2430 {
2431 NautilusFileUndoInfoExtract *self = NAUTILUS_FILE_UNDO_INFO_EXTRACT (obj);
2432
2433 g_object_unref (self->destination_directory);
2434 g_list_free_full (self->sources, g_object_unref);
2435 if (self->outputs)
2436 {
2437 g_list_free_full (self->outputs, g_object_unref);
2438 }
2439
2440 G_OBJECT_CLASS (nautilus_file_undo_info_extract_parent_class)->finalize (obj);
2441 }
2442
2443 static void
nautilus_file_undo_info_extract_class_init(NautilusFileUndoInfoExtractClass * klass)2444 nautilus_file_undo_info_extract_class_init (NautilusFileUndoInfoExtractClass *klass)
2445 {
2446 GObjectClass *oclass = G_OBJECT_CLASS (klass);
2447 NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
2448
2449 oclass->finalize = nautilus_file_undo_info_extract_finalize;
2450
2451 iclass->undo_func = extract_undo_func;
2452 iclass->redo_func = extract_redo_func;
2453 iclass->strings_func = extract_strings_func;
2454 }
2455
2456 void
nautilus_file_undo_info_extract_set_outputs(NautilusFileUndoInfoExtract * self,GList * outputs)2457 nautilus_file_undo_info_extract_set_outputs (NautilusFileUndoInfoExtract *self,
2458 GList *outputs)
2459 {
2460 if (self->outputs)
2461 {
2462 g_list_free_full (self->outputs, g_object_unref);
2463 }
2464 self->outputs = g_list_copy_deep (outputs,
2465 (GCopyFunc) g_object_ref,
2466 NULL);
2467 }
2468
2469 NautilusFileUndoInfo *
nautilus_file_undo_info_extract_new(GList * sources,GFile * destination_directory)2470 nautilus_file_undo_info_extract_new (GList *sources,
2471 GFile *destination_directory)
2472 {
2473 NautilusFileUndoInfoExtract *self;
2474
2475 self = g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_EXTRACT,
2476 "item-count", 1,
2477 "op-type", NAUTILUS_FILE_UNDO_OP_EXTRACT,
2478 NULL);
2479
2480 self->sources = g_list_copy_deep (sources,
2481 (GCopyFunc) g_object_ref,
2482 NULL);
2483 self->destination_directory = g_object_ref (destination_directory);
2484
2485 return NAUTILUS_FILE_UNDO_INFO (self);
2486 }
2487
2488
2489 /* compress */
2490 struct _NautilusFileUndoInfoCompress
2491 {
2492 NautilusFileUndoInfo parent_instance;
2493
2494 GList *sources;
2495 GFile *output;
2496 AutoarFormat format;
2497 AutoarFilter filter;
2498 gchar *passphrase;
2499 };
2500
G_DEFINE_TYPE(NautilusFileUndoInfoCompress,nautilus_file_undo_info_compress,NAUTILUS_TYPE_FILE_UNDO_INFO)2501 G_DEFINE_TYPE (NautilusFileUndoInfoCompress, nautilus_file_undo_info_compress, NAUTILUS_TYPE_FILE_UNDO_INFO)
2502
2503 static void
2504 compress_callback (GFile *new_file,
2505 gboolean success,
2506 gpointer callback_data)
2507 {
2508 NautilusFileUndoInfoCompress *self = NAUTILUS_FILE_UNDO_INFO_COMPRESS (callback_data);
2509
2510 if (success)
2511 {
2512 g_set_object (&self->output, new_file);
2513 }
2514
2515 file_undo_info_transfer_callback (NULL, success, self);
2516 }
2517
2518 static void
compress_strings_func(NautilusFileUndoInfo * info,gchar ** undo_label,gchar ** undo_description,gchar ** redo_label,gchar ** redo_description)2519 compress_strings_func (NautilusFileUndoInfo *info,
2520 gchar **undo_label,
2521 gchar **undo_description,
2522 gchar **redo_label,
2523 gchar **redo_description)
2524 {
2525 NautilusFileUndoInfoCompress *self = NAUTILUS_FILE_UNDO_INFO_COMPRESS (info);
2526 g_autofree gchar *output_name = NULL;
2527 gint sources_count;
2528
2529 output_name = g_file_get_parse_name (self->output);
2530 *undo_description = g_strdup_printf (_("Delete “%s”"), output_name);
2531
2532 sources_count = g_list_length (self->sources);
2533 if (sources_count == 1)
2534 {
2535 GFile *source;
2536 g_autofree gchar *source_name = NULL;
2537
2538 source = self->sources->data;
2539 source_name = g_file_get_parse_name (source);
2540
2541 *redo_description = g_strdup_printf (_("Compress “%s”"), source_name);
2542 }
2543 else
2544 {
2545 *redo_description = g_strdup_printf (ngettext ("Compress %d file",
2546 "Compress %d files",
2547 sources_count),
2548 sources_count);
2549 }
2550
2551 *undo_label = g_strdup (_("_Undo Compress"));
2552 *redo_label = g_strdup (_("_Redo Compress"));
2553 }
2554
2555 static void
compress_redo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)2556 compress_redo_func (NautilusFileUndoInfo *info,
2557 GtkWindow *parent_window,
2558 NautilusFileOperationsDBusData *dbus_data)
2559 {
2560 NautilusFileUndoInfoCompress *self = NAUTILUS_FILE_UNDO_INFO_COMPRESS (info);
2561
2562 nautilus_file_operations_compress (self->sources,
2563 self->output,
2564 self->format,
2565 self->filter,
2566 self->passphrase,
2567 parent_window,
2568 dbus_data,
2569 compress_callback,
2570 self);
2571 }
2572
2573 static void
compress_undo_func(NautilusFileUndoInfo * info,GtkWindow * parent_window,NautilusFileOperationsDBusData * dbus_data)2574 compress_undo_func (NautilusFileUndoInfo *info,
2575 GtkWindow *parent_window,
2576 NautilusFileOperationsDBusData *dbus_data)
2577 {
2578 NautilusFileUndoInfoCompress *self = NAUTILUS_FILE_UNDO_INFO_COMPRESS (info);
2579 GList *files = NULL;
2580
2581 files = g_list_prepend (files, self->output);
2582
2583 nautilus_file_operations_delete_async (files, parent_window,
2584 dbus_data,
2585 file_undo_info_delete_callback, self);
2586
2587 g_list_free (files);
2588 }
2589
2590 static void
nautilus_file_undo_info_compress_init(NautilusFileUndoInfoCompress * self)2591 nautilus_file_undo_info_compress_init (NautilusFileUndoInfoCompress *self)
2592 {
2593 }
2594
2595 static void
nautilus_file_undo_info_compress_finalize(GObject * obj)2596 nautilus_file_undo_info_compress_finalize (GObject *obj)
2597 {
2598 NautilusFileUndoInfoCompress *self = NAUTILUS_FILE_UNDO_INFO_COMPRESS (obj);
2599
2600 g_list_free_full (self->sources, g_object_unref);
2601 g_clear_object (&self->output);
2602 g_free (self->passphrase);
2603
2604 G_OBJECT_CLASS (nautilus_file_undo_info_compress_parent_class)->finalize (obj);
2605 }
2606
2607 static void
nautilus_file_undo_info_compress_class_init(NautilusFileUndoInfoCompressClass * klass)2608 nautilus_file_undo_info_compress_class_init (NautilusFileUndoInfoCompressClass *klass)
2609 {
2610 GObjectClass *oclass = G_OBJECT_CLASS (klass);
2611 NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
2612
2613 oclass->finalize = nautilus_file_undo_info_compress_finalize;
2614
2615 iclass->undo_func = compress_undo_func;
2616 iclass->redo_func = compress_redo_func;
2617 iclass->strings_func = compress_strings_func;
2618 }
2619
2620 NautilusFileUndoInfo *
nautilus_file_undo_info_compress_new(GList * sources,GFile * output,AutoarFormat format,AutoarFilter filter,const gchar * passphrase)2621 nautilus_file_undo_info_compress_new (GList *sources,
2622 GFile *output,
2623 AutoarFormat format,
2624 AutoarFilter filter,
2625 const gchar *passphrase)
2626 {
2627 NautilusFileUndoInfoCompress *self;
2628
2629 self = g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_COMPRESS,
2630 "item-count", 1,
2631 "op-type", NAUTILUS_FILE_UNDO_OP_COMPRESS,
2632 NULL);
2633
2634 self->sources = g_list_copy_deep (sources, (GCopyFunc) g_object_ref, NULL);
2635 self->output = g_object_ref (output);
2636 self->format = format;
2637 self->filter = filter;
2638 self->passphrase = g_strdup (passphrase);
2639
2640 return NAUTILUS_FILE_UNDO_INFO (self);
2641 }
2642