diff --git a/gtk/Makefile.am b/gtk/Makefile.am index e2353d818a..73b8b9252d 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -463,6 +463,7 @@ gtk_private_h_sources = \ gtkfilechooserprivate.h \ gtkfilechoosernativeprivate.h \ gtkfilechooserwidgetprivate.h \ + gtkfilechoosererrorstackprivate.h \ gtkfilechooserutils.h \ gtkfilefilterprivate.h \ gtkfilesystem.h \ @@ -943,7 +944,8 @@ gtk_base_c_sources = \ gtkwin32theme.c \ gdkpixbufutils.c \ gtkgizmo.c \ - gtkcenterbox.c + gtkcenterbox.c \ + gtkfilechoosererrorstack.c if USE_QUARTZ gtk_base_c_sources += \ diff --git a/gtk/gtkfilechoosererrorstack.c b/gtk/gtkfilechoosererrorstack.c new file mode 100644 index 0000000000..03d9c0c768 --- /dev/null +++ b/gtk/gtkfilechoosererrorstack.c @@ -0,0 +1,136 @@ +/* This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ +#include "config.h" +#include "gtkfilechoosererrorstackprivate.h" +#include "gtkstack.h" +#include "gtklabel.h" +#include "gtkintl.h" + +G_DEFINE_TYPE (GtkFileChooserErrorStack, gtk_file_chooser_error_stack, GTK_TYPE_STACK) + +static void +gtk_file_chooser_error_stack_class_init (GtkFileChooserErrorStackClass *class) +{ + +} + +static void +gtk_file_chooser_error_stack_init (GtkFileChooserErrorStack *self) +{ + GtkWidget *label; + GtkStack *stack = GTK_STACK (self); + + gtk_stack_set_transition_type (stack, GTK_STACK_TRANSITION_TYPE_CROSSFADE); + gtk_stack_set_transition_duration (stack, 50); + + label = gtk_label_new (""); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "no-error"); + + label = gtk_label_new (""); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "custom"); + + label = gtk_label_new (_("A folder cannot be called “.”")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "folder-cannot-be-called-dot"); + + label = gtk_label_new (_("A file cannot be called “.”")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "file-cannot-be-called-dot"); + + label = gtk_label_new (_("A folder cannot be called “..”")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "folder-cannot-be-called-dot-dot"); + + label = gtk_label_new (_("A file cannot be called “..”")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "file-cannot-be-called-dot-dot"); + + label = gtk_label_new (_("Folder names cannot contain “/”")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "folder-name-cannot-contain-slash"); + + label = gtk_label_new (_("File names cannot contain “/”")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "file-name-cannot-contain-slash"); + + label = gtk_label_new (_("Folder names should not begin with a space")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "folder-name-should-not-begin-with-space"); + + label = gtk_label_new (_("File names should not begin with a space")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "file-name-should-not-begin-with-space"); + + label = gtk_label_new (_("Folder names should not end with a space")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "folder-name-should-not-end-with-space"); + + label = gtk_label_new (_("File names should not end with a space")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "file-name-should-not-end-with-space"); + + label = gtk_label_new (_("Folder names starting with a “.” are hidden")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "folder-name-with-dot-is-hidden"); + + label = gtk_label_new (_("File names starting with a “.” are hidden")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "file-name-with-dot-is-hidden"); + + label = gtk_label_new (_("A folder with that name already exists")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "folder-name-already-exists"); + + label = gtk_label_new (_("A file with that name already exists")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_stack_add_named (stack, label, "file-name-already-exists"); + + gtk_stack_set_visible_child_name (stack, "no-error"); +} + +void +gtk_file_chooser_error_stack_set_error (GtkFileChooserErrorStack *self, + gboolean is_folder, + const char *label_name) +{ + char *child_name; + + if (g_strcmp0 (label_name, "no-error") == 0) + { + gtk_stack_set_visible_child_name (GTK_STACK (self), "no-error"); + return; + } + + child_name = g_strdup_printf ("%s-%s", + is_folder ? "folder" : "file", + label_name); + + gtk_stack_set_visible_child_name (GTK_STACK (self), child_name); + + g_free (child_name); +} + + +void +gtk_file_chooser_error_stack_set_custom_error (GtkFileChooserErrorStack *self, + const char *label_text) +{ + GtkWidget *label = gtk_stack_get_child_by_name (GTK_STACK (self), "cutsom"); + + gtk_label_set_text (GTK_LABEL (label), label_text); + + gtk_stack_set_visible_child_name (GTK_STACK (self), "custom"); +} diff --git a/gtk/gtkfilechoosererrorstackprivate.h b/gtk/gtkfilechoosererrorstackprivate.h new file mode 100644 index 0000000000..7f222c65f8 --- /dev/null +++ b/gtk/gtkfilechoosererrorstackprivate.h @@ -0,0 +1,58 @@ +/* This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __GTK_FILE_CHOOSER_ERROR_STACK_H__ +#define __GTK_FILE_CHOOSER_ERROR_STACK_H__ + + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#include "gtkstack.h" + +G_BEGIN_DECLS + +#define GTK_TYPE_FILE_CHOOSER_ERROR_STACK (gtk_file_chooser_error_stack_get_type ()) +#define GTK_FILE_CHOOSER_ERROR_STACK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER_ERROR_STACK, GtkFileChooserErrorStack)) +#define GTK_FILE_CHOOSER_ERROR_STACK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_CHOOSER_ERROR_STACK, GtkFileChooserErrorStackClass)) +#define GTK_IS_FILE_CHOOSER_ERROR_STACK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_CHOOSER_ERROR_STACK)) +#define GTK_IS_FILE_CHOOSER_ERROR_STACK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_CHOOSER_ERROR_STACK)) +#define GTK_FILE_CHOOSER_ERROR_STACK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_CHOOSER_ERROR_STACK, GtkFileChooserErrorStackClass)) + +typedef struct _GtkFileChooserErrorStack GtkFileChooserErrorStack; +typedef struct _GtkFileChooserErrorStackClass GtkFileChooserErrorStackClass; + +struct _GtkFileChooserErrorStack +{ + GtkStack parent_instance; +}; + +struct _GtkFileChooserErrorStackClass +{ + GtkStackClass parent_class; +}; + +GType gtk_file_chooser_error_stack_get_type (void) G_GNUC_CONST; + +void gtk_file_chooser_error_stack_set_error (GtkFileChooserErrorStack *self, + gboolean is_folder, + const char *label_name); + +void gtk_file_chooser_error_stack_set_custom_error (GtkFileChooserErrorStack *self, + const char *label_text); + +G_END_DECLS + +#endif diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c index ec51668609..08c96bb1db 100644 --- a/gtk/gtkfilechooserwidget.c +++ b/gtk/gtkfilechooserwidget.c @@ -81,6 +81,7 @@ #include "gtkmodelbutton.h" #include "gtkgesturelongpress.h" #include "gtkdebug.h" +#include "gtkfilechoosererrorstackprivate.h" #include @@ -248,11 +249,11 @@ struct _GtkFileChooserWidgetPrivate { GtkWidget *browse_path_bar; GtkWidget *new_folder_name_entry; GtkWidget *new_folder_create_button; - GtkWidget *new_folder_error_label; + GtkWidget *new_folder_error_stack; GtkWidget *new_folder_popover; GtkWidget *rename_file_name_entry; GtkWidget *rename_file_rename_button; - GtkWidget *rename_file_error_label; + GtkWidget *rename_file_error_stack; GtkWidget *rename_file_popover; GFile *rename_file_source_file; @@ -985,7 +986,9 @@ new_folder_popover_active (GtkWidget *button, gtk_entry_set_text (GTK_ENTRY (priv->new_folder_name_entry), ""); gtk_widget_set_sensitive (priv->new_folder_create_button, FALSE); - gtk_label_set_text (GTK_LABEL (priv->new_folder_error_label), ""); + gtk_file_chooser_error_stack_set_error (GTK_FILE_CHOOSER_ERROR_STACK (priv->new_folder_error_stack), + FALSE, + "no-error"); } struct FileExistsData @@ -994,7 +997,7 @@ struct FileExistsData gboolean file_exists_and_is_not_folder; GFile *parent_file; GFile *file; - GtkWidget *error_label; + GtkWidget *error_stack; GtkWidget *button; }; @@ -1018,15 +1021,10 @@ name_exists_get_info_cb (GCancellable *cancellable, if (info != NULL) { - const gchar *msg; - - if (_gtk_file_info_consider_as_directory (info)) - msg = _("A folder with that name already exists"); - else - msg = _("A file with that name already exists"); - gtk_widget_set_sensitive (data->button, FALSE); - gtk_label_set_text (GTK_LABEL (data->error_label), msg); + gtk_file_chooser_error_stack_set_error (GTK_FILE_CHOOSER_ERROR_STACK (data->error_stack), + _gtk_file_info_consider_as_directory (info), + "name-already-exists"); } else { @@ -1047,38 +1045,31 @@ check_valid_child_name (GtkFileChooserWidget *impl, const gchar *name, gboolean is_folder, GFile *original, - GtkWidget *error_label, + GtkWidget *error_stack, GtkWidget *button) { GtkFileChooserWidgetPrivate *priv = impl->priv; + GtkFileChooserErrorStack *stack = GTK_FILE_CHOOSER_ERROR_STACK (error_stack); gtk_widget_set_sensitive (button, FALSE); if (name[0] == '\0') - gtk_label_set_text (GTK_LABEL (error_label), ""); + gtk_file_chooser_error_stack_set_error (stack, FALSE, "no-error"); else if (strcmp (name, ".") == 0) - gtk_label_set_text (GTK_LABEL (error_label), - is_folder ? _("A folder cannot be called “.”") - : _("A file cannot be called “.”")); + gtk_file_chooser_error_stack_set_error (stack, is_folder, "cannot-be-called-dot"); else if (strcmp (name, "..") == 0) - gtk_label_set_text (GTK_LABEL (error_label), - is_folder ? _("A folder cannot be called “..”") - : _("A file cannot be called “..”")); + gtk_file_chooser_error_stack_set_error (stack, is_folder, "cannot-be-called-dot-dot"); else if (strchr (name, '/') != NULL) - gtk_label_set_text (GTK_LABEL (error_label), - is_folder ? _("Folder names cannot contain “/”") - : _("File names cannot contain “/”")); + gtk_file_chooser_error_stack_set_error (stack, is_folder, "name-cannot-contain-slash"); else { GFile *file; GError *error = NULL; - gtk_label_set_text (GTK_LABEL (error_label), ""); - file = g_file_get_child_for_display_name (parent, name, &error); if (file == NULL) { - gtk_label_set_text (GTK_LABEL (error_label), error->message); + gtk_file_chooser_error_stack_set_custom_error (stack, error->message); g_error_free (error); } else if (original && g_file_equal (original, file)) @@ -1092,23 +1083,18 @@ check_valid_child_name (GtkFileChooserWidget *impl, /* Warn the user about questionable names that are technically valid */ if (g_ascii_isspace (name[0])) - gtk_label_set_text (GTK_LABEL (error_label), - is_folder ? _("Folder names should not begin with a space") - : _("File names should not begin with a space")); - + gtk_file_chooser_error_stack_set_error (stack, is_folder, "name-should-not-begin-with-space"); else if (g_ascii_isspace (name[strlen (name) - 1])) - gtk_label_set_text (GTK_LABEL (error_label), - is_folder ? _("Folder names should not end with a space") - : _("File names should not end with a space")); + gtk_file_chooser_error_stack_set_error (stack, is_folder, "name-should-not-end-with-space"); else if (name[0] == '.') - gtk_label_set_text (GTK_LABEL (error_label), - is_folder ? _("Folder names starting with a “.” are hidden") - : _("File names starting with a “.” are hidden")); + gtk_file_chooser_error_stack_set_error (stack, is_folder, "name-with-dot-is-hidden"); + else + gtk_file_chooser_error_stack_set_error (stack, FALSE, "no-error"); data = g_new0 (struct FileExistsData, 1); data->impl = g_object_ref (impl); data->file = g_object_ref (file); - data->error_label = error_label; + data->error_stack = error_stack; data->button = button; if (priv->file_exists_get_info_cancellable) @@ -1137,7 +1123,7 @@ new_folder_name_changed (GtkEntry *entry, gtk_entry_get_text (entry), TRUE, NULL, - priv->new_folder_error_label, + priv->new_folder_error_stack, priv->new_folder_create_button); } @@ -1570,7 +1556,7 @@ rename_file_name_changed (GtkEntry *entry, gtk_entry_get_text (entry), file_type == G_FILE_TYPE_DIRECTORY, priv->rename_file_source_file, - priv->rename_file_error_label, + priv->rename_file_error_stack, priv->rename_file_rename_button); } @@ -8499,11 +8485,11 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class) gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, list_location_renderer); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, new_folder_name_entry); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, new_folder_create_button); - gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, new_folder_error_label); + gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, new_folder_error_stack); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, new_folder_popover); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, rename_file_name_entry); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, rename_file_rename_button); - gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, rename_file_error_label); + gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, rename_file_error_stack); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, rename_file_popover); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, remote_warning_bar); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, box); @@ -8661,6 +8647,7 @@ gtk_file_chooser_widget_init (GtkFileChooserWidget *impl) */ g_type_ensure (GTK_TYPE_PATH_BAR); g_type_ensure (GTK_TYPE_PLACES_VIEW); + g_type_ensure (GTK_TYPE_FILE_CHOOSER_ERROR_STACK); gtk_widget_init_template (GTK_WIDGET (impl)); gtk_widget_set_size_request (priv->browse_files_tree_view, 280, -1); diff --git a/gtk/ui/gtkfilechooserwidget.ui b/gtk/ui/gtkfilechooserwidget.ui index 40e688ba28..bf678809dc 100644 --- a/gtk/ui/gtkfilechooserwidget.ui +++ b/gtk/ui/gtkfilechooserwidget.ui @@ -427,8 +427,7 @@ - - start + 0 @@ -487,8 +486,7 @@ - - start + 0