summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRazvan Chitu <razvan.ch95@gmail.com>2016-08-19 12:18:30 +0300
committerRazvan Chitu <razvan.ch95@gmail.com>2016-08-23 00:36:56 +0300
commit9f0c9a9f1243e650d5f023f110151640e91e875b (patch)
tree4d21e3c870d6495cddc1af956153fe5913b4c7e9
parent211bfdfd538f098a31bd181fe1ee9e6dfcc1ce46 (diff)
downloadnautilus-9f0c9a9f1243e650d5f023f110151640e91e875b.tar.gz
files-view: add context menu actions for extracting files
The context menu actions are similar to the ones offered by file-roller, but make use of the internal extract operation. https://bugzilla.gnome.org/show_bug.cgi?id=768646
-rw-r--r--src/nautilus-file.c36
-rw-r--r--src/nautilus-files-view.c273
-rw-r--r--src/resources/ui/nautilus-files-view-context-menus.ui10
3 files changed, 288 insertions, 31 deletions
diff --git a/src/nautilus-file.c b/src/nautilus-file.c
index b380d390d..60e2f9b38 100644
--- a/src/nautilus-file.c
+++ b/src/nautilus-file.c
@@ -51,6 +51,7 @@
#include <glib/gstdio.h>
#include <gio/gio.h>
#include <glib.h>
+#include <gnome-autoar/gnome-autoar.h>
#include <gdesktop-enums.h>
#include <libnautilus-extension/nautilus-file-info.h>
#include <libnautilus-extension/nautilus-extension-private.h>
@@ -7012,38 +7013,11 @@ real_is_special_link (NautilusFile *file)
gboolean
nautilus_file_is_archive (NautilusFile *file)
{
- char *mime_type;
- int i;
- static const char * archive_mime_types[] = { "application/x-gtar",
- "application/x-zip",
- "application/x-zip-compressed",
- "application/zip",
- "application/x-zip",
- "application/x-tar",
- "application/x-7z-compressed",
- "application/x-rar",
- "application/x-rar-compressed",
- "application/x-jar",
- "application/x-java-archive",
- "application/x-war",
- "application/x-ear",
- "application/x-arj",
- "application/x-gzip",
- "application/x-bzip-compressed-tar",
- "application/x-compressed-tar" };
-
- g_return_val_if_fail (file != NULL, FALSE);
-
- mime_type = nautilus_file_get_mime_type (file);
- for (i = 0; i < G_N_ELEMENTS (archive_mime_types); i++) {
- if (!strcmp (mime_type, archive_mime_types[i])) {
- g_free (mime_type);
- return TRUE;
- }
- }
- g_free (mime_type);
+ g_autofree char *mime_type;
- return FALSE;
+ mime_type = nautilus_file_get_mime_type (file);
+
+ return autoar_check_mime_type_supported (mime_type);
}
diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c
index a47c2cf56..40f575a4f 100644
--- a/src/nautilus-files-view.c
+++ b/src/nautilus-files-view.c
@@ -683,6 +683,16 @@ nautilus_files_view_supports_creating_files (NautilusFilesView *view)
}
static gboolean
+nautilus_files_view_supports_extract_here (NautilusFilesView *view)
+{
+ g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), FALSE);
+
+ return nautilus_files_view_supports_creating_files (view)
+ && !nautilus_directory_is_remote (view->details->model)
+ && !nautilus_view_is_searching (NAUTILUS_VIEW (view));
+}
+
+static gboolean
nautilus_files_view_is_empty (NautilusFilesView *view)
{
g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), FALSE);
@@ -5360,6 +5370,238 @@ action_rename (GSimpleAction *action,
real_action_rename (NAUTILUS_FILES_VIEW (user_data));
}
+typedef struct {
+ NautilusFilesView *view;
+ GHashTable *added_locations;
+} ExtractData;
+
+static void
+extract_done (GList *outputs,
+ gpointer user_data)
+{
+ ExtractData *data;
+ GList *l;
+ gboolean all_files_acknowledged;
+
+ data = user_data;
+
+ if (data->view == NULL) {
+ goto out;
+ }
+
+ g_signal_handlers_disconnect_by_func (data->view,
+ G_CALLBACK (track_newly_added_locations),
+ data->added_locations);
+
+ if (outputs == NULL) {
+ goto out;
+ }
+
+ all_files_acknowledged = TRUE;
+ for (l = outputs; l && all_files_acknowledged; l = l->next) {
+ all_files_acknowledged = g_hash_table_contains (data->added_locations,
+ l->data);
+ }
+
+ if (all_files_acknowledged) {
+ GList *selection = NULL;
+
+ for (l = outputs; l != NULL; l = l->next) {
+ selection = g_list_prepend (selection,
+ nautilus_file_get (l->data));
+ }
+
+ nautilus_files_view_set_selection (NAUTILUS_VIEW (data->view),
+ selection);
+ nautilus_files_view_reveal_selection (data->view);
+
+ nautilus_file_list_free (selection);
+ } else {
+ for (l = outputs; l != NULL; l = l->next) {
+ gboolean acknowledged;
+
+ acknowledged = g_hash_table_contains (data->added_locations,
+ l->data);
+
+ g_hash_table_insert (data->view->details->pending_reveal,
+ nautilus_file_get (l->data),
+ GUINT_TO_POINTER (acknowledged));
+ }
+ }
+out:
+ g_hash_table_destroy (data->added_locations);
+
+ if (data->view != NULL) {
+ g_object_remove_weak_pointer (G_OBJECT (data->view),
+ (gpointer *) &data->view);
+ }
+
+ g_free (data);
+}
+
+static void
+extract_files (NautilusFilesView *view,
+ GList *files,
+ GFile *destination_directory)
+{
+ GList *locations = NULL;
+ GList *l;
+ gboolean extracting_to_current_directory;
+
+ if (files == NULL) {
+ return;
+ }
+
+ for (l = files; l != NULL; l = l->next) {
+ locations = g_list_prepend (locations,
+ nautilus_file_get_location (l->data));
+ }
+
+ locations = g_list_reverse (locations);
+
+ extracting_to_current_directory = g_file_equal (destination_directory,
+ nautilus_view_get_location (NAUTILUS_VIEW (view)));
+
+ if (extracting_to_current_directory) {
+ ExtractData *data;
+
+ data = g_new (ExtractData, 1);
+ data->view = view;
+ data->added_locations = g_hash_table_new_full (g_file_hash,
+ (GEqualFunc)g_file_equal,
+ g_object_unref, NULL);
+
+
+ g_object_add_weak_pointer (G_OBJECT (data->view),
+ (gpointer *) &data->view);
+
+ g_signal_connect_data (view,
+ "add-file",
+ G_CALLBACK (track_newly_added_locations),
+ data->added_locations,
+ NULL,
+ G_CONNECT_AFTER);
+
+ nautilus_file_operations_extract_files (locations,
+ destination_directory,
+ nautilus_files_view_get_containing_window (view),
+ extract_done,
+ data);
+ } else {
+ nautilus_file_operations_extract_files (locations,
+ destination_directory,
+ nautilus_files_view_get_containing_window (view),
+ NULL,
+ NULL);
+ }
+
+ g_list_free_full (locations, g_object_unref);
+}
+
+typedef struct {
+ NautilusFilesView *view;
+ GList *files;
+} ExtractToData;
+
+static void
+on_extract_destination_dialog_response (GtkDialog *dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ ExtractToData *data;
+
+ data = user_data;
+
+ if (response_id == GTK_RESPONSE_OK) {
+ g_autoptr (GFile) destination_directory;
+
+ destination_directory = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+
+ extract_files (data->view, data->files, destination_directory);
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ nautilus_file_list_free (data->files);
+ g_free (data);
+}
+
+static void
+extract_files_to_chosen_location (NautilusFilesView *view,
+ GList *files)
+{
+ ExtractToData *data;
+ GtkWidget *dialog;
+ g_autofree char *uri = NULL;
+
+ if (files == NULL) {
+ return;
+ }
+
+ data = g_new (ExtractToData, 1);
+
+ dialog = gtk_file_chooser_dialog_new (_("Select Extract Destination"),
+ GTK_WINDOW (nautilus_files_view_get_window (view)),
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Select"), GTK_RESPONSE_OK,
+ NULL);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), FALSE);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK);
+
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ uri = nautilus_directory_get_uri (view->details->model);
+ gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), uri);
+
+ data->view = view;
+ data->files = nautilus_file_list_copy (files);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (on_extract_destination_dialog_response),
+ data);
+
+ gtk_widget_show_all (dialog);
+}
+
+static void
+action_extract_here (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ NautilusFilesView *view;
+ GList *selection;
+
+ view = NAUTILUS_FILES_VIEW (user_data);
+
+ selection = nautilus_view_get_selection (NAUTILUS_VIEW (view));
+
+ extract_files (view, selection,
+ nautilus_view_get_location (NAUTILUS_VIEW (view)));
+
+ nautilus_file_list_free (selection);
+}
+
+static void
+action_extract_to (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ NautilusFilesView *view;
+ GList *selection;
+
+ view = NAUTILUS_FILES_VIEW (user_data);
+
+ selection = nautilus_view_get_selection (NAUTILUS_VIEW (view));
+
+ extract_files_to_chosen_location (view, selection);
+
+ nautilus_file_list_free (selection);
+}
+
+
#define BG_KEY_PRIMARY_COLOR "primary-color"
#define BG_KEY_SECONDARY_COLOR "secondary-color"
#define BG_KEY_COLOR_TYPE "color-shading-type"
@@ -5796,6 +6038,8 @@ const GActionEntry view_entries[] = {
{ "restore-from-trash", action_restore_from_trash},
{ "paste-into", action_paste_files_into },
{ "rename", action_rename},
+ { "extract-here", action_extract_here },
+ { "extract-to", action_extract_to },
{ "properties", action_properties},
{ "set-as-wallpaper", action_set_as_wallpaper },
{ "mount-volume", action_mount_volume },
@@ -6033,6 +6277,21 @@ all_in_trash (GList *files)
return TRUE;
}
+static gboolean
+can_extract_all (GList *files)
+{
+ NautilusFile *file;
+ GList *l;
+
+ for (l = files; l != NULL; l = l->next) {
+ file = l->data;
+ if (!nautilus_file_is_archive (file)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
GActionGroup *
nautilus_files_view_get_action_group (NautilusFilesView *view)
{
@@ -6060,6 +6319,8 @@ real_update_actions_state (NautilusFilesView *view)
gboolean can_copy_files;
gboolean can_link_from_copied_files;
gboolean can_paste_files_into;
+ gboolean can_extract_files;
+ gboolean can_extract_here;
gboolean item_opens_in_view;
gboolean is_read_only;
GAction *action;
@@ -6107,6 +6368,9 @@ real_update_actions_state (NautilusFilesView *view)
can_paste_files_into = (!selection_contains_recent &&
selection_count == 1 &&
can_paste_into_file (NAUTILUS_FILE (selection->data)));
+ can_extract_files = selection_count != 0 &&
+ can_extract_all (selection);
+ can_extract_here = nautilus_files_view_supports_extract_here (view);
settings_show_delete_permanently = g_settings_get_boolean (nautilus_preferences,
NAUTILUS_PREFERENCES_SHOW_DELETE_PERMANENTLY);
settings_show_create_link = g_settings_get_boolean (nautilus_preferences,
@@ -6131,6 +6395,15 @@ real_update_actions_state (NautilusFilesView *view)
}
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
+ "extract-here");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
+ can_extract_files && can_extract_here);
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
+ "extract-to");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), can_extract_files);
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
"open-item-location");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
diff --git a/src/resources/ui/nautilus-files-view-context-menus.ui b/src/resources/ui/nautilus-files-view-context-menus.ui
index b40d24270..564201f18 100644
--- a/src/resources/ui/nautilus-files-view-context-menus.ui
+++ b/src/resources/ui/nautilus-files-view-context-menus.ui
@@ -235,6 +235,16 @@
</section>
<section>
<attribute name="id">extensions</attribute>
+ <item>
+ <attribute name="label" translatable="yes">_Extract Here</attribute>
+ <attribute name="action">view.extract-here</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">E_xtract to…</attribute>
+ <attribute name="action">view.extract-to</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ </item>
</section>
<section>
<item>