From a043e0a81460a94e0732672afc3831689984caf8 Mon Sep 17 00:00:00 2001 From: xmusjackson Date: Sun, 14 May 2023 20:57:35 -0500 Subject: Add "Extract to subdirectory" option This commit adds an "Extract to subdirectory" option to the extract dialog which allows the user to extract the contents of the archive to a directory with the name of the archive (without the extension.) The user will be prompted if the directory must be created. file-utils.c: Improve remove_extension_from_path Rework this function so that it correctly parses and truncates files with multiple extensions like .tar.gz file-utils.c: Improve get_file_extension Improve this function to correctly identify and return supported compressed tar file extensions --- data/org.mate.engrampa.gschema.xml.in | 4 ++++ src/dlg-extract.c | 16 +++++++++++++-- src/file-utils.c | 37 ++++++++++++++++------------------- src/fr-window.c | 22 ++++++++++++++++++++- src/fr-window.h | 1 + src/preferences.h | 1 + src/ui/dlg-extract.ui | 16 +++++++++++++++ 7 files changed, 74 insertions(+), 23 deletions(-) diff --git a/data/org.mate.engrampa.gschema.xml.in b/data/org.mate.engrampa.gschema.xml.in index fed9a1e..5b62190 100644 --- a/data/org.mate.engrampa.gschema.xml.in +++ b/data/org.mate.engrampa.gschema.xml.in @@ -154,6 +154,10 @@ false Close dialog after decompression + + false + Create a folder with the archive name and extract there + diff --git a/src/dlg-extract.c b/src/dlg-extract.c index 263528b..6d63059 100644 --- a/src/dlg-extract.c +++ b/src/dlg-extract.c @@ -69,6 +69,8 @@ extract_cb (GtkWidget *w, FrWindow *window = data->window; gboolean do_not_extract = FALSE; char *extract_to_dir; + char *sub_dir; + gboolean extract_sub_dir; gboolean overwrite; gboolean skip_newer; gboolean selected_files; @@ -179,16 +181,18 @@ extract_cb (GtkWidget *w, return FALSE; } - fr_window_set_extract_default_dir (window, extract_to_dir, TRUE); - overwrite = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("overwrite_checkbutton"))); skip_newer = ! gtk_toggle_button_get_inconsistent (GTK_TOGGLE_BUTTON (GET_WIDGET ("not_newer_checkbutton"))) && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("not_newer_checkbutton"))); junk_paths = ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("recreate_dir_checkbutton"))); + extract_sub_dir = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("create_subdir_checkbutton"))); g_settings_set_boolean (data->settings, PREF_EXTRACT_OVERWRITE, overwrite); if (! gtk_toggle_button_get_inconsistent (GTK_TOGGLE_BUTTON (GET_WIDGET ("not_newer_checkbutton")))) g_settings_set_boolean (data->settings, PREF_EXTRACT_SKIP_NEWER, skip_newer); g_settings_set_boolean (data->settings, PREF_EXTRACT_RECREATE_FOLDERS, ! junk_paths); + g_settings_set_boolean (data->settings, PREF_EXTRACT_CREATE_SUBDIR, extract_sub_dir); + + fr_window_set_extract_default_dir (window, extract_to_dir, !extract_sub_dir); selected_files = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("selected_files_radiobutton"))); pattern_files = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("file_pattern_radiobutton"))); @@ -220,6 +224,11 @@ extract_cb (GtkWidget *w, else base_dir = NULL; + if (extract_sub_dir) + sub_dir = remove_extension_from_path (g_filename_display_basename (fr_window_get_archive_uri (window))); + else + sub_dir = NULL; + /* close the dialog. */ gtk_widget_destroy (data->dialog); @@ -229,6 +238,7 @@ extract_cb (GtkWidget *w, fr_window_archive_extract (window, file_list, extract_to_dir, + sub_dir, base_dir, skip_newer, overwrite ? FR_OVERWRITE_YES : FR_OVERWRITE_NO, @@ -237,6 +247,7 @@ extract_cb (GtkWidget *w, path_list_free (file_list); g_free (extract_to_dir); + g_free (sub_dir); g_free (base_dir); return TRUE; @@ -331,6 +342,7 @@ dlg_extract__common (FrWindow *window, } gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("recreate_dir_checkbutton")), g_settings_get_boolean (data->settings, PREF_EXTRACT_RECREATE_FOLDERS)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("create_subdir_checkbutton")), g_settings_get_boolean (data->settings, PREF_EXTRACT_CREATE_SUBDIR)); button = GET_WIDGET ("close_dialog_checkbutton"); g_settings_bind (data->settings, diff --git a/src/file-utils.c b/src/file-utils.c index a2b782a..4983a7b 100644 --- a/src/file-utils.c +++ b/src/file-utils.c @@ -412,26 +412,16 @@ build_uri (const char *base, ...) gchar * remove_extension_from_path (const gchar *path) { - int len; - int p; - const char *ptr = path; - char *new_path; - - if (! path) - return NULL; + const char *ext; - len = strlen (path); - if (len == 1) - return g_strdup (path); + if (path == NULL) + return NULL; - p = len - 1; - while ((p > 0) && (ptr[p] != '.')) - p--; - if (p == 0) - p = len; - new_path = g_strndup (path, (guint) p); - - return new_path; + ext = get_archive_filename_extension (path); + if (ext == NULL || strlen (ext) == strlen (path)) + return g_strdup (path); + else + return g_strndup (path, strlen (path) - strlen (ext)); } gboolean @@ -517,6 +507,7 @@ get_file_extension (const char *filename) int len; int p; const char *ext; + const char *tar_exts[] = {".7z", ".br", ".bz", ".bz2", ".gz", ".lrz", ".lz", ".lzma", ".lzo", ".xz", ".Z", ".xst", NULL}; if (filename == NULL) return NULL; @@ -532,10 +523,16 @@ get_file_extension (const char *filename) return NULL; ext = filename + p; + p = 0; if (ext - 4 > filename) { const char *test = ext - 4; - if (strncmp (test, ".tar", 4) == 0) - ext = ext - 4; + if (strncmp (test, ".tar", 4) == 0) { + while (tar_exts[p] != NULL) { + if (strcmp (ext, tar_exts[p]) == 0) + ext = ext - 4; + p++; + } + } } return ext; } diff --git a/src/fr-window.c b/src/fr-window.c index 424cad4..cbb0ea6 100644 --- a/src/fr-window.c +++ b/src/fr-window.c @@ -127,6 +127,7 @@ typedef enum { typedef struct { GList *file_list; char *extract_to_dir; + char *sub_dir; char *base_dir; gboolean skip_older; FrOverwrite overwrite; @@ -4181,6 +4182,7 @@ file_list_drag_end (GtkWidget *widget, fr_window_archive_extract (window, window->priv->drag_file_list, window->priv->drag_destination_folder, + NULL, window->priv->drag_base_dir, FALSE, FR_OVERWRITE_ASK, @@ -6310,6 +6312,7 @@ fr_window_archive_remove (FrWindow *window, static ExtractData* extract_data_new (GList *file_list, const char *extract_to_dir, + const char *sub_dir, const char *base_dir, gboolean skip_older, FrOverwrite overwrite, @@ -6318,11 +6321,21 @@ extract_data_new (GList *file_list, gboolean ask_to_open_destination) { ExtractData *edata; + int i = 1; edata = g_new0 (ExtractData, 1); edata->file_list = path_list_dup (file_list); - if (extract_to_dir != NULL) + if (sub_dir != NULL) + edata->sub_dir = g_strdup (sub_dir); + if (extract_to_dir != NULL && sub_dir == NULL) { edata->extract_to_dir = g_strdup (extract_to_dir); + } else if (extract_to_dir != NULL && sub_dir != NULL) { + edata->extract_to_dir = g_build_filename (extract_to_dir, sub_dir, NULL); + while (uri_exists (edata->extract_to_dir) && uri_is_file (edata->extract_to_dir)) { + g_free (edata->extract_to_dir); + edata->extract_to_dir = g_strdup_printf ("%s/%s_%d", extract_to_dir, sub_dir, i++); + } + } edata->skip_older = skip_older; edata->overwrite = overwrite; edata->junk_paths = junk_paths; @@ -6340,6 +6353,7 @@ extract_to_data_new (const char *extract_to_dir) return extract_data_new (NULL, extract_to_dir, NULL, + NULL, FALSE, TRUE, FALSE, @@ -6354,6 +6368,7 @@ extract_data_free (ExtractData *edata) path_list_free (edata->file_list); g_free (edata->extract_to_dir); + g_free (edata->sub_dir); g_free (edata->base_dir); g_free (edata); @@ -6413,6 +6428,7 @@ fr_window_archive_extract_here (FrWindow *window, ExtractData *edata; edata = extract_data_new (NULL, + NULL, NULL, NULL, skip_older, @@ -6630,6 +6646,7 @@ void fr_window_archive_extract (FrWindow *window, GList *file_list, const char *extract_to_dir, + const char *sub_dir, const char *base_dir, gboolean skip_older, FrOverwrite overwrite, @@ -6642,6 +6659,7 @@ fr_window_archive_extract (FrWindow *window, edata = extract_data_new (file_list, extract_to_dir, + sub_dir, base_dir, skip_older, overwrite, @@ -8518,6 +8536,7 @@ fr_window_exec_batch_action (FrWindow *window, fr_window_archive_extract (window, edata->file_list, edata->extract_to_dir, + edata->sub_dir, edata->base_dir, edata->skip_older, edata->overwrite, @@ -8544,6 +8563,7 @@ fr_window_exec_batch_action (FrWindow *window, NULL, window->priv->extract_default_dir, NULL, + NULL, FALSE, FR_OVERWRITE_ASK, FALSE, diff --git a/src/fr-window.h b/src/fr-window.h index 436dd3c..dcbd018 100644 --- a/src/fr-window.h +++ b/src/fr-window.h @@ -152,6 +152,7 @@ void fr_window_archive_remove (FrWindow *window, void fr_window_archive_extract (FrWindow *window, GList *file_list, const char *extract_to_dir, + const char *sub_dir, const char *base_dir, gboolean skip_older, FrOverwrite overwrite, diff --git a/src/preferences.h b/src/preferences.h index 575ffb3..330845e 100644 --- a/src/preferences.h +++ b/src/preferences.h @@ -63,6 +63,7 @@ #define PREF_EXTRACT_SKIP_NEWER "skip-newer" #define PREF_EXTRACT_CLOSE_DIALOG "close-dialog" #define PREF_EXTRACT_RECREATE_FOLDERS "recreate-folders" +#define PREF_EXTRACT_CREATE_SUBDIR "create-subdirectory" #define PREF_ADD_CURRENT_FOLDER "current-folder" #define PREF_ADD_FILENAME "filename" diff --git a/src/ui/dlg-extract.ui b/src/ui/dlg-extract.ui index 745c548..e842512 100644 --- a/src/ui/dlg-extract.ui +++ b/src/ui/dlg-extract.ui @@ -304,6 +304,22 @@ 2 + + + Extract to s_ubdirectory + True + True + False + start + True + True + + + False + True + 1 + + -- cgit v1.2.1