[gtk+/wip/matthiasc/pathbar-in-header: 3/3] wip: external path bar for file chooser
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/matthiasc/pathbar-in-header: 3/3] wip: external path bar for file chooser
- Date: Wed, 17 Jun 2015 14:01:59 +0000 (UTC)
commit b7513c8b63338a526bf7a0cd269654d7dcafe945
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Jun 17 09:57:20 2015 -0400
wip: external path bar for file chooser
gtk/gtkfilechooserdialog.c | 43 +++++++++
gtk/gtkfilechooserwidget.c | 173 +++++++++++++++++++++++++++++--------
gtk/gtkfilechooserwidgetprivate.h | 36 ++++++++
3 files changed, 217 insertions(+), 35 deletions(-)
---
diff --git a/gtk/gtkfilechooserdialog.c b/gtk/gtkfilechooserdialog.c
index 29fbb48..d65f6c5 100644
--- a/gtk/gtkfilechooserdialog.c
+++ b/gtk/gtkfilechooserdialog.c
@@ -34,6 +34,10 @@
#include "gtkstylecontext.h"
#include "gtkheaderbar.h"
#include "gtkdialogprivate.h"
+#include "gtkpathbar.h"
+#include "gtkfilechooserentry.h"
+#include "gtkfilechooserwidgetprivate.h"
+#include "gtkstack.h"
#include <stdarg.h>
@@ -206,6 +210,8 @@ struct _GtkFileChooserDialogPrivate
/* for use with GtkFileChooserEmbed */
gboolean response_requested;
gboolean search_setup;
+
+ gboolean path_bar_setup;
};
static void gtk_file_chooser_dialog_set_property (GObject *object,
@@ -523,6 +529,42 @@ setup_search (GtkFileChooserDialog *dialog)
}
static void
+setup_path_bar (GtkFileChooserDialog *dialog)
+{
+ gboolean use_header;
+
+ if (dialog->priv->path_bar_setup)
+ return;
+
+ dialog->priv->path_bar_setup = TRUE;
+
+ g_object_get (dialog, "use-header-bar", &use_header, NULL);
+ if (use_header)
+ {
+ GtkWidget *stack;
+ GtkWidget *path_bar;
+ GtkWidget *entry;
+ GtkWidget *header;
+
+ stack = gtk_stack_new ();
+ path_bar = (GtkWidget *) g_object_new (GTK_TYPE_PATH_BAR, NULL);
+ entry = _gtk_file_chooser_entry_new (TRUE);
+
+ gtk_stack_add_named (GTK_STACK (stack), path_bar, "pathbar");
+ gtk_stack_add_named (GTK_STACK (stack), entry, "location");
+
+ gtk_widget_show_all (stack);
+
+ header = gtk_dialog_get_header_bar (GTK_DIALOG (dialog));
+ gtk_header_bar_pack_start (GTK_HEADER_BAR (header), stack);
+
+ gtk_file_chooser_widget_set_external_controls (GTK_FILE_CHOOSER_WIDGET (dialog->priv->widget),
+ path_bar,
+ entry);
+ }
+}
+
+static void
ensure_default_response (GtkFileChooserDialog *dialog)
{
GtkWidget *widget;
@@ -540,6 +582,7 @@ gtk_file_chooser_dialog_map (GtkWidget *widget)
GtkFileChooserDialogPrivate *priv = dialog->priv;
setup_search (dialog);
+ setup_path_bar (dialog);
ensure_default_response (dialog);
_gtk_file_chooser_embed_initial_focus (GTK_FILE_CHOOSER_EMBED (priv->widget));
diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c
index 259b6f5..1fa73dc 100644
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -25,6 +25,7 @@
#include "config.h"
#include "gtkfilechooserwidget.h"
+#include "gtkfilechooserwidgetprivate.h"
#include "gtkbindings.h"
#include "gtkbutton.h"
@@ -266,6 +267,10 @@ struct _GtkFileChooserWidgetPrivate {
GtkWidget *location_entry;
LocationMode location_mode;
+ GtkWidget *external_path_bar;
+ GtkWidget *external_location_entry;
+ GtkWidget *external_path_bar_stack;
+
/* Handles */
GCancellable *file_list_drag_data_received_cancellable;
GCancellable *update_current_folder_cancellable;
@@ -2034,6 +2039,22 @@ location_entry_changed_cb (GtkEditable *editable,
}
static void
+setup_location_entry (GtkFileChooserWidget *impl,
+ GtkWidget *entry)
+{
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ gtk_entry_set_placeholder_text (GTK_ENTRY (entry), _("Location"));
+
+ _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (entry), priv->local_only);
+ _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (entry), priv->action);
+ gtk_entry_set_width_chars (GTK_ENTRY (entry), 45);
+ gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
+}
+
+static void
location_entry_create (GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = impl->priv;
@@ -2041,18 +2062,11 @@ location_entry_create (GtkFileChooserWidget *impl)
if (!priv->location_entry)
{
priv->location_entry = _gtk_file_chooser_entry_new (TRUE);
- if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
- gtk_entry_set_placeholder_text (GTK_ENTRY (priv->location_entry), _("Location"));
-
g_signal_connect (priv->location_entry, "changed",
G_CALLBACK (location_entry_changed_cb), impl);
}
- _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->local_only);
- _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->action);
- gtk_entry_set_width_chars (GTK_ENTRY (priv->location_entry), 45);
- gtk_entry_set_activates_default (GTK_ENTRY (priv->location_entry), TRUE);
+ setup_location_entry (impl, priv->location_entry);
}
/* Creates the widgets specific to Save mode */
@@ -2125,6 +2139,12 @@ location_switch_to_path_bar (GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = impl->priv;
+ if (priv->external_path_bar)
+ {
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->external_path_bar_stack), "pathbar");
+ return;
+ }
+
if (priv->location_entry)
{
gtk_widget_destroy (priv->location_entry);
@@ -2150,6 +2170,14 @@ location_switch_to_filename_entry (GtkFileChooserWidget *impl)
priv->operation_mode == OPERATION_MODE_RECENT)
return;
+ if (priv->external_path_bar)
+ {
+ _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (priv->external_location_entry),
priv->current_folder);
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->external_path_bar_stack), "location");
+ gtk_widget_grab_focus (priv->external_location_entry);
+ return;
+ }
+
gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), TRUE);
if (!priv->location_entry)
@@ -2419,6 +2447,9 @@ put_recent_folder_in_pathbar (GtkFileChooserWidget *impl, GtkTreeIter *iter)
gtk_tree_model_get (GTK_TREE_MODEL (priv->recent_model), iter,
MODEL_COL_FILE, &file,
-1);
+ if (priv->external_path_bar)
+ _gtk_path_bar_set_file (GTK_PATH_BAR (priv->external_path_bar), file, FALSE);
+
_gtk_path_bar_set_file (GTK_PATH_BAR (priv->browse_path_bar), file, FALSE);
g_object_unref (file);
}
@@ -2518,8 +2549,16 @@ operation_mode_set_enter_location (GtkFileChooserWidget *impl)
GtkFileChooserWidgetPrivate *priv = impl->priv;
gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_files_stack), "list");
- gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_header_stack), "location");
- gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), TRUE);
+ if (priv->external_path_bar)
+ {
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->external_path_bar_stack), "location");
+ gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), FALSE);
+ }
+ else
+ {
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_header_stack), "location");
+ gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), TRUE);
+ }
location_bar_update (impl);
gtk_widget_set_sensitive (priv->filter_combo, TRUE);
location_mode_set (impl, LOCATION_MODE_FILENAME_ENTRY);
@@ -2532,8 +2571,16 @@ operation_mode_set_browse (GtkFileChooserWidget *impl)
GtkFileChooserWidgetPrivate *priv = impl->priv;
gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_files_stack), "list");
- gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_header_stack), "pathbar");
- gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), TRUE);
+ if (priv->external_path_bar)
+ {
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->external_path_bar_stack), "pathbar");
+ gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), FALSE);
+ }
+ else
+ {
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_header_stack), "pathbar");
+ gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), TRUE);
+ }
location_bar_update (impl);
gtk_widget_set_sensitive (priv->filter_combo, TRUE);
gtk_tree_view_column_set_visible (priv->list_location_column, FALSE);
@@ -2548,6 +2595,8 @@ operation_mode_set_search (GtkFileChooserWidget *impl)
g_assert (priv->search_model == NULL);
gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_files_stack), "list");
+ if (priv->external_path_bar)
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->external_path_bar_stack), "pathbar");
gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_header_stack), "search");
gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), TRUE);
location_bar_update (impl);
@@ -2572,7 +2621,10 @@ operation_mode_set_recent (GtkFileChooserWidget *impl)
GFile *file;
gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_files_stack), "list");
- gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_header_stack), "pathbar");
+ if (priv->external_path_bar)
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->external_path_bar_stack), "pathbar");
+ else
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_header_stack), "pathbar");
gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), FALSE);
location_bar_update (impl);
recent_start_loading (impl);
@@ -4536,6 +4588,9 @@ update_current_folder_get_info_cb (GCancellable *cancellable,
if (! _gtk_file_info_consider_as_directory (info))
goto out;
+ if (priv->external_path_bar)
+ _gtk_path_bar_set_file (GTK_PATH_BAR (priv->external_path_bar), data->file, data->keep_trail);
+
_gtk_path_bar_set_file (GTK_PATH_BAR (priv->browse_path_bar), data->file, data->keep_trail);
if (priv->current_folder != data->file)
@@ -4828,7 +4883,8 @@ gtk_file_chooser_widget_unselect_all (GtkFileChooser *chooser)
* the path will be “$cwd/foobar”)
*/
static void
-check_save_entry (GtkFileChooserWidget *impl,
+check_save_entry (GtkFileChooserWidget *impl,
+ GtkWidget *entry,
GFile **file_ret,
gboolean *is_well_formed_ret,
gboolean *is_empty_ret,
@@ -4836,7 +4892,7 @@ check_save_entry (GtkFileChooserWidget *impl,
gboolean *is_folder)
{
GtkFileChooserWidgetPrivate *priv = impl->priv;
- GtkFileChooserEntry *chooser_entry;
+ GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (entry);
GFile *current_folder;
const char *file_part;
GFile *file;
@@ -4848,9 +4904,7 @@ check_save_entry (GtkFileChooserWidget *impl,
|| priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
&& priv->location_mode == LOCATION_MODE_FILENAME_ENTRY));
- chooser_entry = GTK_FILE_CHOOSER_ENTRY (priv->location_entry);
-
- if (strlen (gtk_entry_get_text (GTK_ENTRY (chooser_entry))) == 0)
+ if (strlen (gtk_entry_get_text (GTK_ENTRY (entry))) == 0)
{
*file_ret = NULL;
*is_well_formed_ret = TRUE;
@@ -4990,13 +5044,20 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
if (info.result == NULL && priv->location_entry)
goto file_entry;
}
- else if (priv->location_entry && current_focus == priv->location_entry)
+ else if ((priv->location_entry && current_focus == priv->location_entry) ||
+ (priv->external_location_entry && current_focus == priv->external_location_entry))
{
gboolean is_well_formed, is_empty, is_file_part_empty, is_folder;
+ GtkWidget *entry;
file_entry:
- check_save_entry (impl, &info.file_from_entry, &is_well_formed, &is_empty, &is_file_part_empty,
&is_folder);
+ if (priv->external_location_entry)
+ entry = priv->external_location_entry;
+ else
+ entry = priv->location_entry;
+
+ check_save_entry (impl, entry, &info.file_from_entry, &is_well_formed, &is_empty, &is_file_part_empty,
&is_folder);
if (is_empty)
goto out;
@@ -5012,14 +5073,15 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
if (info.file_from_entry)
info.result = g_slist_prepend (info.result, info.file_from_entry);
- else if (!file_list_seen)
+ else if (!file_list_seen)
goto file_list;
else
return NULL;
}
else if (priv->toplevel_last_focus_widget == priv->browse_files_tree_view)
goto file_list;
- else if (priv->location_entry && priv->toplevel_last_focus_widget == priv->location_entry)
+ else if ((priv->location_entry && priv->toplevel_last_focus_widget == priv->location_entry) ||
+ (priv->external_location_entry && priv->toplevel_last_focus_widget ==
priv->external_location_entry))
goto file_entry;
else
{
@@ -5028,7 +5090,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
goto file_entry;
else
- goto file_list;
+ goto file_list;
}
out:
@@ -5913,12 +5975,13 @@ gtk_file_chooser_widget_should_respond (GtkFileChooserEmbed *chooser_embed)
g_assert_not_reached ();
}
}
- else if ((priv->location_entry != NULL) && (current_focus == priv->location_entry))
+ else if (((priv->location_entry != NULL) && (current_focus == priv->location_entry)) ||
+ ((priv->external_location_entry != NULL) && (current_focus == priv->external_location_entry)))
{
GFile *file;
gboolean is_well_formed, is_empty, is_file_part_empty;
gboolean is_folder;
- GtkFileChooserEntry *entry;
+ GtkWidget *entry;
GError *error;
save_entry:
@@ -5929,8 +5992,12 @@ gtk_file_chooser_widget_should_respond (GtkFileChooserEmbed *chooser_embed)
|| priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
&& priv->location_mode == LOCATION_MODE_FILENAME_ENTRY));
- entry = GTK_FILE_CHOOSER_ENTRY (priv->location_entry);
- check_save_entry (impl, &file, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder);
+ if (priv->external_location_entry)
+ entry = priv->external_location_entry;
+ else
+ entry = priv->location_entry;
+
+ check_save_entry (impl, entry, &file, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder);
if (!is_well_formed)
{
@@ -5959,7 +6026,7 @@ gtk_file_chooser_widget_should_respond (GtkFileChooserEmbed *chooser_embed)
|| priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
/* FIXME: ERROR_NO_FILENAME */
- gtk_widget_grab_focus (priv->location_entry);
+ gtk_widget_grab_focus (entry);
return FALSE;
}
@@ -6002,7 +6069,7 @@ gtk_file_chooser_widget_should_respond (GtkFileChooserEmbed *chooser_embed)
data = g_new0 (struct FileExistsData, 1);
data->impl = g_object_ref (impl);
data->file = g_object_ref (file);
- data->parent_file = _gtk_file_chooser_entry_get_current_folder (entry);
+ data->parent_file = _gtk_file_chooser_entry_get_current_folder (GTK_FILE_CHOOSER_ENTRY (entry));
if (priv->file_exists_get_info_cancellable)
g_cancellable_cancel (priv->file_exists_get_info_cancellable);
@@ -7023,6 +7090,9 @@ up_folder_handler (GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = impl->priv;
+ if (priv->external_path_bar)
+ _gtk_path_bar_up (GTK_PATH_BAR (priv->external_path_bar));
+
_gtk_path_bar_up (GTK_PATH_BAR (priv->browse_path_bar));
}
@@ -7032,6 +7102,9 @@ down_folder_handler (GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = impl->priv;
+ if (priv->external_path_bar)
+ _gtk_path_bar_down (GTK_PATH_BAR (priv->external_path_bar));
+
_gtk_path_bar_down (GTK_PATH_BAR (priv->browse_path_bar));
}
@@ -7547,12 +7620,24 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
}
static void
+setup_path_bar (GtkFileChooserWidget *impl,
+ GtkWidget *path_bar)
+{
+ GFile *file;
+
+ _gtk_path_bar_set_file_system (GTK_PATH_BAR (path_bar), impl->priv->file_system);
+ file = g_file_new_for_path ("/");
+ _gtk_path_bar_set_file (GTK_PATH_BAR (path_bar), file, FALSE);
+ g_object_unref (file);
+}
+
+
+static void
post_process_ui (GtkFileChooserWidget *impl)
{
GtkTreeSelection *selection;
GtkCellRenderer *cell;
GList *cells;
- GFile *file;
/* Some qdata, qdata can't be set with GtkBuilder */
g_object_set_data (G_OBJECT (impl->priv->browse_files_tree_view), "fmq-name", "file_list");
@@ -7596,11 +7681,7 @@ post_process_ui (GtkFileChooserWidget *impl)
g_list_free (cells);
- /* Set the GtkPathBar file system backend */
- _gtk_path_bar_set_file_system (GTK_PATH_BAR (impl->priv->browse_path_bar), impl->priv->file_system);
- file = g_file_new_for_path ("/");
- _gtk_path_bar_set_file (GTK_PATH_BAR (impl->priv->browse_path_bar), file, FALSE);
- g_object_unref (file);
+ setup_path_bar (impl, impl->priv->browse_path_bar);
/* Set the fixed size icon renderer, this requires
* that priv->icon_size be already setup.
@@ -7610,6 +7691,28 @@ post_process_ui (GtkFileChooserWidget *impl)
gtk_popover_set_default_widget (GTK_POPOVER (impl->priv->new_folder_popover),
impl->priv->new_folder_create_button);
}
+void
+gtk_file_chooser_widget_set_external_controls (GtkFileChooserWidget *impl,
+ GtkWidget *path_bar,
+ GtkWidget *entry)
+{
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+
+ g_return_if_fail (GTK_IS_FILE_CHOOSER_WIDGET (impl));
+ g_return_if_fail (GTK_IS_PATH_BAR (path_bar));
+ g_return_if_fail (GTK_IS_FILE_CHOOSER_ENTRY (entry));
+
+ priv->external_path_bar = path_bar;
+ priv->external_location_entry = entry;
+ priv->external_path_bar_stack = gtk_widget_get_ancestor (path_bar, GTK_TYPE_STACK);
+
+ setup_location_entry (impl, entry);
+ setup_path_bar (impl, path_bar);
+
+ g_signal_connect (path_bar, "path-clicked", G_CALLBACK (path_bar_clicked), impl);
+ g_signal_connect (entry, "changed", G_CALLBACK (location_entry_changed_cb), impl);
+}
+
static void
gtk_file_chooser_widget_init (GtkFileChooserWidget *impl)
{
diff --git a/gtk/gtkfilechooserwidgetprivate.h b/gtk/gtkfilechooserwidgetprivate.h
new file mode 100644
index 0000000..d722ca6
--- /dev/null
+++ b/gtk/gtkfilechooserwidgetprivate.h
@@ -0,0 +1,36 @@
+/* gtkfilechooserwidgetprivate.h
+ *
+ * Copyright (C) 2015 Red Hat
+ *
+ * This file 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 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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 General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Matthias Clasen
+ */
+
+#ifndef __GTK_FILE_CHOOSER_WIDGET_PRIVATE_H__
+#define __GTK_FILE_CHOOSER_WIDGET_PRIVATE_H__
+
+#include <glib.h>
+#include "gtkfilechooserwidget.h"
+
+G_BEGIN_DECLS
+
+void
+gtk_file_chooser_widget_set_external_controls (GtkFileChooserWidget *chooser,
+ GtkWidget *path_bar,
+ GtkWidget *entry);
+
+G_END_DECLS
+
+#endif /* __GTK_FILE_CHOOSER_WIDGET_PRIVATE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]