summaryrefslogtreecommitdiff
path: root/src/dlg-batch-add.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dlg-batch-add.c')
-rw-r--r--src/dlg-batch-add.c611
1 files changed, 611 insertions, 0 deletions
diff --git a/src/dlg-batch-add.c b/src/dlg-batch-add.c
new file mode 100644
index 0000000..47d11e2
--- /dev/null
+++ b/src/dlg-batch-add.c
@@ -0,0 +1,611 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * File-Roller
+ *
+ * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <math.h>
+#include <unistd.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include "file-utils.h"
+#include "fr-stock.h"
+#include "mateconf-utils.h"
+#include "fr-window.h"
+#include "typedefs.h"
+#include "gtk-utils.h"
+#include "glib-utils.h"
+#include "preferences.h"
+#include "main.h"
+
+
+#define ARCHIVE_ICON_SIZE (48)
+#define DEFAULT_EXTENSION ".tar.gz"
+#define BAD_CHARS "/\\*"
+
+
+typedef struct {
+ FrWindow *window;
+ GtkBuilder *builder;
+ int *supported_types;
+
+ GtkWidget *dialog;
+ GtkWidget *a_add_to_entry;
+ GtkWidget *a_location_filechooserbutton;
+ GtkWidget *add_image;
+ GtkWidget *a_archive_type_combo_box;
+ GtkWidget *a_other_options_expander;
+ GtkWidget *a_password_entry;
+ GtkWidget *a_password_label;
+ GtkWidget *a_encrypt_header_checkbutton;
+ GtkWidget *a_volume_checkbutton;
+ GtkWidget *a_volume_spinbutton;
+ GtkWidget *a_volume_box;
+
+ GList *file_list;
+ gboolean add_clicked;
+ const char *last_mime_type;
+ gboolean single_file;
+} DialogData;
+
+
+static const char *
+get_ext (DialogData *data)
+{
+ int idx;
+
+ idx = gtk_combo_box_get_active (GTK_COMBO_BOX (data->a_archive_type_combo_box));
+
+ return mime_type_desc[data->supported_types[idx]].default_ext;
+}
+
+
+/* called when the main dialog is closed. */
+static void
+destroy_cb (GtkWidget *widget,
+ DialogData *data)
+{
+ eel_mateconf_set_string (PREF_BATCH_ADD_DEFAULT_EXTENSION, get_ext (data));
+ /*eel_mateconf_set_boolean (PREF_BATCH_OTHER_OPTIONS, data->add_clicked ? FALSE : gtk_expander_get_expanded (GTK_EXPANDER (data->a_other_options_expander)));*/
+ eel_mateconf_set_boolean (PREF_ENCRYPT_HEADER, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->a_encrypt_header_checkbutton)));
+
+ if (! data->add_clicked) {
+ fr_window_pop_message (data->window);
+ fr_window_stop_batch (data->window);
+ }
+
+ g_object_unref (data->builder);
+ g_free (data);
+}
+
+
+static void
+set_archive_options (DialogData *data)
+{
+ int idx;
+
+ idx = gtk_combo_box_get_active (GTK_COMBO_BOX (data->a_archive_type_combo_box));
+ if (mime_type_desc[data->supported_types[idx]].capabilities & FR_COMMAND_CAN_ENCRYPT) {
+ const char *pwd;
+
+ pwd = gtk_entry_get_text (GTK_ENTRY (data->a_password_entry));
+ if (pwd != NULL) {
+ if (strcmp (pwd, "") != 0) {
+ fr_window_set_password (data->window, pwd);
+ if (mime_type_desc[data->supported_types[idx]].capabilities & FR_COMMAND_CAN_ENCRYPT_HEADER)
+ fr_window_set_encrypt_header (data->window, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->a_encrypt_header_checkbutton)));
+ }
+ }
+ }
+
+ if ((mime_type_desc[data->supported_types[idx]].capabilities & FR_COMMAND_CAN_CREATE_VOLUMES)
+ && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->a_volume_checkbutton)))
+ {
+ double value;
+ int size;
+
+ value = gtk_spin_button_get_value (GTK_SPIN_BUTTON (data->a_volume_spinbutton));
+ size = floor (value * MEGABYTE);
+ eel_mateconf_set_integer (PREF_BATCH_VOLUME_SIZE, size);
+ fr_window_set_volume_size (data->window, (guint) size);
+ }
+}
+
+
+static void
+help_clicked_cb (GtkWidget *widget,
+ DialogData *data)
+{
+ show_help_dialog (GTK_WINDOW (data->dialog), "file-roller-fmgr-add");
+}
+
+
+static void
+add_clicked_cb (GtkWidget *widget,
+ DialogData *data)
+{
+ FrWindow *window = data->window;
+ char *archive_name;
+ char *archive_dir;
+ char *archive_file;
+ char *tmp;
+ const char *archive_ext;
+ gboolean do_not_add = FALSE;
+ GError *error = NULL;
+
+ data->add_clicked = TRUE;
+
+ /* Collect data */
+
+ archive_name = g_uri_escape_string (gtk_entry_get_text (GTK_ENTRY (data->a_add_to_entry)), NULL, FALSE);
+
+ /* Check whether the user entered a valid archive name. */
+
+ if ((archive_name == NULL) || (*archive_name == '\0')) {
+ GtkWidget *d;
+
+ d = _gtk_error_dialog_new (GTK_WINDOW (window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ NULL,
+ _("Could not create the archive"),
+ "%s",
+ _("You have to specify an archive name."));
+ gtk_dialog_run (GTK_DIALOG (d));
+ gtk_widget_destroy (GTK_WIDGET (d));
+ g_free (archive_name);
+
+ return;
+ }
+ else if (strchrs (archive_name, BAD_CHARS)) {
+ GtkWidget *d;
+ char *utf8_name = g_filename_display_name (archive_name);
+
+ d = _gtk_error_dialog_new (GTK_WINDOW (window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ NULL,
+ _("Could not create the archive"),
+ _("The name \"%s\" is not valid because it cannot contain the characters: %s\n\n%s"),
+ utf8_name,
+ BAD_CHARS,
+ _("Please use a different name."));
+ gtk_dialog_run (GTK_DIALOG (d));
+ gtk_widget_destroy (GTK_WIDGET (d));
+
+ g_free (utf8_name);
+ g_free (archive_name);
+
+ return;
+ }
+
+ /* Check directory existence. */
+
+ archive_dir = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (data->a_location_filechooserbutton));
+ if (archive_dir == NULL) {
+ g_free (archive_dir);
+ g_free (archive_name);
+ return;
+ }
+
+ if (! check_permissions (archive_dir, R_OK|W_OK|X_OK)) {
+ GtkWidget *d;
+
+ d = _gtk_error_dialog_new (GTK_WINDOW (window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ NULL,
+ _("Could not create the archive"),
+ "%s",
+ _("You don't have the right permissions to create an archive in the destination folder."));
+ gtk_dialog_run (GTK_DIALOG (d));
+ gtk_widget_destroy (GTK_WIDGET (d));
+
+ g_free (archive_dir);
+ g_free (archive_name);
+ return;
+ }
+
+ if (! uri_is_dir (archive_dir)) {
+ GtkWidget *d;
+ int r;
+ char *folder_name;
+ char *msg;
+
+ folder_name = g_filename_display_name (archive_dir);
+ msg = g_strdup_printf (_("Destination folder \"%s\" does not exist.\n\nDo you want to create it?"), folder_name);
+ g_free (folder_name);
+
+ d = _gtk_message_dialog_new (GTK_WINDOW (data->dialog),
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_DIALOG_QUESTION,
+ msg,
+ NULL,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ _("Create _Folder"), GTK_RESPONSE_YES,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (d), GTK_RESPONSE_YES);
+ r = gtk_dialog_run (GTK_DIALOG (d));
+ gtk_widget_destroy (GTK_WIDGET (d));
+
+ g_free (msg);
+
+ do_not_add = (r != GTK_RESPONSE_YES);
+ }
+
+ if (! do_not_add && ! ensure_dir_exists (archive_dir, 0755, &error)) {
+ GtkWidget *d;
+
+ d = _gtk_error_dialog_new (GTK_WINDOW (window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ NULL,
+ _("Could not create the archive"),
+ _("Could not create the destination folder: %s."),
+ error->message);
+ gtk_dialog_run (GTK_DIALOG (d));
+ gtk_widget_destroy (GTK_WIDGET (d));
+
+ g_error_free (error);
+ g_free (archive_dir);
+ g_free (archive_name);
+ return;
+ }
+
+ if (do_not_add) {
+ GtkWidget *d;
+
+ d = _gtk_message_dialog_new (GTK_WINDOW (window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_DIALOG_WARNING,
+ _("Archive not created"),
+ NULL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (d), GTK_RESPONSE_OK);
+ gtk_dialog_run (GTK_DIALOG (d));
+ gtk_widget_destroy (GTK_WIDGET (d));
+
+ g_free (archive_dir);
+ g_free (archive_name);
+
+ return;
+ }
+
+ /**/
+
+ archive_ext = get_ext (data);
+ tmp = archive_name;
+ archive_name = g_strconcat (tmp, archive_ext, NULL);
+ g_free (tmp);
+ archive_file = g_strconcat (archive_dir, "/", archive_name, NULL);
+
+ if (uri_is_dir (archive_file)) {
+ GtkWidget *d;
+
+ d = _gtk_error_dialog_new (GTK_WINDOW (window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ NULL,
+ _("Could not create the archive"),
+ "%s",
+ _("You have to specify an archive name."));
+ gtk_dialog_run (GTK_DIALOG (d));
+ gtk_widget_destroy (GTK_WIDGET (d));
+
+ g_free (archive_name);
+ g_free (archive_dir);
+ g_free (archive_file);
+
+ return;
+ }
+
+ if (uri_exists (archive_file)) {
+ GtkWidget *d;
+ int r;
+
+ d = _gtk_message_dialog_new (GTK_WINDOW (data->dialog),
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_DIALOG_QUESTION,
+ _("The archive is already present. Do you want to overwrite it?"),
+ NULL,
+ GTK_STOCK_NO, GTK_RESPONSE_NO,
+ _("_Overwrite"), GTK_RESPONSE_YES,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (d), GTK_RESPONSE_YES);
+ r = gtk_dialog_run (GTK_DIALOG (d));
+ gtk_widget_destroy (GTK_WIDGET (d));
+
+ if (r == GTK_RESPONSE_YES) {
+ GFile *file;
+ GError *err = NULL;
+
+ /* FIXME: convert this code in a function in file-utils.c */
+ file = g_file_new_for_uri (archive_file);
+ g_file_delete (file, NULL, &err);
+ if (err != NULL) {
+ g_warning ("Failed to delete file %s: %s",
+ archive_file,
+ err->message);
+ g_clear_error (&err);
+ }
+ g_object_unref (file);
+ }
+ else {
+ g_free (archive_name);
+ g_free (archive_dir);
+ g_free (archive_file);
+ return;
+ }
+ }
+ set_archive_options (data);
+ gtk_widget_destroy (data->dialog);
+
+ fr_window_archive_new (window, archive_file);
+
+ g_free (archive_name);
+ g_free (archive_dir);
+ g_free (archive_file);
+}
+
+
+static void
+update_sensitivity_for_mime_type (DialogData *data,
+ const char *mime_type)
+{
+ int i;
+
+ if (mime_type == NULL) {
+ gtk_widget_set_sensitive (data->a_password_entry, FALSE);
+ gtk_widget_set_sensitive (data->a_password_label, FALSE);
+ gtk_widget_set_sensitive (data->a_encrypt_header_checkbutton, FALSE);
+ gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (data->a_encrypt_header_checkbutton), TRUE);
+ gtk_widget_set_sensitive (data->a_volume_box, FALSE);
+ return;
+ }
+
+ for (i = 0; mime_type_desc[i].mime_type != NULL; i++) {
+ if (strcmp (mime_type_desc[i].mime_type, mime_type) == 0) {
+ gboolean sensitive;
+
+ sensitive = mime_type_desc[i].capabilities & FR_COMMAND_CAN_ENCRYPT;
+ gtk_widget_set_sensitive (data->a_password_entry, sensitive);
+ gtk_widget_set_sensitive (data->a_password_label, sensitive);
+
+ sensitive = mime_type_desc[i].capabilities & FR_COMMAND_CAN_ENCRYPT_HEADER;
+ gtk_widget_set_sensitive (data->a_encrypt_header_checkbutton, sensitive);
+ gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (data->a_encrypt_header_checkbutton), ! sensitive);
+
+ sensitive = mime_type_desc[i].capabilities & FR_COMMAND_CAN_CREATE_VOLUMES;
+ gtk_widget_set_sensitive (data->a_volume_box, sensitive);
+
+ break;
+ }
+ }
+}
+
+
+static void
+archive_type_combo_box_changed_cb (GtkComboBox *combo_box,
+ DialogData *data)
+{
+ const char *mime_type;
+ int idx = gtk_combo_box_get_active (combo_box);
+
+ mime_type = mime_type_desc[data->supported_types[idx]].mime_type;
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (data->add_image), get_mime_type_pixbuf (mime_type, ARCHIVE_ICON_SIZE, NULL));
+ update_sensitivity_for_mime_type (data, mime_type);
+}
+
+
+static void
+update_archive_type_combo_box_from_ext (DialogData *data,
+ const char *ext)
+{
+ int idx = 0;
+ int i;
+
+ if (ext == NULL) {
+ gtk_combo_box_set_active (GTK_COMBO_BOX (data->a_archive_type_combo_box), 0);
+ return;
+ }
+
+ for (i = 0; data->supported_types[i] != -1; i++)
+ if (strcmp (ext, mime_type_desc[data->supported_types[i]].default_ext) == 0) {
+ idx = i;
+ break;
+ }
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (data->a_archive_type_combo_box), idx);
+}
+
+
+static void
+update_sensitivity (DialogData *data)
+{
+ gtk_widget_set_sensitive (data->a_volume_spinbutton, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->a_volume_checkbutton)));
+}
+
+
+static void
+password_entry_changed_cb (GtkEditable *editable,
+ gpointer user_data)
+{
+ update_sensitivity ((DialogData *) user_data);
+}
+
+
+static void
+volume_toggled_cb (GtkToggleButton *toggle_button,
+ gpointer user_data)
+{
+ update_sensitivity ((DialogData *) user_data);
+}
+
+
+void
+dlg_batch_add_files (FrWindow *window,
+ GList *file_list)
+{
+ DialogData *data;
+ GtkWidget *cancel_button;
+ GtkWidget *help_button;
+ GtkWidget *add_button;
+ GtkWidget *a_archive_type_box;
+ GtkSizeGroup *size_group;
+ char *automatic_name = NULL;
+ char *default_ext;
+ const char *first_filename;
+ char *parent;
+ int i;
+
+ if (file_list == NULL)
+ return;
+
+ data = g_new0 (DialogData, 1);
+
+ data->builder = _gtk_builder_new_from_file ("batch-add-files.ui");
+ if (data->builder == NULL) {
+ g_free (data);
+ return;
+ }
+
+ data->window = window;
+ data->file_list = file_list;
+ data->single_file = ((file_list->next == NULL) && uri_is_file ((char*) file_list->data));
+ data->add_clicked = FALSE;
+
+ /* Get the widgets. */
+
+ data->dialog = _gtk_builder_get_widget (data->builder, "batch_add_files_dialog");
+ data->a_add_to_entry = _gtk_builder_get_widget (data->builder, "a_add_to_entry");
+ data->a_location_filechooserbutton = _gtk_builder_get_widget (data->builder, "a_location_filechooserbutton");
+ data->a_password_entry = _gtk_builder_get_widget (data->builder, "a_password_entry");
+ data->a_password_label = _gtk_builder_get_widget (data->builder, "a_password_label");
+ data->a_other_options_expander = _gtk_builder_get_widget (data->builder, "a_other_options_expander");
+ data->a_encrypt_header_checkbutton = _gtk_builder_get_widget (data->builder, "a_encrypt_header_checkbutton");
+
+ data->a_volume_checkbutton = _gtk_builder_get_widget (data->builder, "a_volume_checkbutton");
+ data->a_volume_spinbutton = _gtk_builder_get_widget (data->builder, "a_volume_spinbutton");
+ data->a_volume_box = _gtk_builder_get_widget (data->builder, "a_volume_box");
+
+ add_button = _gtk_builder_get_widget (data->builder, "a_add_button");
+ cancel_button = _gtk_builder_get_widget (data->builder, "a_cancel_button");
+ help_button = _gtk_builder_get_widget (data->builder, "a_help_button");
+ a_archive_type_box = _gtk_builder_get_widget (data->builder, "a_archive_type_box");
+
+ data->add_image = _gtk_builder_get_widget (data->builder, "a_add_image");
+
+ /* Set widgets data. */
+
+ size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ gtk_size_group_add_widget (size_group, _gtk_builder_get_widget (data->builder, "a_archive_label"));
+ gtk_size_group_add_widget (size_group, _gtk_builder_get_widget (data->builder, "a_location_label"));
+ gtk_size_group_add_widget (size_group, _gtk_builder_get_widget (data->builder, "a_password_label"));
+
+ gtk_button_set_use_stock (GTK_BUTTON (add_button), TRUE);
+ gtk_button_set_label (GTK_BUTTON (add_button), FR_STOCK_CREATE_ARCHIVE);
+ gtk_expander_set_expanded (GTK_EXPANDER (data->a_other_options_expander), FALSE /*eel_mateconf_get_boolean (PREF_BATCH_OTHER_OPTIONS, FALSE)*/);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->a_encrypt_header_checkbutton), eel_mateconf_get_boolean (PREF_ENCRYPT_HEADER, FALSE));
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (data->a_volume_spinbutton), (double) eel_mateconf_get_integer (PREF_BATCH_VOLUME_SIZE, 0) / MEGABYTE);
+
+ first_filename = (char*) file_list->data;
+ parent = remove_level_from_path (first_filename);
+
+ if (file_list->next == NULL)
+ automatic_name = g_uri_unescape_string (file_name_from_path ((char*) file_list->data), NULL);
+ else {
+ automatic_name = g_uri_unescape_string (file_name_from_path (parent), NULL);
+ if ((automatic_name == NULL) || (automatic_name[0] == '\0')) {
+ g_free (automatic_name);
+ automatic_name = g_uri_unescape_string (file_name_from_path (first_filename), NULL);
+ }
+ }
+
+ _gtk_entry_set_filename_text (GTK_ENTRY (data->a_add_to_entry), automatic_name);
+ g_free (automatic_name);
+
+ if (check_permissions (parent, R_OK | W_OK))
+ gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (data->a_location_filechooserbutton), parent);
+ else
+ gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (data->a_location_filechooserbutton), get_home_uri ());
+ g_free (parent);
+
+ /* archive type combobox */
+
+ data->a_archive_type_combo_box = gtk_combo_box_new_text ();
+ if (data->single_file)
+ data->supported_types = single_file_save_type;
+ else
+ data->supported_types = save_type;
+ sort_mime_types_by_extension (data->supported_types);
+
+ for (i = 0; data->supported_types[i] != -1; i++)
+ gtk_combo_box_append_text (GTK_COMBO_BOX (data->a_archive_type_combo_box),
+ mime_type_desc[data->supported_types[i]].default_ext);
+
+ gtk_box_pack_start (GTK_BOX (a_archive_type_box), data->a_archive_type_combo_box, TRUE, TRUE, 0);
+ gtk_widget_show_all (a_archive_type_box);
+
+ /* Set the signals handlers. */
+
+ g_signal_connect (G_OBJECT (data->dialog),
+ "destroy",
+ G_CALLBACK (destroy_cb),
+ data);
+ g_signal_connect_swapped (G_OBJECT (cancel_button),
+ "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ G_OBJECT (data->dialog));
+ g_signal_connect (G_OBJECT (add_button),
+ "clicked",
+ G_CALLBACK (add_clicked_cb),
+ data);
+ g_signal_connect (G_OBJECT (help_button),
+ "clicked",
+ G_CALLBACK (help_clicked_cb),
+ data);
+ g_signal_connect (G_OBJECT (data->a_archive_type_combo_box),
+ "changed",
+ G_CALLBACK (archive_type_combo_box_changed_cb),
+ data);
+ g_signal_connect (G_OBJECT (data->a_password_entry),
+ "changed",
+ G_CALLBACK (password_entry_changed_cb),
+ data);
+ g_signal_connect (G_OBJECT (data->a_volume_checkbutton),
+ "toggled",
+ G_CALLBACK (volume_toggled_cb),
+ data);
+
+ /* Run dialog. */
+
+ default_ext = eel_mateconf_get_string (PREF_BATCH_ADD_DEFAULT_EXTENSION, DEFAULT_EXTENSION);
+ update_archive_type_combo_box_from_ext (data, default_ext);
+ g_free (default_ext);
+
+ gtk_widget_grab_focus (data->a_add_to_entry);
+ gtk_editable_select_region (GTK_EDITABLE (data->a_add_to_entry),
+ 0, -1);
+
+ update_sensitivity (data);
+
+ gtk_window_set_modal (GTK_WINDOW (data->dialog), FALSE);
+ gtk_window_present (GTK_WINDOW (data->dialog));
+}