summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRazvan Chitu <razvan.ch95@gmail.com>2016-08-21 00:52:55 +0300
committerRazvan Chitu <razvan.ch95@gmail.com>2016-08-22 12:29:03 +0300
commit116b53c5f2a440487d4a5d35a72da4469aaac567 (patch)
treeecd8270036672154de0058f8831384223e8c5d2c
parent783aeae6874832dc3988382045e9ddd7a66c0ead (diff)
downloadnautilus-116b53c5f2a440487d4a5d35a72da4469aaac567.tar.gz
file-operations: implement extract operation
Add a new operation for extracting archives using gnome-autoar. https://bugzilla.gnome.org/show_bug.cgi?id=768646
-rw-r--r--configure.ac2
-rw-r--r--src/nautilus-file-operations.c378
-rw-r--r--src/nautilus-file-operations.h7
-rw-r--r--src/nautilus-file-undo-operations.c157
-rw-r--r--src/nautilus-file-undo-operations.h29
5 files changed, 573 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index b875402be..01b438264 100644
--- a/configure.ac
+++ b/configure.ac
@@ -11,6 +11,7 @@ m4_define(exif_minver, 0.6.20)
m4_define(exempi_minver, 2.1.0)
m4_define(notify_minver, 0.7.0)
m4_define(schemas_minver, 3.8.0)
+m4_define(autoar_minver, 0.1)
dnl 1. If the library code has changed at all since last release, then increment revision.
dnl 2. If any interfaces have been added, then increment current and set revision to 0.
@@ -268,6 +269,7 @@ dnl base libs
PKG_CHECK_MODULES(BASE, [
gtk+-3.0 >= gtk_minver
glib-2.0 >= glib_minver
+ gnome-autoar >= autoar_minver
])
dnl common libs (eel, nautilus)
diff --git a/src/nautilus-file-operations.c b/src/nautilus-file-operations.c
index a5e8e667a..7b2f72e5c 100644
--- a/src/nautilus-file-operations.c
+++ b/src/nautilus-file-operations.c
@@ -51,6 +51,8 @@
#include <gtk/gtk.h>
#include <gio/gio.h>
#include <glib.h>
+#include <gnome-autoar/gnome-autoar.h>
+
#include "nautilus-operations-ui-manager.h"
#include "nautilus-file-changes-queue.h"
#include "nautilus-file-private.h"
@@ -169,8 +171,24 @@ typedef struct {
int last_reported_files_left;
} TransferInfo;
+typedef struct {
+ CommonJob common;
+ GList *source_files;
+ GFile *destination_directory;
+ GList *output_files;
+
+ gdouble base_progress;
+
+ guint64 archive_compressed_size;
+ guint64 total_compressed_size;
+
+ NautilusExtractCallback done_callback;
+ gpointer done_callback_data;
+} ExtractJob;
+
#define SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE 8
#define NSEC_PER_MICROSEC 1000
+#define PROGRESS_NOTIFY_INTERVAL 100 * NSEC_PER_MICROSEC
#define MAXIMUM_DISPLAYED_FILE_NAME_LENGTH 50
@@ -7025,6 +7043,366 @@ nautilus_file_mark_desktop_file_trusted (GFile *file,
g_object_unref (task);
}
+static void
+extract_task_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ ExtractJob *extract_job;
+
+ extract_job = user_data;
+
+ if (extract_job->done_callback) {
+ extract_job->done_callback (extract_job->output_files,
+ extract_job->done_callback_data);
+ }
+
+ g_list_free_full (extract_job->source_files, g_object_unref);
+ g_list_free_full (extract_job->output_files, g_object_unref);
+ g_object_unref (extract_job->destination_directory);
+
+ finalize_common ((CommonJob *)extract_job);
+
+ nautilus_file_changes_consume_changes (TRUE);
+}
+
+static GFile*
+extract_job_on_decide_destination (AutoarExtractor *extractor,
+ GFile *destination,
+ GList *files,
+ gpointer user_data)
+{
+ ExtractJob *extract_job = user_data;
+ GFile *decided_destination;
+ g_autofree char *basename;
+
+ nautilus_progress_info_set_details (extract_job->common.progress,
+ _("Verifying destination"));
+
+ basename = g_file_get_basename (destination);
+ decided_destination = nautilus_generate_unique_file_in_directory (extract_job->destination_directory,
+ basename);
+
+ if (job_aborted ((CommonJob *)extract_job)) {
+ g_object_unref (decided_destination);
+ return NULL;
+ }
+
+ extract_job->output_files = g_list_prepend (extract_job->output_files,
+ decided_destination);
+
+ return g_object_ref (decided_destination);
+}
+
+static void
+extract_job_on_progress (AutoarExtractor *extractor,
+ guint64 archive_current_decompressed_size,
+ guint archive_current_decompressed_files,
+ gpointer user_data)
+{
+ ExtractJob *extract_job = user_data;
+ CommonJob *common = user_data;
+ GFile *source_file;
+ char *details;
+ double elapsed;
+ double transfer_rate;
+ int remaining_time;
+ guint64 archive_total_decompressed_size;
+ gdouble archive_weight;
+ gdouble archive_decompress_progress;
+ guint64 job_completed_size;
+ gdouble job_progress;
+
+ source_file = autoar_extractor_get_source_file (extractor);
+
+ nautilus_progress_info_take_status (common->progress,
+ f (_("Extracting “%B”"), source_file));
+
+ archive_total_decompressed_size = autoar_extractor_get_total_size (extractor);
+
+ archive_decompress_progress = (gdouble)archive_current_decompressed_size /
+ (gdouble)archive_total_decompressed_size;
+
+ archive_weight = 0;
+ if (extract_job->total_compressed_size) {
+ archive_weight = (gdouble)extract_job->archive_compressed_size /
+ (gdouble)extract_job->total_compressed_size;
+ }
+
+ job_progress = archive_decompress_progress * archive_weight + extract_job->base_progress;
+
+ elapsed = g_timer_elapsed (common->time, NULL);
+
+ transfer_rate = 0;
+ remaining_time = -1;
+
+ job_completed_size = job_progress * extract_job->total_compressed_size;
+
+ if (elapsed > 0) {
+ transfer_rate = job_completed_size / elapsed;
+ }
+ if (transfer_rate > 0) {
+ remaining_time = (extract_job->total_compressed_size - job_completed_size) /
+ transfer_rate;
+ }
+
+ if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE ||
+ transfer_rate == 0) {
+ /* To translators: %S will expand to a size like "2 bytes" or
+ * "3 MB", so something like "4 kb / 4 MB"
+ */
+ details = f (_("%S / %S"), job_completed_size, extract_job->total_compressed_size);
+ } else {
+ /* To translators: %S will expand to a size like "2 bytes" or
+ * "3 MB", %T to a time duration like "2 minutes". So the whole
+ * thing will be something like
+ * "2 kb / 4 MB -- 2 hours left (4kb/sec)"
+ *
+ * The singular/plural form will be used depending on the
+ * remaining time (i.e. the %T argument).
+ */
+ details = f (ngettext ("%S / %S \xE2\x80\x94 %T left (%S/sec)",
+ "%S / %S \xE2\x80\x94 %T left (%S/sec)",
+ seconds_count_format_time_units (remaining_time)),
+ job_completed_size, extract_job->total_compressed_size,
+ remaining_time,
+ (goffset)transfer_rate);
+ }
+
+ nautilus_progress_info_take_details (common->progress, details);
+
+ if (elapsed > SECONDS_NEEDED_FOR_APROXIMATE_TRANSFER_RATE) {
+ nautilus_progress_info_set_remaining_time (common->progress,
+ remaining_time);
+ nautilus_progress_info_set_elapsed_time (common->progress,
+ elapsed);
+ }
+
+ nautilus_progress_info_set_progress (common->progress, job_progress, 1);
+}
+
+static void
+extract_job_on_error (AutoarExtractor *extractor,
+ GError *error,
+ gpointer user_data)
+{
+ ExtractJob *extract_job = user_data;
+ GFile *source_file;
+ gint response_id;
+
+ source_file = autoar_extractor_get_source_file (extractor);
+
+ nautilus_progress_info_take_status (extract_job->common.progress,
+ f (_("Error extracting “%B””"),
+ source_file));
+
+ response_id = run_warning ((CommonJob *)extract_job,
+ f (_("There was an error while extracting “%B”."),
+ source_file),
+ g_strdup (error->message),
+ NULL,
+ FALSE,
+ CANCEL,
+ SKIP,
+ NULL);
+
+ if (response_id == 0 || response_id == GTK_RESPONSE_DELETE_EVENT) {
+ abort_job ((CommonJob *)extract_job);
+ }
+}
+
+static void
+extract_job_on_completed (AutoarExtractor *extractor,
+ gpointer user_data)
+{
+ ExtractJob *extract_job = user_data;
+ GFile *output_file;
+
+ output_file = G_FILE (extract_job->output_files->data);
+
+ nautilus_file_changes_queue_file_added (output_file);
+}
+
+static void
+report_extract_final_progress (ExtractJob *extract_job,
+ gint total_files)
+{
+ char *status;
+
+ nautilus_progress_info_set_destination (extract_job->common.progress,
+ extract_job->destination_directory);
+
+ if (total_files == 1) {
+ GFile *source_file;
+
+ source_file = G_FILE (extract_job->source_files->data);
+ status = f (_("Extracted “%B” to “%B”"),
+ source_file,
+ extract_job->destination_directory);
+ } else {
+ status = f (ngettext ("Extracted %'d file to “%B”",
+ "Extracted %'d files to “%B”",
+ total_files),
+ total_files,
+ extract_job->destination_directory);
+
+ }
+
+ nautilus_progress_info_take_status (extract_job->common.progress,
+ status);
+ nautilus_progress_info_take_details (extract_job->common.progress,
+ f (_("%S / %S"),
+ extract_job->total_compressed_size,
+ extract_job->total_compressed_size));
+}
+
+static void
+extract_task_thread_func (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ ExtractJob *extract_job = task_data;
+ GList *l;
+ GList *existing_output_files = NULL;
+ gint total_files;
+ g_autofree guint64 *archive_compressed_sizes;
+ gint i;
+
+ g_timer_start (extract_job->common.time);
+
+ nautilus_progress_info_start (extract_job->common.progress);
+
+ nautilus_progress_info_set_details (extract_job->common.progress,
+ _("Preparing to extract"));
+
+ total_files = g_list_length (extract_job->source_files);
+
+ archive_compressed_sizes = g_malloc0_n (total_files, sizeof (guint64));
+ extract_job->total_compressed_size = 0;
+
+ for (l = extract_job->source_files, i = 0;
+ l != NULL && !job_aborted ((CommonJob *)extract_job);
+ l = l->next, i++) {
+ GFile *source_file;
+ g_autoptr (GFileInfo) info;
+
+ source_file = G_FILE (l->data);
+ info = g_file_query_info (source_file,
+ G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ G_FILE_COPY_NOFOLLOW_SYMLINKS,
+ extract_job->common.cancellable,
+ NULL);
+
+ if (info) {
+ archive_compressed_sizes[i] = g_file_info_get_size (info);
+ extract_job->total_compressed_size += archive_compressed_sizes[i];
+ }
+ }
+
+ extract_job->base_progress = 0;
+
+ for (l = extract_job->source_files, i = 0;
+ l != NULL && !job_aborted ((CommonJob *)extract_job);
+ l = l->next, i++) {
+ g_autoptr (AutoarExtractor) extractor;
+
+ extractor = autoar_extractor_new (G_FILE (l->data),
+ extract_job->destination_directory);
+
+ autoar_extractor_set_notify_interval (extractor,
+ PROGRESS_NOTIFY_INTERVAL);
+
+ g_signal_connect (extractor, "error",
+ G_CALLBACK (extract_job_on_error),
+ extract_job);
+ g_signal_connect (extractor, "decide-destination",
+ G_CALLBACK (extract_job_on_decide_destination),
+ extract_job);
+ g_signal_connect (extractor, "progress",
+ G_CALLBACK (extract_job_on_progress),
+ extract_job);
+ g_signal_connect (extractor, "completed",
+ G_CALLBACK (extract_job_on_completed),
+ extract_job);
+
+ extract_job->archive_compressed_size = archive_compressed_sizes[i];
+
+ autoar_extractor_start (extractor,
+ extract_job->common.cancellable);
+
+ g_signal_handlers_disconnect_by_data (extractor,
+ extract_job);
+
+ extract_job->base_progress += (gdouble)extract_job->archive_compressed_size /
+ (gdouble)extract_job->total_compressed_size;
+ }
+
+ if (!job_aborted ((CommonJob *)extract_job)) {
+ report_extract_final_progress (extract_job, total_files);
+ }
+
+ for (l = extract_job->output_files; l != NULL; l = l->next) {
+ GFile *output_file;
+
+ output_file = G_FILE (l->data);
+
+ if (g_file_query_exists (output_file, NULL)) {
+ existing_output_files = g_list_prepend (existing_output_files,
+ g_object_ref (output_file));
+ }
+ }
+
+ g_list_free_full (extract_job->output_files, g_object_unref);
+
+ extract_job->output_files = existing_output_files;
+
+ if (extract_job->common.undo_info) {
+ if (extract_job->output_files) {
+ NautilusFileUndoInfoExtract *undo_info;
+
+ undo_info = NAUTILUS_FILE_UNDO_INFO_EXTRACT (extract_job->common.undo_info);
+
+ nautilus_file_undo_info_extract_set_outputs (undo_info,
+ extract_job->output_files);
+ } else {
+ /* There is nothing to undo if there is no output */
+ g_clear_object (&extract_job->common.undo_info);
+ }
+ }
+}
+
+void
+nautilus_file_operations_extract_files (GList *files,
+ GFile *destination_directory,
+ GtkWindow *parent_window,
+ NautilusExtractCallback done_callback,
+ gpointer done_callback_data)
+{
+ ExtractJob *extract_job;
+ g_autoptr (GTask) task;
+
+ extract_job = op_job_new (ExtractJob, parent_window);
+ extract_job->source_files = g_list_copy_deep (files,
+ (GCopyFunc)g_object_ref,
+ NULL);
+ extract_job->destination_directory = g_object_ref (destination_directory);
+ extract_job->done_callback = done_callback;
+ extract_job->done_callback_data = done_callback_data;
+
+ inhibit_power_manager ((CommonJob *)extract_job, _("Extracting Files"));
+
+ if (!nautilus_file_undo_manager_is_operating ()) {
+ extract_job->common.undo_info = nautilus_file_undo_info_extract_new (files,
+ destination_directory);
+ }
+
+ task = g_task_new (NULL, extract_job->common.cancellable,
+ extract_task_done, extract_job);
+ g_task_set_task_data (task, extract_job, NULL);
+ g_task_run_in_thread (task, extract_task_thread_func);
+}
+
#if !defined (NAUTILUS_OMIT_SELF_CHECK)
void
diff --git a/src/nautilus-file-operations.h b/src/nautilus-file-operations.h
index 08b11ca95..fb209d136 100644
--- a/src/nautilus-file-operations.h
+++ b/src/nautilus-file-operations.h
@@ -44,6 +44,8 @@ typedef void (* NautilusMountCallback) (GVolume *volume,
gboolean success,
GObject *callback_data_object);
typedef void (* NautilusUnmountCallback) (gpointer callback_data);
+typedef void (* NautilusExtractCallback) (GList *outputs,
+ gpointer callback_data);
/* FIXME: int copy_action should be an enum */
@@ -147,6 +149,11 @@ void nautilus_file_mark_desktop_file_trusted (GFile *file,
gboolean interactive,
NautilusOpCallback done_callback,
gpointer done_callback_data);
+void nautilus_file_operations_extract_files (GList *files,
+ GFile *destination_directory,
+ GtkWindow *parent_window,
+ NautilusExtractCallback done_callback,
+ gpointer done_callback_data);
#endif /* NAUTILUS_FILE_OPERATIONS_H */
diff --git a/src/nautilus-file-undo-operations.c b/src/nautilus-file-undo-operations.c
index 17b8c1dc6..6025848c9 100644
--- a/src/nautilus-file-undo-operations.c
+++ b/src/nautilus-file-undo-operations.c
@@ -1692,3 +1692,160 @@ nautilus_file_undo_info_ownership_new (NautilusFileUndoOp op_type,
return NAUTILUS_FILE_UNDO_INFO (retval);
}
+
+/* extract */
+G_DEFINE_TYPE (NautilusFileUndoInfoExtract, nautilus_file_undo_info_extract, NAUTILUS_TYPE_FILE_UNDO_INFO)
+
+struct _NautilusFileUndoInfoExtractDetails {
+ GList *sources;
+ GFile *destination_directory;
+ GList *outputs;
+};
+
+static void
+extract_callback (GList *outputs,
+ gpointer callback_data)
+{
+ NautilusFileUndoInfoExtract *self = NAUTILUS_FILE_UNDO_INFO_EXTRACT (callback_data);
+ gboolean success;
+
+ nautilus_file_undo_info_extract_set_outputs (self, outputs);
+
+ success = self->priv->outputs != NULL;
+
+ file_undo_info_transfer_callback (NULL, success, self);
+}
+
+static void
+extract_strings_func (NautilusFileUndoInfo *info,
+ gchar **undo_label,
+ gchar **undo_description,
+ gchar **redo_label,
+ gchar **redo_description)
+{
+ NautilusFileUndoInfoExtract *self = NAUTILUS_FILE_UNDO_INFO_EXTRACT (info);
+ gint total_sources;
+ gint total_outputs;
+
+ *undo_label = g_strdup (_("_Undo Extract"));
+ *redo_label = g_strdup (_("_Redo Extract"));
+
+ total_sources = g_list_length (self->priv->sources);
+ total_outputs = g_list_length (self->priv->outputs);
+
+ if (total_outputs == 1) {
+ GFile *output;
+ g_autofree gchar *name;
+
+ output = self->priv->outputs->data;
+ name = g_file_get_parse_name (output);
+
+ *undo_description = g_strdup_printf (_("Delete '%s'"), name);
+ } else {
+ *undo_description = g_strdup_printf (_("Delete %d extracted files"),
+ total_outputs);
+ }
+
+ if (total_sources == 1) {
+ GFile *source;
+ g_autofree gchar *name;
+
+ source = self->priv->sources->data;
+ name = g_file_get_parse_name (source);
+
+ *undo_description = g_strdup_printf (_("Extract '%s'"), name);
+ } else {
+ *undo_description = g_strdup_printf (_("Extract %d files"),
+ total_sources);
+ }
+}
+
+static void
+extract_redo_func (NautilusFileUndoInfo *info,
+ GtkWindow *parent_window)
+{
+ NautilusFileUndoInfoExtract *self = NAUTILUS_FILE_UNDO_INFO_EXTRACT (info);
+
+ nautilus_file_operations_extract_files (self->priv->sources,
+ self->priv->destination_directory,
+ parent_window,
+ extract_callback,
+ self);
+}
+
+static void
+extract_undo_func (NautilusFileUndoInfo *info,
+ GtkWindow *parent_window)
+{
+ NautilusFileUndoInfoExtract *self = NAUTILUS_FILE_UNDO_INFO_EXTRACT (info);
+
+ nautilus_file_operations_delete (self->priv->outputs, parent_window,
+ file_undo_info_delete_callback, self);
+}
+
+static void
+nautilus_file_undo_info_extract_init (NautilusFileUndoInfoExtract *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, nautilus_file_undo_info_extract_get_type (),
+ NautilusFileUndoInfoExtractDetails);
+}
+
+static void
+nautilus_file_undo_info_extract_finalize (GObject *obj)
+{
+ NautilusFileUndoInfoExtract *self = NAUTILUS_FILE_UNDO_INFO_EXTRACT (obj);
+
+ g_object_unref (self->priv->destination_directory);
+ g_list_free_full (self->priv->sources, g_object_unref);
+ if (self->priv->outputs) {
+ g_list_free_full (self->priv->outputs, g_object_unref);
+ }
+
+ G_OBJECT_CLASS (nautilus_file_undo_info_extract_parent_class)->finalize (obj);
+}
+
+static void
+nautilus_file_undo_info_extract_class_init (NautilusFileUndoInfoExtractClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+ NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
+
+ oclass->finalize = nautilus_file_undo_info_extract_finalize;
+
+ iclass->undo_func = extract_undo_func;
+ iclass->redo_func = extract_redo_func;
+ iclass->strings_func = extract_strings_func;
+
+ g_type_class_add_private (klass, sizeof (NautilusFileUndoInfoExtractDetails));
+}
+
+void
+nautilus_file_undo_info_extract_set_outputs (NautilusFileUndoInfoExtract *self,
+ GList *outputs)
+{
+ if (self->priv->outputs) {
+ g_list_free_full (self->priv->outputs, g_object_unref);
+ }
+ self->priv->outputs = g_list_copy_deep (outputs,
+ (GCopyFunc)g_object_ref,
+ NULL);
+}
+
+NautilusFileUndoInfo *
+nautilus_file_undo_info_extract_new (GList *sources,
+ GFile *destination_directory)
+{
+ NautilusFileUndoInfoExtract *self;
+
+ self = g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_EXTRACT,
+ "item-count", 1,
+ "op-type", NAUTILUS_FILE_UNDO_OP_EXTRACT,
+ NULL);
+
+ self->priv->sources = g_list_copy_deep (sources,
+ (GCopyFunc)g_object_ref,
+ NULL);
+ self->priv->destination_directory = g_object_ref (destination_directory);
+
+ return NAUTILUS_FILE_UNDO_INFO (self);
+}
diff --git a/src/nautilus-file-undo-operations.h b/src/nautilus-file-undo-operations.h
index cec1c7c4e..ef01363b6 100644
--- a/src/nautilus-file-undo-operations.h
+++ b/src/nautilus-file-undo-operations.h
@@ -36,6 +36,7 @@ typedef enum {
NAUTILUS_FILE_UNDO_OP_CREATE_EMPTY_FILE,
NAUTILUS_FILE_UNDO_OP_CREATE_FILE_FROM_TEMPLATE,
NAUTILUS_FILE_UNDO_OP_CREATE_FOLDER,
+ NAUTILUS_FILE_UNDO_OP_EXTRACT,
NAUTILUS_FILE_UNDO_OP_MOVE_TO_TRASH,
NAUTILUS_FILE_UNDO_OP_RESTORE_FROM_TRASH,
NAUTILUS_FILE_UNDO_OP_CREATE_LINK,
@@ -296,4 +297,32 @@ NautilusFileUndoInfo *nautilus_file_undo_info_ownership_new (NautilusFileUndoOp
const char *current_data,
const char *new_data);
+/* extract */
+#define NAUTILUS_TYPE_FILE_UNDO_INFO_EXTRACT (nautilus_file_undo_info_extract_get_type ())
+#define NAUTILUS_FILE_UNDO_INFO_EXTRACT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NAUTILUS_TYPE_FILE_UNDO_INFO_EXTRACT, NautilusFileUndoInfoExtract))
+#define NAUTILUS_FILE_UNDO_INFO_EXTRACT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NAUTILUS_TYPE_FILE_UNDO_INFO_EXTRACT, NautilusFileUndoInfoExtractClass))
+#define NAUTILUS_IS_FILE_UNDO_INFO_EXTRACT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NAUTILUS_TYPE_FILE_UNDO_INFO_EXTRACT))
+#define NAUTILUS_IS_FILE_UNDO_INFO_EXTRACT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NAUTILUS_TYPE_FILE_UNDO_INFO_EXTRACT))
+#define NAUTILUS_FILE_UNDO_INFO_EXTRACT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NAUTILUS_TYPE_FILE_UNDO_INFO_EXTRACT, NautilusFileUndoInfoExtractClass))
+
+typedef struct _NautilusFileUndoInfoExtract NautilusFileUndoInfoExtract;
+typedef struct _NautilusFileUndoInfoExtractClass NautilusFileUndoInfoExtractClass;
+typedef struct _NautilusFileUndoInfoExtractDetails NautilusFileUndoInfoExtractDetails;
+
+struct _NautilusFileUndoInfoExtract {
+ NautilusFileUndoInfo parent;
+ NautilusFileUndoInfoExtractDetails *priv;
+};
+
+struct _NautilusFileUndoInfoExtractClass {
+ NautilusFileUndoInfoClass parent_class;
+};
+
+GType nautilus_file_undo_info_extract_get_type (void) G_GNUC_CONST;
+NautilusFileUndoInfo * nautilus_file_undo_info_extract_new (GList *sources,
+ GFile *destination_directory);
+void nautilus_file_undo_info_extract_set_outputs (NautilusFileUndoInfoExtract *self,
+ GList *outputs);
+
+
#endif /* __NAUTILUS_FILE_UNDO_OPERATIONS_H__ */