X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkfilechooserbutton.c;h=0c887e5968d90366090f488ae8c168c59ba36625;hb=fa4878979e0a72890ca577a210ccd7cf6291dbf0;hp=70b0b4f26898325373f2104a2a523a007368bd7b;hpb=48f1b89eae8d67663f841865c8eaf1efe08b82a4;p=~andy%2Fgtk
diff --git a/gtk/gtkfilechooserbutton.c b/gtk/gtkfilechooserbutton.c
index 70b0b4f26..0c887e596 100644
--- a/gtk/gtkfilechooserbutton.c
+++ b/gtk/gtkfilechooserbutton.c
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 2 -*- */
+/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
/* GTK+: gtkfilechooserbutton.c
*
@@ -15,9 +15,7 @@
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see .
*/
#include "config.h"
@@ -44,7 +42,7 @@
#include "gtkliststore.h"
#include "gtkstock.h"
#include "gtktreemodelfilter.h"
-#include "gtkvseparator.h"
+#include "gtkseparator.h"
#include "gtkfilechooserdialog.h"
#include "gtkfilechooserprivate.h"
#include "gtkfilechooserutils.h"
@@ -52,18 +50,60 @@
#include "gtkfilechooserbutton.h"
+#include "gtkorientable.h"
+
+#include "gtktypebuiltins.h"
#include "gtkprivate.h"
-#include "gtkalias.h"
+#include "gtksettings.h"
+
+
+/**
+ * SECTION:gtkfilechooserbutton
+ * @Short_description: A button to launch a file selection dialog
+ * @Title: GtkFileChooserButton
+ * @See_also:#GtkFileChooserDialog
+ *
+ * The #GtkFileChooserButton is a widget that lets the user select a
+ * file. It implements the #GtkFileChooser interface. Visually, it is a
+ * file name with a button to bring up a #GtkFileChooserDialog.
+ * The user can then use that dialog to change the file associated with
+ * that button. This widget does not support setting the
+ * #GtkFileChooser:select-multiple property to %TRUE.
+ *
+ *
+ * Create a button to let the user select a file in /etc
+ *
+ * {
+ * GtkWidget *button;
+ *
+ * button = gtk_file_chooser_button_new (_("Select a file"),
+ * GTK_FILE_CHOOSER_ACTION_OPEN);
+ * gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (button),
+ * "/etc");
+ * }
+ *
+ *
+ *
+ * The #GtkFileChooserButton supports the #GtkFileChooserActions
+ * %GTK_FILE_CHOOSER_ACTION_OPEN and %GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER.
+ *
+ *
+ * The #GtkFileChooserButton will ellipsize the label,
+ * and thus will thus request little horizontal space. To give the button
+ * more space, you should call gtk_widget_get_preferred_size(),
+ * gtk_file_chooser_button_set_width_chars(), or pack the button in
+ * such a way that other interface elements give space to the widget.
+ *
+ */
+
/* **************** *
* Private Macros *
* **************** */
-#define GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_FILE_CHOOSER_BUTTON, GtkFileChooserButtonPrivate))
-
-#define DEFAULT_TITLE N_("Select A File")
+#define DEFAULT_TITLE N_("Select a File")
#define DESKTOP_DISPLAY_NAME N_("Desktop")
-#define FALLBACK_DISPLAY_NAME N_("(None)")
+#define FALLBACK_DISPLAY_NAME N_("(None)") /* this string is used in gtk+/gtk/tests/filechooser.c - change it there if you change it here */
#define FALLBACK_ICON_NAME "stock_unknown"
#define FALLBACK_ICON_SIZE 16
@@ -114,6 +154,7 @@ typedef enum
ROW_TYPE_CURRENT_FOLDER,
ROW_TYPE_OTHER_SEPARATOR,
ROW_TYPE_OTHER,
+ ROW_TYPE_EMPTY_SELECTION,
ROW_TYPE_INVALID = -1
}
@@ -138,7 +179,8 @@ struct _GtkFileChooserButtonPrivate
GtkTreeModel *filter_model;
GtkFileSystem *fs;
- GFile *old_file;
+ GFile *selection_while_inactive;
+ GFile *current_folder_while_inactive;
gulong combo_box_changed_id;
gulong dialog_file_activated_id;
@@ -165,10 +207,10 @@ struct _GtkFileChooserButtonPrivate
/* Used for hiding/showing the dialog when the button is hidden */
guint active : 1;
- /* Used to track whether we need to set a default current folder on ::map() */
- guint folder_has_been_set : 1;
-
guint focus_on_click : 1;
+
+ /* Whether the next async callback from GIO should emit the "selection-changed" signal */
+ guint is_changing_selection : 1;
};
@@ -189,6 +231,17 @@ enum
/* GtkFileChooserIface Functions */
static void gtk_file_chooser_button_file_chooser_iface_init (GtkFileChooserIface *iface);
+static gboolean gtk_file_chooser_button_set_current_folder (GtkFileChooser *chooser,
+ GFile *file,
+ GError **error);
+static GFile *gtk_file_chooser_button_get_current_folder (GtkFileChooser *chooser);
+static gboolean gtk_file_chooser_button_select_file (GtkFileChooser *chooser,
+ GFile *file,
+ GError **error);
+static void gtk_file_chooser_button_unselect_file (GtkFileChooser *chooser,
+ GFile *file);
+static void gtk_file_chooser_button_unselect_all (GtkFileChooser *chooser);
+static GSList *gtk_file_chooser_button_get_files (GtkFileChooser *chooser);
static gboolean gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser,
GFile *file,
GError **error);
@@ -210,10 +263,8 @@ static void gtk_file_chooser_button_get_property (GObject *ob
GParamSpec *pspec);
static void gtk_file_chooser_button_finalize (GObject *object);
-/* GtkObject Functions */
-static void gtk_file_chooser_button_destroy (GtkObject *object);
-
/* GtkWidget Functions */
+static void gtk_file_chooser_button_destroy (GtkWidget *widget);
static void gtk_file_chooser_button_drag_data_received (GtkWidget *widget,
GdkDragContext *context,
gint x,
@@ -222,14 +273,12 @@ static void gtk_file_chooser_button_drag_data_received (GtkWidget *wi
guint type,
guint drag_time);
static void gtk_file_chooser_button_show_all (GtkWidget *widget);
-static void gtk_file_chooser_button_hide_all (GtkWidget *widget);
static void gtk_file_chooser_button_show (GtkWidget *widget);
static void gtk_file_chooser_button_hide (GtkWidget *widget);
static void gtk_file_chooser_button_map (GtkWidget *widget);
static gboolean gtk_file_chooser_button_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
-static void gtk_file_chooser_button_style_set (GtkWidget *widget,
- GtkStyle *old_style);
+static void gtk_file_chooser_button_style_updated (GtkWidget *widget);
static void gtk_file_chooser_button_screen_changed (GtkWidget *widget,
GdkScreen *old_screen);
@@ -243,8 +292,9 @@ static gint model_get_type_position (GtkFileChooserButton *button,
RowType row_type);
static void model_free_row_data (GtkFileChooserButton *button,
GtkTreeIter *iter);
-static inline void model_add_special (GtkFileChooserButton *button);
-static inline void model_add_other (GtkFileChooserButton *button);
+static void model_add_special (GtkFileChooserButton *button);
+static void model_add_other (GtkFileChooserButton *button);
+static void model_add_empty_selection (GtkFileChooserButton *button);
static void model_add_volumes (GtkFileChooserButton *button,
GSList *volumes);
static void model_add_bookmarks (GtkFileChooserButton *button,
@@ -279,6 +329,9 @@ static void fs_bookmarks_changed_cb (GtkFileSystem *fs,
static void combo_box_changed_cb (GtkComboBox *combo_box,
gpointer user_data);
+static void combo_box_notify_popup_shown_cb (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data);
static void button_clicked_cb (GtkButton *real_button,
gpointer user_data);
@@ -307,7 +360,7 @@ static guint file_chooser_button_signals[LAST_SIGNAL] = { 0 };
* GType Declaration *
* ******************* */
-G_DEFINE_TYPE_WITH_CODE (GtkFileChooserButton, gtk_file_chooser_button, GTK_TYPE_HBOX, { \
+G_DEFINE_TYPE_WITH_CODE (GtkFileChooserButton, gtk_file_chooser_button, GTK_TYPE_BOX, { \
G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER, gtk_file_chooser_button_file_chooser_iface_init) \
})
@@ -320,11 +373,9 @@ static void
gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
{
GObjectClass *gobject_class;
- GtkObjectClass *gtkobject_class;
GtkWidgetClass *widget_class;
gobject_class = G_OBJECT_CLASS (class);
- gtkobject_class = GTK_OBJECT_CLASS (class);
widget_class = GTK_WIDGET_CLASS (class);
gobject_class->constructor = gtk_file_chooser_button_constructor;
@@ -332,15 +383,13 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
gobject_class->get_property = gtk_file_chooser_button_get_property;
gobject_class->finalize = gtk_file_chooser_button_finalize;
- gtkobject_class->destroy = gtk_file_chooser_button_destroy;
-
+ widget_class->destroy = gtk_file_chooser_button_destroy;
widget_class->drag_data_received = gtk_file_chooser_button_drag_data_received;
widget_class->show_all = gtk_file_chooser_button_show_all;
- widget_class->hide_all = gtk_file_chooser_button_hide_all;
widget_class->show = gtk_file_chooser_button_show;
widget_class->hide = gtk_file_chooser_button_hide;
widget_class->map = gtk_file_chooser_button_map;
- widget_class->style_set = gtk_file_chooser_button_style_set;
+ widget_class->style_updated = gtk_file_chooser_button_style_updated;
widget_class->screen_changed = gtk_file_chooser_button_screen_changed;
widget_class->mnemonic_activate = gtk_file_chooser_button_mnemonic_activate;
@@ -435,7 +484,9 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
GtkWidget *box, *image, *sep;
GtkTargetList *target_list;
- priv = button->priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (button);
+ priv = button->priv = G_TYPE_INSTANCE_GET_PRIVATE (button,
+ GTK_TYPE_FILE_CHOOSER_BUTTON,
+ GtkFileChooserButtonPrivate);
priv->icon_size = FALLBACK_ICON_SIZE;
priv->focus_on_click = TRUE;
@@ -444,12 +495,13 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
/* Button */
priv->button = gtk_button_new ();
- g_signal_connect (priv->button, "clicked", G_CALLBACK (button_clicked_cb),
- button);
- gtk_container_add (GTK_CONTAINER (button), priv->button);
+ g_signal_connect (priv->button, "clicked",
+ G_CALLBACK (button_clicked_cb), button);
+ gtk_box_pack_start (GTK_BOX (button), priv->button, TRUE, TRUE, 0);
+ gtk_widget_set_halign (priv->button, GTK_ALIGN_FILL);
gtk_widget_show (priv->button);
- box = gtk_hbox_new (FALSE, 4);
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
gtk_container_add (GTK_CONTAINER (priv->button), box);
gtk_widget_show (box);
@@ -459,16 +511,17 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
priv->label = gtk_label_new (_(FALLBACK_DISPLAY_NAME));
gtk_label_set_ellipsize (GTK_LABEL (priv->label), PANGO_ELLIPSIZE_END);
- gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.5);
- gtk_container_add (GTK_CONTAINER (box), priv->label);
+ gtk_widget_set_halign (priv->label, GTK_ALIGN_START);
+ gtk_widget_set_valign (priv->label, GTK_ALIGN_CENTER);
+ gtk_box_pack_start (GTK_BOX (box), priv->label, TRUE, TRUE, 0);
+ //gtk_container_add (GTK_CONTAINER (box), priv->label);
gtk_widget_show (priv->label);
- sep = gtk_vseparator_new ();
+ sep = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
gtk_box_pack_start (GTK_BOX (box), sep, FALSE, FALSE, 0);
gtk_widget_show (sep);
- image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
- GTK_ICON_SIZE_MENU);
+ image = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
gtk_widget_show (image);
@@ -476,18 +529,22 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
/* Keep in sync with columns enum, line 88 */
priv->model =
GTK_TREE_MODEL (gtk_list_store_new (NUM_COLUMNS,
- GDK_TYPE_PIXBUF, /* Icon */
- G_TYPE_STRING, /* Display Name */
- G_TYPE_CHAR, /* Row Type */
- G_TYPE_POINTER /* Volume || Path */,
- G_TYPE_BOOLEAN /* Is Folder? */,
- G_TYPE_POINTER /* cancellable */));
+ GDK_TYPE_PIXBUF, /* ICON_COLUMN */
+ G_TYPE_STRING, /* DISPLAY_NAME_COLUMN */
+ G_TYPE_CHAR, /* TYPE_COLUMN */
+ G_TYPE_POINTER /* DATA_COLUMN (Volume || Path) */,
+ G_TYPE_BOOLEAN /* IS_FOLDER_COLUMN */,
+ G_TYPE_POINTER /* CANCELLABLE_COLUMN */));
priv->combo_box = gtk_combo_box_new ();
- priv->combo_box_changed_id =
- g_signal_connect (priv->combo_box, "changed",
- G_CALLBACK (combo_box_changed_cb), button);
- gtk_container_add (GTK_CONTAINER (button), priv->combo_box);
+ priv->combo_box_changed_id = g_signal_connect (priv->combo_box, "changed",
+ G_CALLBACK (combo_box_changed_cb), button);
+
+ g_signal_connect (priv->combo_box, "notify::popup-shown",
+ G_CALLBACK (combo_box_notify_popup_shown_cb), button);
+
+ gtk_box_pack_start (GTK_BOX (button), priv->combo_box, TRUE, TRUE, 0);
+ gtk_widget_set_halign (priv->combo_box, GTK_ALIGN_FILL);
priv->icon_cell = gtk_cell_renderer_pixbuf_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->combo_box),
@@ -527,10 +584,196 @@ gtk_file_chooser_button_file_chooser_iface_init (GtkFileChooserIface *iface)
{
_gtk_file_chooser_delegate_iface_init (iface);
+ iface->set_current_folder = gtk_file_chooser_button_set_current_folder;
+ iface->get_current_folder = gtk_file_chooser_button_get_current_folder;
+ iface->select_file = gtk_file_chooser_button_select_file;
+ iface->unselect_file = gtk_file_chooser_button_unselect_file;
+ iface->unselect_all = gtk_file_chooser_button_unselect_all;
+ iface->get_files = gtk_file_chooser_button_get_files;
iface->add_shortcut_folder = gtk_file_chooser_button_add_shortcut_folder;
iface->remove_shortcut_folder = gtk_file_chooser_button_remove_shortcut_folder;
}
+static void
+emit_selection_changed_if_changing_selection (GtkFileChooserButton *button)
+{
+ GtkFileChooserButtonPrivate *priv = button->priv;
+
+ if (priv->is_changing_selection)
+ {
+ priv->is_changing_selection = FALSE;
+ g_signal_emit_by_name (button, "selection-changed");
+ }
+}
+
+static gboolean
+gtk_file_chooser_button_set_current_folder (GtkFileChooser *chooser,
+ GFile *file,
+ GError **error)
+{
+ GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser);
+ GtkFileChooserButtonPrivate *priv = button->priv;
+ GtkFileChooser *delegate;
+
+ delegate = g_object_get_qdata (G_OBJECT (chooser),
+ GTK_FILE_CHOOSER_DELEGATE_QUARK);
+
+ if (priv->active)
+ return gtk_file_chooser_set_current_folder_file (delegate, file, error);
+ else
+ {
+ if (priv->current_folder_while_inactive)
+ g_object_unref (priv->current_folder_while_inactive);
+
+ priv->current_folder_while_inactive = g_object_ref (file);
+
+ update_combo_box (button);
+
+ g_signal_emit_by_name (button, "current-folder-changed");
+
+ return TRUE;
+ }
+}
+
+static GFile *
+gtk_file_chooser_button_get_current_folder (GtkFileChooser *chooser)
+{
+ GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser);
+ GtkFileChooserButtonPrivate *priv = button->priv;
+ GtkFileChooser *delegate;
+
+ delegate = g_object_get_qdata (G_OBJECT (chooser),
+ GTK_FILE_CHOOSER_DELEGATE_QUARK);
+
+ if (priv->active)
+ return gtk_file_chooser_get_current_folder_file (delegate);
+ else
+ {
+ if (priv->current_folder_while_inactive)
+ return g_object_ref (priv->current_folder_while_inactive);
+ else
+ return NULL;
+ }
+}
+
+static gboolean
+gtk_file_chooser_button_select_file (GtkFileChooser *chooser,
+ GFile *file,
+ GError **error)
+{
+ GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser);
+ GtkFileChooserButtonPrivate *priv = button->priv;
+ GtkFileChooser *delegate;
+
+ delegate = g_object_get_qdata (G_OBJECT (chooser),
+ GTK_FILE_CHOOSER_DELEGATE_QUARK);
+
+ if (priv->active)
+ return gtk_file_chooser_select_file (delegate, file, error);
+ else
+ {
+ if (priv->selection_while_inactive)
+ g_object_unref (priv->selection_while_inactive);
+
+ priv->selection_while_inactive = g_object_ref (file);
+
+ priv->is_changing_selection = TRUE;
+
+ update_label_and_image (button);
+ update_combo_box (button);
+
+ return TRUE;
+ }
+}
+
+static void
+gtk_file_chooser_button_unselect_file (GtkFileChooser *chooser,
+ GFile *file)
+{
+ GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser);
+ GtkFileChooserButtonPrivate *priv = button->priv;
+ GtkFileChooser *delegate;
+
+ delegate = g_object_get_qdata (G_OBJECT (chooser),
+ GTK_FILE_CHOOSER_DELEGATE_QUARK);
+
+ if (priv->active)
+ gtk_file_chooser_unselect_file (delegate, file);
+ else
+ {
+ if (g_file_equal (priv->selection_while_inactive, file))
+ {
+ if (priv->selection_while_inactive)
+ {
+ g_object_unref (priv->selection_while_inactive);
+ priv->selection_while_inactive = NULL;
+ }
+
+ priv->is_changing_selection = TRUE;
+
+ update_label_and_image (button);
+ update_combo_box (button);
+ }
+ }
+}
+
+static void
+gtk_file_chooser_button_unselect_all (GtkFileChooser *chooser)
+{
+ GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser);
+ GtkFileChooserButtonPrivate *priv = button->priv;
+ GtkFileChooser *delegate;
+
+ delegate = g_object_get_qdata (G_OBJECT (chooser),
+ GTK_FILE_CHOOSER_DELEGATE_QUARK);
+
+ if (priv->active)
+ gtk_file_chooser_unselect_all (delegate);
+ else
+ {
+ if (priv->selection_while_inactive)
+ {
+ g_object_unref (priv->selection_while_inactive);
+ priv->selection_while_inactive = NULL;
+ }
+
+ update_label_and_image (button);
+ update_combo_box (button);
+ }
+}
+
+static GFile *
+get_selected_file (GtkFileChooserButton *button)
+{
+ GtkFileChooserButtonPrivate *priv = button->priv;
+
+ if (priv->active)
+ return gtk_file_chooser_get_file (GTK_FILE_CHOOSER (priv->dialog));
+ else
+ {
+ if (priv->selection_while_inactive)
+ return g_object_ref (priv->selection_while_inactive);
+ else if (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (priv->dialog)) == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ {
+ /* If there is no "real" selection in SELECT_FOLDER mode, then we'll just return
+ * the current folder, since that is what GtkFileChooserDefault would do.
+ */
+ if (priv->current_folder_while_inactive)
+ return g_object_ref (priv->current_folder_while_inactive);
+ }
+ }
+
+ return NULL;
+}
+
+static GSList *
+gtk_file_chooser_button_get_files (GtkFileChooser *chooser)
+{
+ GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser);
+
+ return g_slist_prepend (NULL, get_selected_file (button));
+}
+
static gboolean
gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser,
GFile *file,
@@ -635,7 +878,6 @@ gtk_file_chooser_button_constructor (GType type,
GtkFileChooserButton *button;
GtkFileChooserButtonPrivate *priv;
GSList *list;
- char *current_folder;
object = G_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->constructor (type,
n_params,
@@ -662,18 +904,11 @@ gtk_file_chooser_button_constructor (GType type,
gtk_file_chooser_button_set_title (button, _(DEFAULT_TITLE));
}
- else if (!GTK_WINDOW (priv->dialog)->title)
+ else if (!gtk_window_get_title (GTK_WINDOW (priv->dialog)))
{
gtk_file_chooser_button_set_title (button, _(DEFAULT_TITLE));
}
- current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (priv->dialog));
- if (current_folder != NULL)
- {
- priv->folder_has_been_set = TRUE;
- g_free (current_folder);
- }
-
g_signal_connect (priv->dialog, "delete-event",
G_CALLBACK (dialog_delete_event_cb), object);
g_signal_connect (priv->dialog, "response",
@@ -714,6 +949,8 @@ gtk_file_chooser_button_constructor (GType type,
model_add_other (button);
+ model_add_empty_selection (button);
+
priv->filter_model = gtk_tree_model_filter_new (priv->model, NULL);
gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (priv->filter_model),
filter_model_visible_func,
@@ -738,6 +975,9 @@ gtk_file_chooser_button_constructor (GType type,
g_signal_connect (priv->fs, "bookmarks-changed",
G_CALLBACK (fs_bookmarks_changed_cb), object);
+ update_label_and_image (button);
+ update_combo_box (button);
+
return object;
}
@@ -820,10 +1060,6 @@ gtk_file_chooser_button_set_property (GObject *object,
fs_bookmarks_changed_cb (priv->fs, button);
break;
- case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM_BACKEND:
- /* Ignore property */
- break;
-
case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
g_warning ("%s: Choosers of type `%s` do not support selecting multiple files.",
G_STRFUNC, G_OBJECT_TYPE_NAME (object));
@@ -856,7 +1092,6 @@ gtk_file_chooser_button_get_property (GObject *object,
case PROP_TITLE:
case GTK_FILE_CHOOSER_PROP_ACTION:
- case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM_BACKEND:
case GTK_FILE_CHOOSER_PROP_FILTER:
case GTK_FILE_CHOOSER_PROP_LOCAL_ONLY:
case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
@@ -866,6 +1101,7 @@ gtk_file_chooser_button_get_property (GObject *object,
case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
case GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION:
+ case GTK_FILE_CHOOSER_PROP_CREATE_FOLDERS:
g_object_get_property (G_OBJECT (priv->dialog), pspec->name, value);
break;
@@ -881,20 +1117,23 @@ gtk_file_chooser_button_finalize (GObject *object)
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object);
GtkFileChooserButtonPrivate *priv = button->priv;
- if (priv->old_file)
- g_object_unref (priv->old_file);
+ if (priv->selection_while_inactive)
+ g_object_unref (priv->selection_while_inactive);
+
+ if (priv->current_folder_while_inactive)
+ g_object_unref (priv->current_folder_while_inactive);
G_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->finalize (object);
}
/* ********************* *
- * GtkObject Functions *
+ * GtkWidget Functions *
* ********************* */
static void
-gtk_file_chooser_button_destroy (GtkObject *object)
+gtk_file_chooser_button_destroy (GtkWidget *widget)
{
- GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object);
+ GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget);
GtkFileChooserButtonPrivate *priv = button->priv;
GtkTreeIter iter;
GSList *l;
@@ -954,14 +1193,9 @@ gtk_file_chooser_button_destroy (GtkObject *object)
priv->fs = NULL;
}
- GTK_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->destroy (object);
+ GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->destroy (widget);
}
-
-/* ********************* *
- * GtkWidget Functions *
- * ********************* */
-
struct DndSelectFolderData
{
GtkFileSystem *file_system;
@@ -1057,7 +1291,7 @@ gtk_file_chooser_button_drag_data_received (GtkWidget *widget,
data, type,
drag_time);
- if (widget == NULL || context == NULL || data == NULL || data->length < 0)
+ if (widget == NULL || context == NULL || data == NULL || gtk_selection_data_get_length (data) < 0)
return;
switch (type)
@@ -1115,12 +1349,6 @@ gtk_file_chooser_button_show_all (GtkWidget *widget)
gtk_widget_show (widget);
}
-static void
-gtk_file_chooser_button_hide_all (GtkWidget *widget)
-{
- gtk_widget_hide (widget);
-}
-
static void
gtk_file_chooser_button_show (GtkWidget *widget)
{
@@ -1149,20 +1377,6 @@ gtk_file_chooser_button_hide (GtkWidget *widget)
static void
gtk_file_chooser_button_map (GtkWidget *widget)
{
- GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget);
- GtkFileChooserButtonPrivate *priv = button->priv;
-
- if (!priv->folder_has_been_set)
- {
- char *current_working_dir;
-
- current_working_dir = g_get_current_dir ();
- gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (widget), current_working_dir);
- g_free (current_working_dir);
-
- priv->folder_has_been_set = TRUE;
- }
-
GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->map (widget);
}
@@ -1369,11 +1583,9 @@ change_icon_theme (GtkFileChooserButton *button)
}
static void
-gtk_file_chooser_button_style_set (GtkWidget *widget,
- GtkStyle *old_style)
+gtk_file_chooser_button_style_updated (GtkWidget *widget)
{
- GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->style_set (widget,
- old_style);
+ GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->style_updated (widget);
if (gtk_widget_has_screen (widget))
change_icon_theme (GTK_FILE_CHOOSER_BUTTON (widget));
@@ -1423,7 +1635,7 @@ set_info_get_info_cb (GCancellable *cancellable,
GdkPixbuf *pixbuf;
GtkTreePath *path;
GtkTreeIter iter;
- GCancellable *model_cancellable;
+ GCancellable *model_cancellable = NULL;
struct SetDisplayNameData *data = callback_data;
gboolean is_folder;
@@ -1476,7 +1688,8 @@ out:
gtk_tree_row_reference_free (data->row_ref);
g_free (data);
- g_object_unref (cancellable);
+ if (model_cancellable)
+ g_object_unref (model_cancellable);
}
static void
@@ -1555,6 +1768,11 @@ model_get_type_position (GtkFileChooserButton *button,
if (row_type == ROW_TYPE_OTHER)
return retval;
+ retval++;
+
+ if (row_type == ROW_TYPE_EMPTY_SELECTION)
+ return retval;
+
g_assert_not_reached ();
return -1;
}
@@ -1574,7 +1792,10 @@ model_free_row_data (GtkFileChooserButton *button,
-1);
if (cancellable)
- g_cancellable_cancel (cancellable);
+ {
+ g_cancellable_cancel (cancellable);
+ g_object_unref (cancellable);
+ }
switch (type)
{
@@ -1585,7 +1806,7 @@ model_free_row_data (GtkFileChooserButton *button,
g_object_unref (data);
break;
case ROW_TYPE_VOLUME:
- _gtk_file_system_volume_free (data);
+ _gtk_file_system_volume_unref (data);
break;
default:
break;
@@ -1602,7 +1823,7 @@ model_add_special_get_info_cb (GCancellable *cancellable,
GtkTreeIter iter;
GtkTreePath *path;
GdkPixbuf *pixbuf;
- GCancellable *model_cancellable;
+ GCancellable *model_cancellable = NULL;
struct ChangeIconThemeData *data = user_data;
gchar *name;
@@ -1655,10 +1876,11 @@ out:
gtk_tree_row_reference_free (data->row_ref);
g_free (data);
- g_object_unref (cancellable);
+ if (model_cancellable)
+ g_object_unref (model_cancellable);
}
-static inline void
+static void
model_add_special (GtkFileChooserButton *button)
{
const gchar *homedir;
@@ -1708,7 +1930,10 @@ model_add_special (GtkFileChooserButton *button)
desktopdir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
- if (desktopdir)
+ /* "To disable a directory, point it to the homedir."
+ * See http://freedesktop.org/wiki/Software/xdg-user-dirs
+ **/
+ if (g_strcmp0 (desktopdir, g_get_home_dir ()) != 0)
{
GtkTreePath *tree_path;
GCancellable *cancellable;
@@ -1744,21 +1969,19 @@ model_add_special (GtkFileChooserButton *button)
static void
model_add_volumes (GtkFileChooserButton *button,
- GSList *volumes)
+ GSList *volumes)
{
GtkListStore *store;
gint pos;
gboolean local_only;
- GtkFileSystem *file_system;
GSList *l;
-
+
if (!volumes)
return;
store = GTK_LIST_STORE (button->priv->model);
pos = model_get_type_position (button, ROW_TYPE_VOLUME);
local_only = gtk_file_chooser_get_local_only (GTK_FILE_CHOOSER (button->priv->dialog));
- file_system = button->priv->fs;
for (l = volumes; l; l = l->next)
{
@@ -1770,37 +1993,42 @@ model_add_volumes (GtkFileChooserButton *button,
volume = l->data;
if (local_only)
- {
- if (_gtk_file_system_volume_is_mounted (volume))
- {
- GFile *base_file;
-
- base_file = _gtk_file_system_volume_get_root (volume);
- if (base_file != NULL && !g_file_is_native (base_file))
- {
- _gtk_file_system_volume_free (volume);
- continue;
- }
- }
- }
+ {
+ if (_gtk_file_system_volume_is_mounted (volume))
+ {
+ GFile *base_file;
+
+ base_file = _gtk_file_system_volume_get_root (volume);
+ if (base_file != NULL)
+ {
+ if (!_gtk_file_has_native_path (base_file))
+ {
+ g_object_unref (base_file);
+ continue;
+ }
+ else
+ g_object_unref (base_file);
+ }
+ }
+ }
pixbuf = _gtk_file_system_volume_render_icon (volume,
- GTK_WIDGET (button),
- button->priv->icon_size,
- NULL);
+ GTK_WIDGET (button),
+ button->priv->icon_size,
+ NULL);
display_name = _gtk_file_system_volume_get_display_name (volume);
gtk_list_store_insert (store, &iter, pos);
gtk_list_store_set (store, &iter,
- ICON_COLUMN, pixbuf,
- DISPLAY_NAME_COLUMN, display_name,
- TYPE_COLUMN, ROW_TYPE_VOLUME,
- DATA_COLUMN, volume,
- IS_FOLDER_COLUMN, TRUE,
- -1);
+ ICON_COLUMN, pixbuf,
+ DISPLAY_NAME_COLUMN, display_name,
+ TYPE_COLUMN, ROW_TYPE_VOLUME,
+ DATA_COLUMN, _gtk_file_system_volume_ref (volume),
+ IS_FOLDER_COLUMN, TRUE,
+ -1);
if (pixbuf)
- g_object_unref (pixbuf);
+ g_object_unref (pixbuf);
g_free (display_name);
button->priv->n_volumes++;
@@ -1833,7 +2061,7 @@ model_add_bookmarks (GtkFileChooserButton *button,
file = l->data;
- if (g_file_is_native (file))
+ if (_gtk_file_has_native_path (file))
{
gtk_list_store_insert (store, &iter, pos);
gtk_list_store_set (store, &iter,
@@ -1988,7 +2216,7 @@ model_update_current_folder (GtkFileChooserButton *button,
}
}
-static inline void
+static void
model_add_other (GtkFileChooserButton *button)
{
GtkListStore *store;
@@ -2012,13 +2240,33 @@ model_add_other (GtkFileChooserButton *button)
gtk_list_store_insert (store, &iter, pos);
gtk_list_store_set (store, &iter,
ICON_COLUMN, NULL,
- DISPLAY_NAME_COLUMN, _("Other..."),
+ DISPLAY_NAME_COLUMN, _("Otherâ¦"),
TYPE_COLUMN, ROW_TYPE_OTHER,
DATA_COLUMN, NULL,
IS_FOLDER_COLUMN, FALSE,
-1);
}
+static void
+model_add_empty_selection (GtkFileChooserButton *button)
+{
+ GtkListStore *store;
+ GtkTreeIter iter;
+ gint pos;
+
+ store = GTK_LIST_STORE (button->priv->model);
+ pos = model_get_type_position (button, ROW_TYPE_EMPTY_SELECTION);
+
+ gtk_list_store_insert (store, &iter, pos);
+ gtk_list_store_set (store, &iter,
+ ICON_COLUMN, NULL,
+ DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME),
+ TYPE_COLUMN, ROW_TYPE_EMPTY_SELECTION,
+ DATA_COLUMN, NULL,
+ IS_FOLDER_COLUMN, FALSE,
+ -1);
+}
+
static void
model_remove_rows (GtkFileChooserButton *button,
gint pos,
@@ -2046,7 +2294,7 @@ model_remove_rows (GtkFileChooserButton *button,
}
/* Filter Model */
-static inline gboolean
+static gboolean
test_if_file_is_visible (GtkFileSystem *fs,
GFile *file,
gboolean local_only,
@@ -2055,7 +2303,7 @@ test_if_file_is_visible (GtkFileSystem *fs,
if (!file)
return FALSE;
- if (local_only && !g_file_is_native (file))
+ if (local_only && !_gtk_file_has_native_path (file))
return FALSE;
if (!is_folder)
@@ -2108,7 +2356,7 @@ filter_model_visible_func (GtkTreeModel *model,
if (base_file)
{
- if (!g_file_is_native (base_file))
+ if (!_gtk_file_has_native_path (base_file))
retval = FALSE;
g_object_unref (base_file);
}
@@ -2118,6 +2366,34 @@ filter_model_visible_func (GtkTreeModel *model,
}
}
break;
+ case ROW_TYPE_EMPTY_SELECTION:
+ {
+ gboolean popup_shown;
+
+ g_object_get (priv->combo_box,
+ "popup-shown", &popup_shown,
+ NULL);
+
+ if (popup_shown)
+ retval = FALSE;
+ else
+ {
+ GFile *selected;
+
+ /* When the combo box is not popped up... */
+
+ selected = get_selected_file (button);
+ if (selected)
+ retval = FALSE; /* ... nonempty selection means the ROW_TYPE_EMPTY_SELECTION is *not* visible... */
+ else
+ retval = TRUE; /* ... and empty selection means the ROW_TYPE_EMPTY_SELECTION *is* visible */
+
+ if (selected)
+ g_object_unref (selected);
+ }
+
+ break;
+ }
default:
retval = TRUE;
break;
@@ -2159,22 +2435,37 @@ combo_box_row_separator_func (GtkTreeModel *model,
return (type == ROW_TYPE_BOOKMARK_SEPARATOR ||
type == ROW_TYPE_CURRENT_FOLDER_SEPARATOR ||
type == ROW_TYPE_OTHER_SEPARATOR);
-}
+}
+
+static void
+select_combo_box_row_no_notify (GtkFileChooserButton *button, int pos)
+{
+ GtkFileChooserButtonPrivate *priv = button->priv;
+ GtkTreeIter iter, filter_iter;
+
+ gtk_tree_model_iter_nth_child (priv->model, &iter, NULL, pos);
+ gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (priv->filter_model),
+ &filter_iter, &iter);
+
+ g_signal_handler_block (priv->combo_box, priv->combo_box_changed_id);
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combo_box), &filter_iter);
+ g_signal_handler_unblock (priv->combo_box, priv->combo_box_changed_id);
+}
static void
update_combo_box (GtkFileChooserButton *button)
{
GtkFileChooserButtonPrivate *priv = button->priv;
- GSList *files;
+ GFile *file;
GtkTreeIter iter;
gboolean row_found;
- gtk_tree_model_get_iter_first (priv->filter_model, &iter);
-
- files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (priv->dialog));
+ file = get_selected_file (button);
row_found = FALSE;
+ gtk_tree_model_get_iter_first (priv->filter_model, &iter);
+
do
{
gchar type;
@@ -2194,9 +2485,7 @@ update_combo_box (GtkFileChooserButton *button)
case ROW_TYPE_SHORTCUT:
case ROW_TYPE_BOOKMARK:
case ROW_TYPE_CURRENT_FOLDER:
- row_found = (files &&
- files->data &&
- g_file_equal (data, files->data));
+ row_found = (file && g_file_equal (data, file));
break;
case ROW_TYPE_VOLUME:
{
@@ -2205,9 +2494,7 @@ update_combo_box (GtkFileChooserButton *button)
base_file = _gtk_file_system_volume_get_root (data);
if (base_file)
{
- row_found = (files &&
- files->data &&
- g_file_equal (base_file, files->data));
+ row_found = (file && g_file_equal (base_file, file));
g_object_unref (base_file);
}
}
@@ -2228,28 +2515,30 @@ update_combo_box (GtkFileChooserButton *button)
}
while (!row_found && gtk_tree_model_iter_next (priv->filter_model, &iter));
- /* If it hasn't been found already, update & select the current-folder row. */
- if (!row_found && files && files->data)
+ if (!row_found)
{
- GtkTreeIter filter_iter;
gint pos;
-
- model_update_current_folder (button, files->data);
- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model));
- pos = model_get_type_position (button, ROW_TYPE_CURRENT_FOLDER);
- gtk_tree_model_iter_nth_child (priv->model, &iter, NULL, pos);
+ /* If it hasn't been found already, update & select the current-folder row. */
+ if (file)
+ {
+ model_update_current_folder (button, file);
+ pos = model_get_type_position (button, ROW_TYPE_CURRENT_FOLDER);
+ }
+ else
+ {
+ /* No selection; switch to that row */
- gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (priv->filter_model),
- &filter_iter, &iter);
+ pos = model_get_type_position (button, ROW_TYPE_EMPTY_SELECTION);
+ }
- g_signal_handler_block (priv->combo_box, priv->combo_box_changed_id);
- gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combo_box), &filter_iter);
- g_signal_handler_unblock (priv->combo_box, priv->combo_box_changed_id);
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model));
+
+ select_combo_box_row_no_notify (button, pos);
}
- g_slist_foreach (files, (GFunc) g_object_unref, NULL);
- g_slist_free (files);
+ if (file)
+ g_object_unref (file);
}
/* Button */
@@ -2286,6 +2575,8 @@ update_label_get_info_cb (GCancellable *cancellable,
g_object_unref (pixbuf);
out:
+ emit_selection_changed_if_changing_selection (button);
+
g_object_unref (button);
g_object_unref (cancellable);
}
@@ -2294,13 +2585,14 @@ static void
update_label_and_image (GtkFileChooserButton *button)
{
GtkFileChooserButtonPrivate *priv = button->priv;
- GdkPixbuf *pixbuf;
gchar *label_text;
- GSList *files;
+ GFile *file;
+ gboolean done_changing_selection;
+
+ file = get_selected_file (button);
- files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (priv->dialog));
label_text = NULL;
- pixbuf = NULL;
+ done_changing_selection = FALSE;
if (priv->update_button_cancellable)
{
@@ -2308,64 +2600,75 @@ update_label_and_image (GtkFileChooserButton *button)
priv->update_button_cancellable = NULL;
}
- if (files && files->data)
+ if (file)
{
- GFile *file;
GtkFileSystemVolume *volume = NULL;
- file = files->data;
-
volume = _gtk_file_system_get_volume_for_file (priv->fs, file);
if (volume)
- {
- GFile *base_file;
+ {
+ GFile *base_file;
- base_file = _gtk_file_system_volume_get_root (volume);
- if (base_file && g_file_equal (base_file, file))
- {
- label_text = _gtk_file_system_volume_get_display_name (volume);
- pixbuf = _gtk_file_system_volume_render_icon (volume,
- GTK_WIDGET (button),
- priv->icon_size,
- NULL);
- }
+ base_file = _gtk_file_system_volume_get_root (volume);
+ if (base_file && g_file_equal (base_file, file))
+ {
+ GdkPixbuf *pixbuf;
- if (base_file)
- g_object_unref (base_file);
+ label_text = _gtk_file_system_volume_get_display_name (volume);
+ pixbuf = _gtk_file_system_volume_render_icon (volume,
+ GTK_WIDGET (button),
+ priv->icon_size,
+ NULL);
+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), pixbuf);
+ if (pixbuf)
+ g_object_unref (pixbuf);
+ }
- _gtk_file_system_volume_free (volume);
+ if (base_file)
+ g_object_unref (base_file);
- if (label_text)
- goto out;
- }
+ _gtk_file_system_volume_unref (volume);
+
+ if (label_text)
+ {
+ done_changing_selection = TRUE;
+ goto out;
+ }
+ }
if (g_file_is_native (file))
- {
- priv->update_button_cancellable =
- _gtk_file_system_get_info (priv->fs, file,
- "standard::icon,standard::display-name",
- update_label_get_info_cb,
- g_object_ref (button));
- }
+ {
+ priv->update_button_cancellable =
+ _gtk_file_system_get_info (priv->fs, file,
+ "standard::icon,standard::display-name",
+ update_label_get_info_cb,
+ g_object_ref (button));
+ }
else
- {
- GdkPixbuf *pixbuf;
+ {
+ GdkPixbuf *pixbuf;
- label_text = _gtk_file_system_get_bookmark_label (button->priv->fs, file);
-
- pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (priv->image)),
- "text-x-generic",
- priv->icon_size, 0, NULL);
-
- gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), pixbuf);
+ label_text = _gtk_file_system_get_bookmark_label (button->priv->fs, file);
+ pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (priv->image)),
+ "text-x-generic",
+ priv->icon_size, 0, NULL);
+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), pixbuf);
+ if (pixbuf)
+ g_object_unref (pixbuf);
- if (pixbuf)
- g_object_unref (pixbuf);
- }
+ done_changing_selection = TRUE;
+ }
+ }
+ else
+ {
+ /* We know the selection is empty */
+ done_changing_selection = TRUE;
}
+
out:
- g_slist_foreach (files, (GFunc) g_object_unref, NULL);
- g_slist_free (files);
+
+ if (file)
+ g_object_unref (file);
if (label_text)
{
@@ -2377,6 +2680,9 @@ out:
gtk_label_set_text (GTK_LABEL (priv->label), _(FALLBACK_DISPLAY_NAME));
gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), NULL);
}
+
+ if (done_changing_selection)
+ emit_selection_changed_if_changing_selection (button);
}
@@ -2434,6 +2740,35 @@ fs_bookmarks_changed_cb (GtkFileSystem *fs,
update_combo_box (user_data);
}
+static void
+save_inactive_state (GtkFileChooserButton *button)
+{
+ GtkFileChooserButtonPrivate *priv = button->priv;
+
+ if (priv->current_folder_while_inactive)
+ g_object_unref (priv->current_folder_while_inactive);
+
+ if (priv->selection_while_inactive)
+ g_object_unref (priv->selection_while_inactive);
+
+ priv->current_folder_while_inactive = gtk_file_chooser_get_current_folder_file (GTK_FILE_CHOOSER (priv->dialog));
+ priv->selection_while_inactive = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (priv->dialog));
+}
+
+static void
+restore_inactive_state (GtkFileChooserButton *button)
+{
+ GtkFileChooserButtonPrivate *priv = button->priv;
+
+ if (priv->current_folder_while_inactive)
+ gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (priv->dialog), priv->current_folder_while_inactive, NULL);
+
+ if (priv->selection_while_inactive)
+ gtk_file_chooser_select_file (GTK_FILE_CHOOSER (priv->dialog), priv->selection_while_inactive, NULL);
+ else
+ gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
+}
+
/* Dialog */
static void
open_dialog (GtkFileChooserButton *button)
@@ -2442,13 +2777,13 @@ open_dialog (GtkFileChooserButton *button)
/* Setup the dialog parent to be chooser button's toplevel, and be modal
as needed. */
- if (!GTK_WIDGET_VISIBLE (priv->dialog))
+ if (!gtk_widget_get_visible (priv->dialog))
{
GtkWidget *toplevel;
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (button));
- if (GTK_WIDGET_TOPLEVEL (toplevel) && GTK_IS_WINDOW (toplevel))
+ if (gtk_widget_is_toplevel (toplevel) && GTK_IS_WINDOW (toplevel))
{
if (GTK_WINDOW (toplevel) != gtk_window_get_transient_for (GTK_WINDOW (priv->dialog)))
gtk_window_set_transient_for (GTK_WINDOW (priv->dialog),
@@ -2461,23 +2796,14 @@ open_dialog (GtkFileChooserButton *button)
if (!priv->active)
{
- GSList *files;
-
g_signal_handler_block (priv->dialog,
priv->dialog_folder_changed_id);
g_signal_handler_block (priv->dialog,
priv->dialog_file_activated_id);
g_signal_handler_block (priv->dialog,
priv->dialog_selection_changed_id);
- files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (priv->dialog));
- if (files)
- {
- if (files->data)
- priv->old_file = g_object_ref (files->data);
- g_slist_foreach (files, (GFunc) g_object_unref, NULL);
- g_slist_free (files);
- }
+ restore_inactive_state (button);
priv->active = TRUE;
}
@@ -2514,21 +2840,17 @@ combo_box_changed_cb (GtkComboBox *combo_box,
case ROW_TYPE_SHORTCUT:
case ROW_TYPE_BOOKMARK:
case ROW_TYPE_CURRENT_FOLDER:
- gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
if (data)
- gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (priv->dialog),
- data, NULL);
+ gtk_file_chooser_button_select_file (GTK_FILE_CHOOSER (button), data, NULL);
break;
case ROW_TYPE_VOLUME:
{
GFile *base_file;
- gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
base_file = _gtk_file_system_volume_get_root (data);
if (base_file)
{
- gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (priv->dialog),
- base_file, NULL);
+ gtk_file_chooser_button_select_file (GTK_FILE_CHOOSER (button), base_file, NULL);
g_object_unref (base_file);
}
}
@@ -2542,6 +2864,50 @@ combo_box_changed_cb (GtkComboBox *combo_box,
}
}
+/* Calback for the "notify::popup-shown" signal on the combo box.
+ * When the combo is popped up, we don't want the ROW_TYPE_EMPTY_SELECTION to be visible
+ * at all; otherwise we would be showing a "(None)" item in the combo box's popup.
+ *
+ * However, when the combo box is *not* popped up, we want the empty-selection row
+ * to be visible depending on the selection.
+ *
+ * Since all that is done through the filter_model_visible_func(), this means
+ * that we need to refilter the model when the combo box pops up - hence the
+ * present signal handler.
+ */
+static void
+combo_box_notify_popup_shown_cb (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (user_data);
+ GtkFileChooserButtonPrivate *priv = button->priv;
+ gboolean popup_shown;
+
+ g_object_get (priv->combo_box,
+ "popup-shown", &popup_shown,
+ NULL);
+
+ /* Indicate that the ROW_TYPE_EMPTY_SELECTION will change visibility... */
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model));
+
+ /* If the combo box popup got dismissed, go back to showing the ROW_TYPE_EMPTY_SELECTION if needed */
+ if (!popup_shown)
+ {
+ GFile *selected = get_selected_file (button);
+
+ if (!selected)
+ {
+ int pos;
+
+ pos = model_get_type_position (button, ROW_TYPE_EMPTY_SELECTION);
+ select_combo_box_row_no_notify (button, pos);
+ }
+ else
+ g_object_unref (selected);
+ }
+}
+
/* Button */
static void
button_clicked_cb (GtkButton *real_button,
@@ -2556,9 +2922,6 @@ dialog_current_folder_changed_cb (GtkFileChooser *dialog,
gpointer user_data)
{
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (user_data);
- GtkFileChooserButtonPrivate *priv = button->priv;
-
- priv->folder_has_been_set = TRUE;
g_signal_emit_by_name (button, "current-folder-changed");
}
@@ -2618,7 +2981,7 @@ dialog_notify_cb (GObject *dialog,
/* If the path isn't local but we're in local-only mode now, remove
* the custom-folder row */
- if (data && g_file_is_native (G_FILE (data)) &&
+ if (data && _gtk_file_has_native_path (G_FILE (data)) &&
gtk_file_chooser_get_local_only (GTK_FILE_CHOOSER (priv->dialog)))
{
pos--;
@@ -2652,38 +3015,16 @@ dialog_response_cb (GtkDialog *dialog,
if (response == GTK_RESPONSE_ACCEPT ||
response == GTK_RESPONSE_OK)
{
- g_signal_emit_by_name (user_data, "current-folder-changed");
- g_signal_emit_by_name (user_data, "selection-changed");
- }
- else if (priv->old_file)
- {
- switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)))
- {
- case GTK_FILE_CHOOSER_ACTION_OPEN:
- gtk_file_chooser_select_file (GTK_FILE_CHOOSER (dialog), priv->old_file,
- NULL);
- break;
- case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
- gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
- priv->old_file, NULL);
- break;
- default:
- g_assert_not_reached ();
- break;
- }
+ save_inactive_state (button);
+
+ g_signal_emit_by_name (button, "current-folder-changed");
+ g_signal_emit_by_name (button, "selection-changed");
}
else
- gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (dialog));
-
- if (priv->old_file)
{
- g_object_unref (priv->old_file);
- priv->old_file = NULL;
+ restore_inactive_state (button);
}
- update_label_and_image (user_data);
- update_combo_box (user_data);
-
if (priv->active)
{
g_signal_handler_unblock (priv->dialog,
@@ -2695,12 +3036,15 @@ dialog_response_cb (GtkDialog *dialog,
priv->active = FALSE;
}
+ update_label_and_image (button);
+ update_combo_box (button);
+
gtk_widget_set_sensitive (priv->combo_box, TRUE);
gtk_widget_hide (priv->dialog);
if (response == GTK_RESPONSE_ACCEPT ||
response == GTK_RESPONSE_OK)
- g_signal_emit (user_data, file_chooser_button_signals[FILE_SET], 0);
+ g_signal_emit (button, file_chooser_button_signals[FILE_SET], 0);
}
@@ -2732,33 +3076,6 @@ gtk_file_chooser_button_new (const gchar *title,
NULL);
}
-/**
- * gtk_file_chooser_button_new_with_backend:
- * @title: the title of the browse dialog.
- * @action: the open mode for the widget.
- * @backend: the name of the #GtkFileSystem backend to use.
- *
- * Creates a new file-selecting button widget using @backend.
- *
- * Returns: a new button widget.
- *
- * Since: 2.6
- * Deprecated: 2.14: Use gtk_file_chooser_button_new() instead.
- **/
-GtkWidget *
-gtk_file_chooser_button_new_with_backend (const gchar *title,
- GtkFileChooserAction action,
- const gchar *backend)
-{
- g_return_val_if_fail (action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, NULL);
-
- return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON,
- "action", action,
- "title", (title ? title : _(DEFAULT_TITLE)),
- NULL);
-}
-
/**
* gtk_file_chooser_button_new_with_dialog:
* @dialog: the widget to use as dialog
@@ -2818,7 +3135,7 @@ gtk_file_chooser_button_set_title (GtkFileChooserButton *button,
*
* Since: 2.6
**/
-G_CONST_RETURN gchar *
+const gchar *
gtk_file_chooser_button_get_title (GtkFileChooserButton *button)
{
g_return_val_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button), NULL);
@@ -2916,6 +3233,3 @@ gtk_file_chooser_button_get_focus_on_click (GtkFileChooserButton *button)
return button->priv->focus_on_click;
}
-
-#define __GTK_FILE_CHOOSER_BUTTON_C__
-#include "gtkaliasdef.c"