+/* Saves the widgets around the pathbar so they can be reparented later
+ * in the correct place. This function must be called paired with
+ * restore_path_bar().
+ */
+static void
+save_path_bar (GtkFileChooserDefault *impl)
+{
+ GtkWidget *parent;
+
+ g_object_ref (impl->browse_path_bar_hbox);
+
+ parent = gtk_widget_get_parent (impl->browse_path_bar_hbox);
+ if (parent)
+ gtk_container_remove (GTK_CONTAINER (parent), impl->browse_path_bar_hbox);
+}
+
+/* Reparents the path bar and the "Create folder" button to the right place:
+ * Above the file list in Open mode, or to the right of the "Save in folder:"
+ * label in Save mode. The save_path_bar() function must be called before this
+ * one.
+ */
+static void
+restore_path_bar (GtkFileChooserDefault *impl)
+{
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ {
+ gtk_box_pack_start (GTK_BOX (impl->browse_header_box), impl->browse_path_bar_hbox, FALSE, FALSE, 0);
+ gtk_box_reorder_child (GTK_BOX (impl->browse_header_box), impl->browse_path_bar_hbox, 0);
+ }
+ else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ {
+ gtk_widget_set_hexpand (impl->browse_path_bar_hbox, TRUE);
+ gtk_grid_attach (GTK_GRID (impl->save_widgets_table), impl->browse_path_bar_hbox, 1, 1, 1, 1);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (impl->save_folder_label), impl->browse_path_bar);
+ }
+ else
+ g_assert_not_reached ();
+
+ g_object_unref (impl->browse_path_bar_hbox);
+}
+
+/* Takes the folder stored in a row in the recent_model, and puts it in the pathbar */
+static void
+put_recent_folder_in_pathbar (GtkFileChooserDefault *impl, GtkTreeIter *iter)
+{
+ GFile *file;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), iter,
+ MODEL_COL_FILE, &file,
+ -1);
+ _gtk_path_bar_set_file (GTK_PATH_BAR (impl->browse_path_bar), file, FALSE);
+ g_object_unref (file);
+}
+
+/* Sets the pathbar in the appropriate mode according to the current operation mode and action. This is the central function for
+ * dealing with the pathbar's widgets; as long as impl->action and impl->operation_mode are set correctly, then calling this
+ * function will update all the pathbar's widgets.
+ */
+static void
+path_bar_update (GtkFileChooserDefault *impl)
+{
+ PathBarMode mode;
+
+ switch (impl->operation_mode)
+ {
+ case OPERATION_MODE_BROWSE:
+ mode = PATH_BAR_FOLDER_PATH;
+ break;
+
+ case OPERATION_MODE_RECENT:
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ {
+ GtkTreeSelection *selection;
+ gboolean have_selected;
+ GtkTreeIter iter;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+
+ /* Save mode means single-selection mode, so the following is valid */
+ have_selected = gtk_tree_selection_get_selected (selection, NULL, &iter);
+
+ if (have_selected)
+ {
+ mode = PATH_BAR_FOLDER_PATH;
+ put_recent_folder_in_pathbar (impl, &iter);
+ }
+ else
+ mode = PATH_BAR_SELECT_A_FOLDER;
+ }
+ else
+ mode = PATH_BAR_RECENTLY_USED;
+
+ break;
+
+ case OPERATION_MODE_SEARCH:
+ mode = PATH_BAR_SEARCH;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ return;
+ }
+
+ path_bar_set_mode (impl, mode);
+}
+
+static void
+operation_mode_discard_search_widgets (GtkFileChooserDefault *impl)
+{
+ if (impl->search_hbox)
+ {
+ gtk_widget_destroy (impl->search_hbox);
+
+ impl->search_hbox = NULL;
+ impl->search_entry = NULL;
+ }
+}
+
+/* Stops running operations like populating the browse model, searches, and the recent-files model */
+static void
+operation_mode_stop (GtkFileChooserDefault *impl, OperationMode mode)
+{
+ switch (mode)
+ {
+ case OPERATION_MODE_BROWSE:
+ stop_loading_and_clear_list_model (impl, TRUE);
+ break;
+
+ case OPERATION_MODE_SEARCH:
+ search_stop_searching (impl, FALSE);
+ search_clear_model (impl, TRUE);
+
+ operation_mode_discard_search_widgets (impl);
+ break;
+
+ case OPERATION_MODE_RECENT:
+ recent_stop_loading (impl);
+ recent_clear_model (impl, TRUE);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+operation_mode_set_browse (GtkFileChooserDefault *impl)
+{
+ path_bar_update (impl);
+
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ {
+ gtk_widget_show (impl->location_button);
+ location_mode_set (impl, impl->location_mode, TRUE);
+
+ if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
+ gtk_widget_show (impl->location_entry_box);
+ }
+}
+
+static void
+operation_mode_set_search (GtkFileChooserDefault *impl)
+{
+ g_assert (impl->search_hbox == NULL);
+ g_assert (impl->search_entry == NULL);
+ g_assert (impl->search_model == NULL);
+
+ search_setup_widgets (impl);
+}
+
+static void
+operation_mode_set_recent (GtkFileChooserDefault *impl)
+{
+ path_bar_update (impl);
+
+ /* Hide the location widgets temporarily */
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ {
+ gtk_widget_hide (impl->location_button);
+ gtk_widget_hide (impl->location_entry_box);
+ }
+
+ recent_start_loading (impl);
+}
+
+/* Sometimes we need to frob the selection in the shortcuts list manually */
+static void
+shortcuts_select_item_without_activating (GtkFileChooserDefault *impl, int pos)
+{
+ GtkTreeSelection *selection;
+ GtkTreePath *path;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
+
+ g_signal_handlers_block_by_func (selection, G_CALLBACK (shortcuts_selection_changed_cb), impl);
+
+ path = gtk_tree_path_new_from_indices (pos, -1);
+ gtk_tree_selection_select_path (selection, path);
+ gtk_tree_path_free (path);
+
+ g_signal_handlers_unblock_by_func (selection, G_CALLBACK (shortcuts_selection_changed_cb), impl);
+}
+
+static void
+operation_mode_set (GtkFileChooserDefault *impl, OperationMode mode)
+{
+ ShortcutsIndex shortcut_to_select;
+
+ operation_mode_stop (impl, impl->operation_mode);
+
+ impl->operation_mode = mode;
+
+ switch (impl->operation_mode)
+ {
+ case OPERATION_MODE_BROWSE:
+ operation_mode_set_browse (impl);
+ shortcut_to_select = SHORTCUTS_CURRENT_FOLDER;
+ break;
+
+ case OPERATION_MODE_SEARCH:
+ operation_mode_set_search (impl);
+ shortcut_to_select = SHORTCUTS_SEARCH;
+ break;
+
+ case OPERATION_MODE_RECENT:
+ operation_mode_set_recent (impl);
+ shortcut_to_select = SHORTCUTS_RECENT;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ return;
+ }
+
+ if (shortcut_to_select != SHORTCUTS_CURRENT_FOLDER)
+ shortcuts_select_item_without_activating (impl, shortcuts_get_index (impl, shortcut_to_select));
+}
+