summaryrefslogtreecommitdiff
path: root/gtk/gtkfilechooserdefault.c
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@ximian.com>2004-03-05 00:10:59 +0000
committerFederico Mena Quintero <federico@src.gnome.org>2004-03-05 00:10:59 +0000
commitd64c7c08a8e742158d49a129f8b68215dd8d2eff (patch)
tree8b208d81b5b5219737efd74e1f8446ffe3b02c48 /gtk/gtkfilechooserdefault.c
parent1810dba3384c18152bf9993467acbf8f36528312 (diff)
downloadgtk+-d64c7c08a8e742158d49a129f8b68215dd8d2eff.tar.gz
New handler. Ask the GtkFileChooser widget if it wants to do something
2004-03-04 Federico Mena Quintero <federico@ximian.com> * gtk/gtkfilechooserdialog.c (response_cb): New handler. Ask the GtkFileChooser widget if it wants to do something special rather than letting us terminate the dialog. (gtk_file_chooser_dialog_init): Connect to "response"; see the comment in the sources to see why we don't override the method in class_init. * gtk/gtkfilechooserembed.h (struct _GtkFileChooserEmbedIface): Added a ::should_respond() method. * gtk/gtkfilechooserembed.c (_gtk_file_chooser_embed_delegate_iface_init): Add a delegate for ::should_respond(). (delegate_should_respond): New delegate. (_gtk_file_chooser_embed_should_respond): New function. * gtk/gtkfilechooserdefault.c (set_list_model, create_file_list): Use dashes in signal names rather than underscores. (gtk_file_chooser_default_init): Hook up our ::should_respond() implementation. (gtk_file_chooser_default_should_respond): Implement. go into a folder rather than responding if we are in File mode and the selected file is a folder. (get_selection): New helper function. (add_bookmark_button_clicked_cb): Use get_selection(). (bookmarks_check_add_sensitivity): Likewise. (gtk_file_chooser_default_get_paths): Likewise. (check_save_entry): New helper function. (gtk_file_chooser_default_get_paths): Use check_save_entry(). (selection_check): Renamed from selection_is_folders(). Now checks whether the selection is empty, all files, all folders. (bookmarks_check_add_sensitivity): Use selection_check().
Diffstat (limited to 'gtk/gtkfilechooserdefault.c')
-rw-r--r--gtk/gtkfilechooserdefault.c326
1 files changed, 253 insertions, 73 deletions
diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c
index 19147dc361..c5188a47ad 100644
--- a/gtk/gtkfilechooserdefault.c
+++ b/gtk/gtkfilechooserdefault.c
@@ -267,12 +267,14 @@ static gboolean gtk_file_chooser_default_remove_shortcut_folder (GtkFileCh
const GtkFilePath *path,
GError **error);
static GSList * gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser);
+
static void gtk_file_chooser_default_get_default_size (GtkFileChooserEmbed *chooser_embed,
gint *default_width,
gint *default_height);
static void gtk_file_chooser_default_get_resizable_hints (GtkFileChooserEmbed *chooser_embed,
gboolean *resize_horizontally,
gboolean *resize_vertically);
+static gboolean gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed);
static void location_popup_handler (GtkFileChooserDefault *impl);
static void up_folder_handler (GtkFileChooserDefault *impl);
@@ -502,6 +504,7 @@ gtk_file_chooser_embed_default_iface_init (GtkFileChooserEmbedIface *iface)
{
iface->get_default_size = gtk_file_chooser_default_get_default_size;
iface->get_resizable_hints = gtk_file_chooser_default_get_resizable_hints;
+ iface->should_respond = gtk_file_chooser_default_should_respond;
}
static void
gtk_file_chooser_default_init (GtkFileChooserDefault *impl)
@@ -1432,6 +1435,21 @@ shortcuts_add_bookmark_from_path (GtkFileChooserDefault *impl,
}
}
+/* Returns the GtkTreeSelection that makes sense for the mode which the file chooser is in */
+static GtkTreeSelection *
+get_selection (GtkFileChooserDefault *impl)
+{
+ GtkWidget *tree_view;
+
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
+ impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ tree_view = impl->browse_directories_tree_view;
+ else
+ tree_view = impl->browse_files_tree_view;
+
+ return gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+}
+
static void
add_bookmark_foreach_cb (GtkTreeModel *model,
GtkTreePath *path,
@@ -1466,16 +1484,10 @@ static void
add_bookmark_button_clicked_cb (GtkButton *button,
GtkFileChooserDefault *impl)
{
- GtkWidget *tree_view;
GtkTreeSelection *selection;
- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
- tree_view = impl->browse_directories_tree_view;
- else
- tree_view = impl->browse_files_tree_view;
+ selection = get_selection (impl);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
if (gtk_tree_selection_count_selected_rows (selection) == 0)
shortcuts_add_bookmark_from_path (impl, impl->current_folder);
else
@@ -1517,46 +1529,86 @@ remove_bookmark_button_clicked_cb (GtkButton *button,
}
}
-struct is_folders_foreach_closure {
+struct selection_check_closure {
GtkFileChooserDefault *impl;
+ gboolean empty;
+ gboolean all_files;
gboolean all_folders;
};
/* Used from gtk_tree_selection_selected_foreach() */
static void
-is_folders_foreach_cb (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
+selection_check_foreach_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
{
- struct is_folders_foreach_closure *closure;
+ struct selection_check_closure *closure;
GtkTreeIter child_iter;
const GtkFileInfo *info;
+ gboolean is_folder;
closure = data;
+ closure->empty = FALSE;
gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter);
info = _gtk_file_system_model_get_info (closure->impl->browse_files_model, &child_iter);
- closure->all_folders &= gtk_file_info_get_is_folder (info);
+ is_folder = gtk_file_info_get_is_folder (info);
+
+ closure->all_folders &= is_folder;
+ closure->all_files &= !is_folder;
}
-/* Returns whether the selected items in the file list are all folders */
-static gboolean
-selection_is_folders (GtkFileChooserDefault *impl)
+/* Checks whether the selected items in the file list are all files or all folders */
+static void
+selection_check (GtkFileChooserDefault *impl,
+ gboolean *empty,
+ gboolean *all_files,
+ gboolean *all_folders)
{
- struct is_folders_foreach_closure closure;
+ struct selection_check_closure closure;
GtkTreeSelection *selection;
- closure.impl = impl;
- closure.all_folders = TRUE;
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ {
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_directories_tree_view));
+ if (gtk_tree_selection_count_selected_rows (selection) == 0)
+ closure.empty = TRUE;
+ else
+ {
+ closure.empty = FALSE;
+ closure.all_files = FALSE;
+ closure.all_folders = TRUE;
+ }
+ }
+ else
+ {
+ g_assert (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
+ || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- gtk_tree_selection_selected_foreach (selection,
- is_folders_foreach_cb,
- &closure);
+ closure.impl = impl;
+ closure.empty = TRUE;
+ closure.all_files = TRUE;
+ closure.all_folders = TRUE;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+ gtk_tree_selection_selected_foreach (selection,
+ selection_check_foreach_cb,
+ &closure);
+ }
- return closure.all_folders;
+ g_assert (closure.empty || !(closure.all_files && closure.all_folders));
+
+ if (empty)
+ *empty = closure.empty;
+
+ if (all_files)
+ *all_files = closure.all_files;
+
+ if (all_folders)
+ *all_folders = closure.all_folders;
}
/* Sensitize the "add bookmark" button if all the selected items are folders, or
@@ -1566,26 +1618,24 @@ selection_is_folders (GtkFileChooserDefault *impl)
static void
bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl)
{
- GtkWidget *tree_view;
GtkTreeSelection *selection;
gboolean active;
/* Check selection */
- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
- tree_view = impl->browse_directories_tree_view;
- else
- tree_view = impl->browse_files_tree_view;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+ selection = get_selection (impl);
if (gtk_tree_selection_count_selected_rows (selection) == 0)
active = (shortcut_find_position (impl, impl->current_folder) == -1);
else
- active = (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER ||
- selection_is_folders (impl));
+ {
+ gboolean all_folders;
+
+ selection_check (impl, NULL, NULL, &all_folders);
+ active = (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
+ impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER ||
+ all_folders);
+ }
gtk_widget_set_sensitive (impl->browse_shortcuts_add_button, active);
}
@@ -1833,7 +1883,7 @@ create_file_list (GtkFileChooserDefault *impl)
impl->browse_files_tree_view = gtk_tree_view_new ();
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (impl->browse_files_tree_view), TRUE);
gtk_container_add (GTK_CONTAINER (impl->browse_files_swin), impl->browse_files_tree_view);
- g_signal_connect (impl->browse_files_tree_view, "row_activated",
+ g_signal_connect (impl->browse_files_tree_view, "row-activated",
G_CALLBACK (list_row_activated), impl);
gtk_widget_show (impl->browse_files_tree_view);
@@ -2744,7 +2794,7 @@ set_list_model (GtkFileChooserDefault *impl)
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->sort_model), FILE_LIST_COL_NAME, GTK_SORT_ASCENDING);
impl->list_sort_ascending = TRUE;
- g_signal_connect (impl->sort_model, "sort_column_changed",
+ g_signal_connect (impl->sort_model, "sort-column-changed",
G_CALLBACK (list_sort_column_changed_cb), impl);
gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
@@ -3001,6 +3051,44 @@ gtk_file_chooser_default_unselect_all (GtkFileChooser *chooser)
gtk_tree_selection_unselect_all (selection);
}
+/* Checks whether the filename entry for the Save modes contains a valid filename */
+static GtkFilePath *
+check_save_entry (GtkFileChooserDefault *impl,
+ gboolean *is_valid,
+ gboolean *is_empty)
+{
+ const char *filename;
+ GtkFilePath *path;
+ GError *error;
+
+ g_assert (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
+
+ filename = gtk_entry_get_text (GTK_ENTRY (impl->save_file_name_entry));
+
+ if (!filename || filename[0] == '\0')
+ {
+ *is_valid = FALSE;
+ *is_empty = TRUE;
+ return NULL;
+ }
+
+ *is_empty = FALSE;
+
+ error = NULL;
+ path = gtk_file_system_make_path (impl->file_system, impl->current_folder, filename, &error);
+
+ if (!path)
+ {
+ error_building_filename_dialog (impl, impl->current_folder, filename, error);
+ *is_valid = FALSE;
+ return NULL;
+ }
+
+ *is_valid = TRUE;
+ return path;
+}
+
struct get_paths_closure {
GtkFileChooserDefault *impl;
GSList *result;
@@ -3049,49 +3137,22 @@ gtk_file_chooser_default_get_paths (GtkFileChooser *chooser)
info.result = NULL;
info.path_from_entry = NULL;
- if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
- const char *filename;
-
- filename = gtk_entry_get_text (GTK_ENTRY (impl->save_file_name_entry));
-
- if (filename != NULL && filename[0] != '\0')
- {
- GtkFilePath *selected;
- GError *error = NULL;
-
- selected = gtk_file_system_make_path (impl->file_system, impl->current_folder, filename, &error);
+ gboolean is_valid, is_empty;
- if (!selected)
- {
- error_building_filename_dialog (impl, impl->current_folder, filename, error);
- return NULL;
- }
-
- info.path_from_entry = selected;
- }
+ info.path_from_entry = check_save_entry (impl, &is_valid, &is_empty);
+ if (!is_valid && !is_empty)
+ return NULL;
}
if (!info.path_from_entry || impl->select_multiple)
{
GtkTreeSelection *selection;
- selection = NULL;
-
- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
- {
- if (impl->browse_directories_model)
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_directories_tree_view));
- }
- else
- {
- if (impl->sort_model)
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- }
-
- if (selection)
- gtk_tree_selection_selected_foreach (selection, get_paths_foreach, &info);
+ selection = get_selection (impl);
+ gtk_tree_selection_selected_foreach (selection, get_paths_foreach, &info);
}
if (info.path_from_entry)
@@ -3394,6 +3455,125 @@ gtk_file_chooser_default_get_resizable_hints (GtkFileChooserEmbed *chooser_embed
}
}
+struct switch_folder_closure {
+ GtkFileChooserDefault *impl;
+ const GtkFilePath *path;
+ int num_selected;
+};
+
+/* Used from gtk_tree_selection_selected_foreach() in switch_to_selected_folder() */
+static void
+switch_folder_foreach_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ struct switch_folder_closure *closure;
+ GtkTreeIter child_iter;
+
+ closure = data;
+
+ gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter);
+
+ closure->path = _gtk_file_system_model_get_path (closure->impl->browse_files_model, &child_iter);
+ closure->num_selected++;
+}
+
+/* Changes to the selected folder in the list view */
+static void
+switch_to_selected_folder (GtkFileChooserDefault *impl)
+{
+ GtkTreeSelection *selection;
+ struct switch_folder_closure closure;
+
+ g_assert (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
+ || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE);
+
+ /* We do this with foreach() rather than get_selected() as we may be in
+ * multiple selection mode
+ */
+
+ closure.impl = impl;
+ closure.path = NULL;
+ closure.num_selected = 0;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+ gtk_tree_selection_selected_foreach (selection, switch_folder_foreach_cb, &closure);
+
+ g_assert (closure.path && closure.num_selected == 1);
+
+ _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (impl), closure.path);
+}
+
+/* Implementation for GtkFileChooserEmbed::should_respond() */
+static gboolean
+gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
+{
+ GtkFileChooserDefault *impl;
+ GtkTreeSelection *selection;
+ int num_selected;
+
+ impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
+
+ /* First, check the save entry. If it has a valid name, we are done */
+
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ {
+ GtkFilePath *path;
+ gboolean is_valid, is_empty;
+
+ path = check_save_entry (impl, &is_valid, &is_empty);
+
+ if (is_valid)
+ {
+ gtk_file_path_free (path);
+ return TRUE;
+ }
+ else if (!is_empty)
+ return FALSE;
+ }
+
+ /* Second, do we have an empty selection? */
+
+ selection = get_selection (impl);
+ num_selected = gtk_tree_selection_count_selected_rows (selection);
+ if (num_selected == 0)
+ return FALSE;
+
+ /* Third, should we return file names or folder names? */
+
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
+ || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ {
+ gboolean all_files, all_folders;
+
+ selection_check (impl, NULL, &all_files, &all_folders);
+
+ if (num_selected == 1)
+ {
+ if (all_folders)
+ {
+ switch_to_selected_folder (impl);
+ return FALSE;
+ }
+ else if (all_files)
+ return TRUE;
+ }
+ else
+ return all_files;
+ }
+ else if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ /* There can be no files selected in folder mode since we don't show them,
+ * anyway.
+ */
+ return TRUE;
+
+ g_assert_not_reached ();
+ return FALSE;
+}
+
static void
set_current_filter (GtkFileChooserDefault *impl,
GtkFileFilter *filter)