]> Pileus Git - ~andy/gtk/commitdiff
New handler. Ask the GtkFileChooser widget if it wants to do something
authorFederico Mena Quintero <federico@ximian.com>
Fri, 5 Mar 2004 00:10:59 +0000 (00:10 +0000)
committerFederico Mena Quintero <federico@src.gnome.org>
Fri, 5 Mar 2004 00:10:59 +0000 (00:10 +0000)
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().

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtkfilechooserdefault.c
gtk/gtkfilechooserdialog.c
gtk/gtkfilechooserembed.c
gtk/gtkfilechooserembed.h

index 5ba94bcd68af0fcf27a4a3f223dbaa407298de12..c7a754c7c8ba7236f571cb062c142cea1d986bcf 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+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().
+
 Fri Mar  5 00:05:59 2004  Matthias Clasen  <maclas@gmx.de>
 
        * gtk/gtkcombobox.c (gtk_combo_box_list_setup): 
index 5ba94bcd68af0fcf27a4a3f223dbaa407298de12..c7a754c7c8ba7236f571cb062c142cea1d986bcf 100644 (file)
@@ -1,3 +1,36 @@
+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().
+
 Fri Mar  5 00:05:59 2004  Matthias Clasen  <maclas@gmx.de>
 
        * gtk/gtkcombobox.c (gtk_combo_box_list_setup): 
index 5ba94bcd68af0fcf27a4a3f223dbaa407298de12..c7a754c7c8ba7236f571cb062c142cea1d986bcf 100644 (file)
@@ -1,3 +1,36 @@
+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().
+
 Fri Mar  5 00:05:59 2004  Matthias Clasen  <maclas@gmx.de>
 
        * gtk/gtkcombobox.c (gtk_combo_box_list_setup): 
index 5ba94bcd68af0fcf27a4a3f223dbaa407298de12..c7a754c7c8ba7236f571cb062c142cea1d986bcf 100644 (file)
@@ -1,3 +1,36 @@
+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().
+
 Fri Mar  5 00:05:59 2004  Matthias Clasen  <maclas@gmx.de>
 
        * gtk/gtkcombobox.c (gtk_combo_box_list_setup): 
index 5ba94bcd68af0fcf27a4a3f223dbaa407298de12..c7a754c7c8ba7236f571cb062c142cea1d986bcf 100644 (file)
@@ -1,3 +1,36 @@
+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().
+
 Fri Mar  5 00:05:59 2004  Matthias Clasen  <maclas@gmx.de>
 
        * gtk/gtkcombobox.c (gtk_combo_box_list_setup): 
index 19147dc36175a173fe636ef88576fb4d29965ab8..c5188a47ad7fb3e324bd06371e89b1f507431b7d 100644 (file)
@@ -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)
index 4aa02b93ee8cee3604d61577244639ac7e1810da..0816ef15bc62a9ca3f465aa42512658d7f1773b7 100644 (file)
@@ -61,6 +61,9 @@ static void     gtk_file_chooser_dialog_get_property (GObject               *obj
 static void     gtk_file_chooser_dialog_style_set    (GtkWidget             *widget,
                                                      GtkStyle              *previous_style);
 
+static void response_cb (GtkDialog *dialog,
+                        gint       response_id);
+
 static GObjectClass *parent_class;
 
 GType
@@ -133,6 +136,14 @@ gtk_file_chooser_dialog_init (GtkFileChooserDialog *dialog)
   dialog->priv->resize_vertically = TRUE;
 
   gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+
+  /* We do a signal connection here rather than overriding the method in
+   * class_init because GtkDialog::response is a RUN_LAST signal.  We want *our*
+   * handler to be run *first*, regardless of whether the user installs response
+   * handlers of his own.
+   */
+  g_signal_connect (dialog, "response",
+                   G_CALLBACK (response_cb), NULL);
 }
 
 static void
@@ -441,6 +452,29 @@ gtk_file_chooser_dialog_style_set (GtkWidget *widget,
   gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
 }
 
+/* GtkDialog::response handler */
+static void
+response_cb (GtkDialog *dialog,
+            gint       response_id)
+{
+  GtkFileChooserDialogPrivate *priv;
+
+  priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
+
+  /* Ugh, try to filter out cancel-type responses */
+  if (response_id == GTK_RESPONSE_NONE
+      || response_id == GTK_RESPONSE_REJECT
+      || response_id == GTK_RESPONSE_DELETE_EVENT
+      || response_id == GTK_RESPONSE_CANCEL
+      || response_id == GTK_RESPONSE_CLOSE
+      || response_id == GTK_RESPONSE_NO
+      || response_id == GTK_RESPONSE_HELP)
+    return;
+
+  if (!_gtk_file_chooser_embed_should_respond (GTK_FILE_CHOOSER_EMBED (priv->widget)))
+    g_signal_stop_emission_by_name (dialog, "response");
+}
+
 static GtkWidget *
 gtk_file_chooser_dialog_new_valist (const gchar          *title,
                                    GtkWindow            *parent,
index 61a48fff567f39853c6850550eff0010d681613c..696efc50dffcb3f1d55ab169978180a12b33ae51 100644 (file)
@@ -8,6 +8,7 @@ static void delegate_get_default_size         (GtkFileChooserEmbed *chooser_embe
 static void delegate_get_resizable_hints      (GtkFileChooserEmbed *chooser_embed,
                                               gboolean            *resize_horizontally,
                                               gboolean            *resize_vertically);
+static gboolean delegate_should_respond       (GtkFileChooserEmbed *chooser_embed);
 static void delegate_default_size_changed     (GtkFileChooserEmbed *chooser_embed,
                                               gpointer             data);
 
@@ -31,6 +32,7 @@ _gtk_file_chooser_embed_delegate_iface_init (GtkFileChooserEmbedIface *iface)
 {
   iface->get_default_size = delegate_get_default_size;
   iface->get_resizable_hints = delegate_get_resizable_hints;
+  iface->should_respond = delegate_should_respond;
 }
 
 /**
@@ -74,6 +76,12 @@ delegate_get_resizable_hints (GtkFileChooserEmbed *chooser_embed,
   _gtk_file_chooser_embed_get_resizable_hints (get_delegate (chooser_embed), resize_horizontally, resize_vertically);
 }
 
+static gboolean
+delegate_should_respond (GtkFileChooserEmbed *chooser_embed)
+{
+  return _gtk_file_chooser_embed_should_respond (get_delegate (chooser_embed));
+}
+
 static void
 delegate_default_size_changed (GtkFileChooserEmbed *chooser_embed,
                               gpointer             data)
@@ -135,6 +143,14 @@ _gtk_file_chooser_embed_get_default_size (GtkFileChooserEmbed *chooser_embed,
   GTK_FILE_CHOOSER_EMBED_GET_IFACE (chooser_embed)->get_default_size (chooser_embed, default_width, default_height);
 }
 
+gboolean
+_gtk_file_chooser_embed_should_respond (GtkFileChooserEmbed *chooser_embed)
+{
+  g_return_val_if_fail (GTK_IS_FILE_CHOOSER_EMBED (chooser_embed), FALSE);
+
+  return GTK_FILE_CHOOSER_EMBED_GET_IFACE (chooser_embed)->should_respond (chooser_embed);
+}
+
 void
 _gtk_file_chooser_embed_get_resizable_hints (GtkFileChooserEmbed *chooser_embed,
                                             gboolean            *resize_horizontally,
index e41c7f86ccd19a0f868c6879b5ba89fd095aa8e7..7c6d6bb31e6e14813742fb9849205ed1b567dfb0 100644 (file)
@@ -46,6 +46,8 @@ struct _GtkFileChooserEmbedIface
   void (*get_resizable_hints)     (GtkFileChooserEmbed *chooser_embed,
                                   gboolean            *resize_horizontally,
                                   gboolean            *resize_vertically);
+
+  gboolean (*should_respond)      (GtkFileChooserEmbed *chooser_embed);
   /* Signals
    */
   void (*default_size_changed)    (GtkFileChooserEmbed *chooser_embed);
@@ -60,6 +62,8 @@ void  _gtk_file_chooser_embed_get_resizable_hints (GtkFileChooserEmbed *chooser_
                                                   gboolean            *resize_horizontally,
                                                   gboolean            *resize_vertically);
 
+gboolean _gtk_file_chooser_embed_should_respond (GtkFileChooserEmbed *chooser_embed);
+
 void _gtk_file_chooser_embed_delegate_iface_init  (GtkFileChooserEmbedIface *iface);
 void _gtk_file_chooser_embed_set_delegate         (GtkFileChooserEmbed *receiver,
                                                   GtkFileChooserEmbed *delegate);