/* nautilus-compress-dialog-controller.h * * Copyright (C) 2016 the Nautilus developers * * 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, see . * */ #include #include #include #include "nautilus-compress-dialog-controller.h" #include "nautilus-global-preferences.h" struct _NautilusCompressDialogController { NautilusFileNameWidgetController parent_instance; GtkWidget *compress_dialog; GtkWidget *description_stack; GtkWidget *name_entry; GtkWidget *zip_radio_button; GtkWidget *tar_xz_radio_button; GtkWidget *seven_zip_radio_button; const char *extension; gulong response_handler_id; }; G_DEFINE_TYPE (NautilusCompressDialogController, nautilus_compress_dialog_controller, NAUTILUS_TYPE_FILE_NAME_WIDGET_CONTROLLER); static gboolean nautilus_compress_dialog_controller_name_is_valid (NautilusFileNameWidgetController *self, gchar *name, gchar **error_message) { gboolean is_valid; is_valid = TRUE; if (strlen (name) == 0) { is_valid = FALSE; } else if (strstr (name, "/") != NULL) { is_valid = FALSE; *error_message = _("Archive names cannot contain “/”."); } else if (strcmp (name, ".") == 0) { is_valid = FALSE; *error_message = _("An archive cannot be called “.”."); } else if (strcmp (name, "..") == 0) { is_valid = FALSE; *error_message = _("An archive cannot be called “..”."); } else if (nautilus_file_name_widget_controller_is_name_too_long (self, name)) { is_valid = FALSE; *error_message = _("Archive name is too long."); } if (is_valid && g_str_has_prefix (name, ".")) { /* We must warn about the side effect */ *error_message = _("Archives with “.” at the beginning of their name are hidden."); } return is_valid; } static gchar * nautilus_compress_dialog_controller_get_new_name (NautilusFileNameWidgetController *controller) { NautilusCompressDialogController *self; g_autofree gchar *basename = NULL; gchar *error_message = NULL; gboolean valid_name; self = NAUTILUS_COMPRESS_DIALOG_CONTROLLER (controller); basename = NAUTILUS_FILE_NAME_WIDGET_CONTROLLER_CLASS (nautilus_compress_dialog_controller_parent_class)->get_new_name (controller); /* Do not check or add the extension if the name is invalid */ valid_name = nautilus_compress_dialog_controller_name_is_valid (controller, basename, &error_message); if (!valid_name) { return g_strdup (basename); } if (g_str_has_suffix (basename, self->extension)) { return g_strdup (basename); } return g_strconcat (basename, self->extension, NULL); } static void compress_dialog_controller_on_response (GtkDialog *dialog, gint response_id, gpointer user_data) { NautilusCompressDialogController *controller; controller = NAUTILUS_COMPRESS_DIALOG_CONTROLLER (user_data); if (response_id != GTK_RESPONSE_OK) { g_signal_emit_by_name (controller, "cancelled"); } } static void update_selected_format (NautilusCompressDialogController *self, NautilusCompressionFormat format) { const char *extension; const char *description_label_name; GtkWidget *active_button; switch (format) { case NAUTILUS_COMPRESSION_ZIP: { extension = ".zip"; description_label_name = "zip-description-label"; active_button = self->zip_radio_button; } break; case NAUTILUS_COMPRESSION_TAR_XZ: { extension = ".tar.xz"; description_label_name = "tar-xz-description-label"; active_button = self->tar_xz_radio_button; } break; case NAUTILUS_COMPRESSION_7ZIP: { extension = ".7z"; description_label_name = "seven-zip-description-label"; active_button = self->seven_zip_radio_button; } break; default: { g_assert_not_reached (); } break; } self->extension = extension; gtk_stack_set_visible_child_name (GTK_STACK (self->description_stack), description_label_name); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (active_button), TRUE); g_settings_set_enum (nautilus_compression_preferences, NAUTILUS_PREFERENCES_DEFAULT_COMPRESSION_FORMAT, format); /* Since the extension changes when the button is toggled, force a * verification of the new file name by simulating an entry change */ g_signal_emit_by_name (self->name_entry, "changed"); } static void zip_radio_button_on_toggled (GtkToggleButton *toggle_button, gpointer user_data) { NautilusCompressDialogController *controller; controller = NAUTILUS_COMPRESS_DIALOG_CONTROLLER (user_data); if (!gtk_toggle_button_get_active (toggle_button)) { return; } update_selected_format (controller, NAUTILUS_COMPRESSION_ZIP); } static void tar_xz_radio_button_on_toggled (GtkToggleButton *toggle_button, gpointer user_data) { NautilusCompressDialogController *controller; controller = NAUTILUS_COMPRESS_DIALOG_CONTROLLER (user_data); if (!gtk_toggle_button_get_active (toggle_button)) { return; } update_selected_format (controller, NAUTILUS_COMPRESSION_TAR_XZ); } static void seven_zip_radio_button_on_toggled (GtkToggleButton *toggle_button, gpointer user_data) { NautilusCompressDialogController *controller; controller = NAUTILUS_COMPRESS_DIALOG_CONTROLLER (user_data); if (!gtk_toggle_button_get_active (toggle_button)) { return; } update_selected_format (controller, NAUTILUS_COMPRESSION_7ZIP); } NautilusCompressDialogController * nautilus_compress_dialog_controller_new (GtkWindow *parent_window, NautilusDirectory *destination_directory, gchar *initial_name) { NautilusCompressDialogController *self; g_autoptr (GtkBuilder) builder = NULL; GtkWidget *compress_dialog; GtkWidget *error_revealer; GtkWidget *error_label; GtkWidget *name_entry; GtkWidget *activate_button; GtkWidget *description_stack; GtkWidget *zip_radio_button; GtkWidget *tar_xz_radio_button; GtkWidget *seven_zip_radio_button; NautilusCompressionFormat format; builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/ui/nautilus-compress-dialog.ui"); compress_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "compress_dialog")); error_revealer = GTK_WIDGET (gtk_builder_get_object (builder, "error_revealer")); error_label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label")); name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry")); activate_button = GTK_WIDGET (gtk_builder_get_object (builder, "activate_button")); zip_radio_button = GTK_WIDGET (gtk_builder_get_object (builder, "zip_radio_button")); tar_xz_radio_button = GTK_WIDGET (gtk_builder_get_object (builder, "tar_xz_radio_button")); seven_zip_radio_button = GTK_WIDGET (gtk_builder_get_object (builder, "seven_zip_radio_button")); description_stack = GTK_WIDGET (gtk_builder_get_object (builder, "description_stack")); gtk_window_set_transient_for (GTK_WINDOW (compress_dialog), parent_window); self = g_object_new (NAUTILUS_TYPE_COMPRESS_DIALOG_CONTROLLER, "error-revealer", error_revealer, "error-label", error_label, "name-entry", name_entry, "activate-button", activate_button, "containing-directory", destination_directory, NULL); self->compress_dialog = compress_dialog; self->zip_radio_button = zip_radio_button; self->tar_xz_radio_button = tar_xz_radio_button; self->seven_zip_radio_button = seven_zip_radio_button; self->description_stack = description_stack; self->name_entry = name_entry; self->response_handler_id = g_signal_connect (compress_dialog, "response", (GCallback) compress_dialog_controller_on_response, self); gtk_builder_add_callback_symbols (builder, "zip_radio_button_on_toggled", G_CALLBACK (zip_radio_button_on_toggled), "tar_xz_radio_button_on_toggled", G_CALLBACK (tar_xz_radio_button_on_toggled), "seven_zip_radio_button_on_toggled", G_CALLBACK (seven_zip_radio_button_on_toggled), NULL); gtk_builder_connect_signals (builder, self); format = g_settings_get_enum (nautilus_compression_preferences, NAUTILUS_PREFERENCES_DEFAULT_COMPRESSION_FORMAT); update_selected_format (self, format); if (initial_name != NULL) { gtk_entry_set_text (GTK_ENTRY (name_entry), initial_name); } gtk_widget_show_all (compress_dialog); return self; } static void nautilus_compress_dialog_controller_init (NautilusCompressDialogController *self) { } static void nautilus_compress_dialog_controller_finalize (GObject *object) { NautilusCompressDialogController *self; self = NAUTILUS_COMPRESS_DIALOG_CONTROLLER (object); if (self->compress_dialog != NULL) { g_clear_signal_handler (&self->response_handler_id, self->compress_dialog); gtk_widget_destroy (self->compress_dialog); self->compress_dialog = NULL; } G_OBJECT_CLASS (nautilus_compress_dialog_controller_parent_class)->finalize (object); } static void nautilus_compress_dialog_controller_class_init (NautilusCompressDialogControllerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); NautilusFileNameWidgetControllerClass *parent_class = NAUTILUS_FILE_NAME_WIDGET_CONTROLLER_CLASS (klass); object_class->finalize = nautilus_compress_dialog_controller_finalize; parent_class->get_new_name = nautilus_compress_dialog_controller_get_new_name; parent_class->name_is_valid = nautilus_compress_dialog_controller_name_is_valid; }