[gtk+/save-popover: 1/2] Use a popover for creating new folders
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/save-popover: 1/2] Use a popover for creating new folders
- Date: Fri, 10 Apr 2015 01:04:00 +0000 (UTC)
commit 5e35d3c8de8209bca2f9469a4e94441c8c290ca3
Author: Matthias Clasen <mclasen redhat com>
Date: Thu Apr 9 20:56:54 2015 -0400
Use a popover for creating new folders
gtk/gtkfilechooserwidget.c | 172 ++++++++++++++++++++++++++++++++++++++--
gtk/ui/gtkfilechooserwidget.ui | 83 ++++++++++++++++---
2 files changed, 233 insertions(+), 22 deletions(-)
---
diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c
index 8fada3b..3016d88 100644
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -229,6 +229,10 @@ struct _GtkFileChooserWidgetPrivate {
GtkWidget *browse_path_bar_hbox;
GtkSizeGroup *browse_path_bar_size_group;
GtkWidget *browse_path_bar;
+ GtkWidget *new_folder_name_entry;
+ GtkWidget *new_folder_create_button;
+ GtkWidget *new_folder_error_label;
+ GtkWidget *new_folder_popover;
GtkFileSystemModel *browse_files_model;
char *browse_files_last_selected_name;
@@ -937,6 +941,159 @@ new_folder_button_clicked (GtkButton *button,
gtk_tree_path_free (path);
}
+static void
+new_folder_popover_active (GtkWidget *button,
+ GParamSpec *pspec,
+ GtkFileChooserWidget *impl)
+{
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+
+ 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), "");
+}
+
+struct FileExistsData
+{
+ GtkFileChooserWidget *impl;
+ gboolean file_exists_and_is_not_folder;
+ GFile *parent_file;
+ GFile *file;
+};
+
+static void
+name_exists_get_info_cb (GCancellable *cancellable,
+ GFileInfo *info,
+ const GError *error,
+ gpointer user_data)
+{
+ struct FileExistsData *data = user_data;
+ GtkFileChooserWidget *impl = data->impl;
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+
+ if (cancellable != priv->file_exists_get_info_cancellable)
+ goto out;
+
+ priv->file_exists_get_info_cancellable = NULL;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ goto out;
+
+ 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 (priv->new_folder_create_button, FALSE);
+ gtk_label_set_text (GTK_LABEL (priv->new_folder_error_label), msg);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (priv->new_folder_create_button, TRUE);
+ gtk_label_set_text (GTK_LABEL (priv->new_folder_error_label), "");
+ }
+
+out:
+ g_object_unref (impl);
+ g_object_unref (data->file);
+ g_object_unref (data->parent_file);
+ g_free (data);
+ g_object_unref (cancellable);
+}
+
+static void
+check_valid_folder_name (GtkFileChooserWidget *impl,
+ const gchar *name)
+{
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+
+ gtk_widget_set_sensitive (priv->new_folder_create_button, FALSE);
+
+ if (name[0] == '\0')
+ gtk_label_set_text (GTK_LABEL (priv->new_folder_error_label), "");
+ else if (strcmp (name, ".") == 0)
+ gtk_label_set_text (GTK_LABEL (priv->new_folder_error_label),
+ _("A folder cannot be called “.”"));
+ else if (strcmp (name, "..") == 0)
+ gtk_label_set_text (GTK_LABEL (priv->new_folder_error_label),
+ _("A folder cannot be called “..”"));
+ else if (strchr (name, '/') != NULL)
+ gtk_label_set_text (GTK_LABEL (priv->new_folder_error_label),
+ _("Folder names cannot contain “/”"));
+ else
+ {
+ GFile *file;
+ GError *error = NULL;
+
+ file = g_file_get_child_for_display_name (priv->current_folder, name, &error);
+ if (file == NULL)
+ {
+ gtk_label_set_text (GTK_LABEL (priv->new_folder_error_label), error->message);
+ g_error_free (error);
+ }
+ else
+ {
+ struct FileExistsData *data;
+
+ gtk_label_set_text (GTK_LABEL (priv->new_folder_error_label), "");
+
+ data = g_new0 (struct FileExistsData, 1);
+ data->impl = g_object_ref (impl);
+ data->parent_file = g_object_ref (priv->current_folder);
+ data->file = g_object_ref (file);
+
+ if (priv->file_exists_get_info_cancellable)
+ g_cancellable_cancel (priv->file_exists_get_info_cancellable);
+
+ priv->file_exists_get_info_cancellable =
+ _gtk_file_system_get_info (priv->file_system,
+ file,
+ "standard::type",
+ name_exists_get_info_cb,
+ data);
+
+ g_object_unref (file);
+ }
+ }
+}
+
+static void
+new_folder_name_changed (GtkEntry *entry,
+ GtkFileChooserWidget *impl)
+{
+ check_valid_folder_name (impl, gtk_entry_get_text (entry));
+}
+
+static void
+new_folder_create_clicked (GtkButton *button,
+ GtkFileChooserWidget *impl)
+{
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+ GError *error = NULL;
+ GFile *file;
+ const gchar *name;
+
+ name = gtk_entry_get_text (GTK_ENTRY (priv->new_folder_name_entry));
+ file = g_file_get_child_for_display_name (priv->current_folder, name, &error);
+
+ gtk_widget_hide (priv->new_folder_popover);
+
+ if (file)
+ {
+ if (g_file_make_directory (file, NULL, &error))
+ change_folder_and_display_error (impl, file, FALSE);
+ else
+ error_creating_folder_dialog (impl, file, error);
+ g_object_unref (file);
+ }
+ else
+ error_creating_folder_dialog (impl, file, error);
+}
+
static GSource *
add_idle_while_impl_is_alive (GtkFileChooserWidget *impl, GCallback callback)
{
@@ -5482,14 +5639,6 @@ should_respond_after_confirm_overwrite (GtkFileChooserWidget *impl,
}
}
-struct FileExistsData
-{
- GtkFileChooserWidget *impl;
- gboolean file_exists_and_is_not_folder;
- GFile *parent_file;
- GFile *file;
-};
-
static void
name_entry_get_parent_info_cb (GCancellable *cancellable,
GFileInfo *info,
@@ -7491,6 +7640,10 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, list_mtime_column);
gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, list_size_column);
gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, list_location_column);
+ 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_popover);
/* And a *lot* of callbacks to bind ... */
gtk_widget_class_bind_template_callback (widget_class, browse_files_key_press_event_cb);
@@ -7513,6 +7666,9 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
gtk_widget_class_bind_template_callback (widget_class, places_sidebar_show_enter_location_cb);
gtk_widget_class_bind_template_callback (widget_class, search_entry_activate_cb);
gtk_widget_class_bind_template_callback (widget_class, search_entry_stop_cb);
+ gtk_widget_class_bind_template_callback (widget_class, new_folder_popover_active);
+ gtk_widget_class_bind_template_callback (widget_class, new_folder_name_changed);
+ gtk_widget_class_bind_template_callback (widget_class, new_folder_create_clicked);
}
static void
diff --git a/gtk/ui/gtkfilechooserwidget.ui b/gtk/ui/gtkfilechooserwidget.ui
index 83e095c..40cfb3e 100644
--- a/gtk/ui/gtkfilechooserwidget.ui
+++ b/gtk/ui/gtkfilechooserwidget.ui
@@ -78,22 +78,13 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="browse_new_folder_button">
- <property name="tooltip-text" translatable="yes">Create Folder</property>
+ <object class="GtkMenuButton" id="browse_new_folder_button">
+ <property name="label" translatable="yes">Create _Folder</property>
<property name="can_focus">True</property>
- <property name="receives_default">True</property>
+ <property name="receives_default">False</property>
<property name="use_underline">True</property>
- <signal name="clicked" handler="new_folder_button_clicked" swapped="no"/>
- <style>
- <class name="image-button"/>
- </style>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="icon-name">list-add-symbolic</property>
- <property name="icon-size">1</property>
- </object>
- </child>
+ <property name="popover">new_folder_popover</property>
+ <signal name="notify::active" handler="new_folder_popover_active"/>
</object>
<packing>
<property name="expand">False</property>
@@ -372,4 +363,68 @@
<widget name="browse_new_folder_button"/>
</widgets>
</object>
+ <object class="GtkPopover" id="new_folder_popover">
+ <property name="modal">True</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="margin">10</property>
+ <property name="column-spacing">6</property>
+ <property name="row-spacing">10</property>
+ <property name="row-homogeneous">True</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Name</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">horizontal</property>
+ <style>
+ <class name="linked"/>
+ </style>
+ <child>
+ <object class="GtkEntry" id="new_folder_name_entry">
+ <property name="visible">True</property>
+ <signal name="changed" handler="new_folder_name_changed"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="new_folder_create_button">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="label" translatable="yes">_Create</property>
+ <property name="use_underline">True</property>
+ <signal name="clicked" handler="new_folder_create_clicked"/>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="new_folder_error_label">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]