X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkfilechooserbutton.c;h=c66769382cffcb792689b9b834ab30be0e3e3a08;hb=b2340254109d8599244c875fe7bc5e234f64da08;hp=f00339f1ef7989a8ffa46c02c9310dc2af5277f4;hpb=09f461b01e3eed0cca58e786d08628195a4ae16e;p=~andy%2Fgtk diff --git a/gtk/gtkfilechooserbutton.c b/gtk/gtkfilechooserbutton.c index f00339f1e..c66769382 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,12 +15,10 @@ * 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 +#include "config.h" #include #include @@ -44,27 +42,66 @@ #include "gtkliststore.h" #include "gtkstock.h" #include "gtktreemodelfilter.h" -#include "gtkvseparator.h" +#include "gtkseparator.h" #include "gtkfilechooserdialog.h" #include "gtkfilechooserprivate.h" #include "gtkfilechooserutils.h" +#include "gtkmarshalers.h" #include "gtkfilechooserbutton.h" -#ifdef G_OS_WIN32 -#include "gtkfilesystemwin32.h" -#endif +#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_ICON_NAME "stock_unknown" @@ -86,6 +123,13 @@ enum PROP_WIDTH_CHARS }; +/* Signals */ +enum +{ + FILE_SET, + LAST_SIGNAL +}; + /* TreeModel Columns */ enum { @@ -94,7 +138,7 @@ enum TYPE_COLUMN, DATA_COLUMN, IS_FOLDER_COLUMN, - HANDLE_COLUMN, + CANCELLABLE_COLUMN, NUM_COLUMNS }; @@ -133,9 +177,9 @@ struct _GtkFileChooserButtonPrivate GtkTreeModel *model; GtkTreeModel *filter_model; - gchar *backend; GtkFileSystem *fs; - GtkFilePath *old_path; + GFile *selection_while_inactive; + GFile *current_folder_while_inactive; gulong combo_box_changed_id; gulong dialog_file_activated_id; @@ -144,9 +188,9 @@ struct _GtkFileChooserButtonPrivate gulong fs_volumes_changed_id; gulong fs_bookmarks_changed_id; - GtkFileSystemHandle *dnd_select_folder_handle; - GtkFileSystemHandle *update_button_handle; - GSList *change_icon_theme_handles; + GCancellable *dnd_select_folder_cancellable; + GCancellable *update_button_cancellable; + GSList *change_icon_theme_cancellables; gint icon_size; @@ -154,21 +198,15 @@ struct _GtkFileChooserButtonPrivate guint8 n_volumes; guint8 n_shortcuts; guint8 n_bookmarks; - guint8 has_bookmark_separator : 1; - guint8 has_current_folder_separator : 1; - guint8 has_current_folder : 1; - guint8 has_other_separator : 1; + guint has_bookmark_separator : 1; + guint has_current_folder_separator : 1; + guint has_current_folder : 1; + guint has_other_separator : 1; /* Used for hiding/showing the dialog when the button is hidden */ - guint8 active : 1; - - /* Used to remember whether a title has been set yet, so we can use the default if it has not been set. */ - guint8 has_title : 1; - - /* Used to track whether we need to set a default current folder on ::map() */ - guint8 folder_has_been_set : 1; + guint active : 1; - guint8 focus_on_click : 1; + guint focus_on_click : 1; }; @@ -189,11 +227,22 @@ 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, - const GtkFilePath *path, + GFile *file, GError **error); static gboolean gtk_file_chooser_button_remove_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *file, GError **error); /* GObject Functions */ @@ -210,33 +259,29 @@ 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, gint y, GtkSelectionData *data, - guint info, + 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); /* Utility Functions */ static GtkIconTheme *get_icon_theme (GtkWidget *widget); -static void set_info_for_path_at_iter (GtkFileChooserButton *fs, - const GtkFilePath *path, +static void set_info_for_file_at_iter (GtkFileChooserButton *fs, + GFile *file, GtkTreeIter *iter); static gint model_get_type_position (GtkFileChooserButton *button, @@ -250,7 +295,7 @@ static void model_add_volumes (GtkFileChooserButton *button, static void model_add_bookmarks (GtkFileChooserButton *button, GSList *bookmarks); static void model_update_current_folder (GtkFileChooserButton *button, - const GtkFilePath *path); + GFile *file); static void model_remove_rows (GtkFileChooserButton *button, gint pos, gint n_rows); @@ -301,12 +346,13 @@ static void dialog_response_cb (GtkDialog *dialog, gint response, gpointer user_data); +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) \ }) @@ -319,11 +365,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; @@ -331,18 +375,36 @@ 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; + /** + * GtkFileChooserButton::file-set: + * @widget: the object which received the signal. + * + * The ::file-set signal is emitted when the user selects a file. + * + * Note that this signal is only emitted when the user + * changes the file. + * + * Since: 2.12 + */ + file_chooser_button_signals[FILE_SET] = + g_signal_new (I_("file-set"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkFileChooserButtonClass, file_set), + NULL, NULL, + _gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** * GtkFileChooserButton:dialog: * @@ -354,7 +416,7 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class) g_param_spec_object ("dialog", P_("Dialog"), P_("The file chooser dialog to use."), - GTK_TYPE_FILE_CHOOSER_DIALOG, + GTK_TYPE_FILE_CHOOSER, (GTK_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY))); @@ -414,7 +476,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; @@ -423,12 +487,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); @@ -438,16 +503,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); @@ -460,13 +526,14 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button) G_TYPE_CHAR, /* Row Type */ G_TYPE_POINTER /* Volume || Path */, G_TYPE_BOOLEAN /* Is Folder? */, - G_TYPE_POINTER /* handle */)); + G_TYPE_POINTER /* cancellable */)); 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); + 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), @@ -506,21 +573,181 @@ 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 gboolean -gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +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); + + 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); + + 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; + } + } + } +} + +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; + } + } +} + +static GSList * +gtk_file_chooser_button_get_files (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_files (delegate); + else + { + GSList *result; + + result = NULL; + + if (priv->selection_while_inactive) + result = g_slist_prepend (NULL, 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) + result = g_slist_prepend (NULL, g_object_ref (priv->current_folder_while_inactive)); + } + + return result; + } +} + +static gboolean +gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser, + GFile *file, + GError **error) { GtkFileChooser *delegate; gboolean retval; delegate = g_object_get_qdata (G_OBJECT (chooser), GTK_FILE_CHOOSER_DELEGATE_QUARK); - retval = _gtk_file_chooser_add_shortcut_folder (delegate, path, error); + retval = _gtk_file_chooser_add_shortcut_folder (delegate, file, error); if (retval) { @@ -537,10 +764,10 @@ gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser, ICON_COLUMN, NULL, DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME), TYPE_COLUMN, ROW_TYPE_SHORTCUT, - DATA_COLUMN, gtk_file_path_copy (path), + DATA_COLUMN, g_object_ref (file), IS_FOLDER_COLUMN, FALSE, -1); - set_info_for_path_at_iter (button, path, &iter); + set_info_for_file_at_iter (button, file, &iter); priv->n_shortcuts++; gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model)); @@ -550,9 +777,9 @@ gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser, } static gboolean -gtk_file_chooser_button_remove_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +gtk_file_chooser_button_remove_shortcut_folder (GtkFileChooser *chooser, + GFile *file, + GError **error) { GtkFileChooser *delegate; gboolean retval; @@ -560,7 +787,7 @@ gtk_file_chooser_button_remove_shortcut_folder (GtkFileChooser *chooser, delegate = g_object_get_qdata (G_OBJECT (chooser), GTK_FILE_CHOOSER_DELEGATE_QUARK); - retval = _gtk_file_chooser_remove_shortcut_folder (delegate, path, error); + retval = _gtk_file_chooser_remove_shortcut_folder (delegate, file, error); if (retval) { @@ -583,8 +810,7 @@ gtk_file_chooser_button_remove_shortcut_folder (GtkFileChooser *chooser, -1); if (type == ROW_TYPE_SHORTCUT && - data && - gtk_file_path_compare (data, path) == 0) + data && g_file_equal (data, file)) { model_free_row_data (GTK_FILE_CHOOSER_BUTTON (chooser), &iter); gtk_list_store_remove (GTK_LIST_STORE (priv->model), &iter); @@ -615,33 +841,22 @@ 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, - params); + object = G_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->constructor (type, + n_params, + params); button = GTK_FILE_CHOOSER_BUTTON (object); priv = button->priv; if (!priv->dialog) { - if (priv->backend) - priv->dialog = gtk_file_chooser_dialog_new_with_backend (NULL, NULL, - GTK_FILE_CHOOSER_ACTION_OPEN, - priv->backend, - GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, - GTK_RESPONSE_ACCEPT, - NULL); - else - priv->dialog = gtk_file_chooser_dialog_new (NULL, NULL, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, - GTK_RESPONSE_ACCEPT, - NULL); + priv->dialog = gtk_file_chooser_dialog_new (NULL, NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, + GTK_RESPONSE_ACCEPT, + NULL); gtk_dialog_set_default_response (GTK_DIALOG (priv->dialog), GTK_RESPONSE_ACCEPT); @@ -649,23 +864,15 @@ gtk_file_chooser_button_constructor (GType type, GTK_RESPONSE_ACCEPT, GTK_RESPONSE_CANCEL, -1); - } - - /* Set the default title if necessary. We must wait until the dialog has been created to do this. */ - if (!priv->has_title) - 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) + gtk_file_chooser_button_set_title (button, _(DEFAULT_TITLE)); + } + else if (!gtk_window_get_title (GTK_WINDOW (priv->dialog))) { - priv->folder_has_been_set = TRUE; - g_free (current_folder); + gtk_file_chooser_button_set_title (button, _(DEFAULT_TITLE)); } - g_free (priv->backend); - priv->backend = NULL; - - g_signal_connect (priv->dialog, "delete_event", + g_signal_connect (priv->dialog, "delete-event", G_CALLBACK (dialog_delete_event_cb), object); g_signal_connect (priv->dialog, "response", G_CALLBACK (dialog_response_cb), object); @@ -687,20 +894,21 @@ gtk_file_chooser_button_constructor (GType type, g_signal_connect (priv->dialog, "notify", G_CALLBACK (dialog_notify_cb), object); g_object_add_weak_pointer (G_OBJECT (priv->dialog), - (gpointer *) (&priv->dialog)); + (gpointer) (&priv->dialog)); priv->fs = g_object_ref (_gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog))); model_add_special (button); - list = gtk_file_system_list_volumes (priv->fs); + list = _gtk_file_system_list_volumes (priv->fs); model_add_volumes (button, list); g_slist_free (list); - list = gtk_file_system_list_bookmarks (priv->fs); + list = _gtk_file_system_list_bookmarks (priv->fs); model_add_bookmarks (button, list); - gtk_file_paths_free (list); + g_slist_foreach (list, (GFunc) g_object_unref, NULL); + g_slist_free (list); model_add_other (button); @@ -793,9 +1001,6 @@ gtk_file_chooser_button_set_property (GObject *object, break; case PROP_TITLE: - /* Remember that a title has been set, so we do no try to set it to the default in _init(). */ - priv->has_title = TRUE; - /* Intentionally fall through instead of breaking here, to actually set the property. */ case GTK_FILE_CHOOSER_PROP_FILTER: case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET: case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE: @@ -803,6 +1008,7 @@ gtk_file_chooser_button_set_property (GObject *object, case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET: case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN: case GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION: + case GTK_FILE_CHOOSER_PROP_CREATE_FOLDERS: g_object_set_property (G_OBJECT (priv->dialog), pspec->name, value); break; @@ -812,11 +1018,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: - /* Construct-only */ - priv->backend = g_value_dup_string (value); - 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)); @@ -849,7 +1050,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: @@ -859,6 +1059,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; @@ -874,21 +1075,23 @@ gtk_file_chooser_button_finalize (GObject *object) GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object); GtkFileChooserButtonPrivate *priv = button->priv; - if (priv->old_path) - gtk_file_path_free (priv->old_path); + 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); - if (G_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->finalize != NULL) - (*G_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->finalize) (object); + 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; @@ -905,27 +1108,27 @@ gtk_file_chooser_button_destroy (GtkObject *object) } while (gtk_tree_model_iter_next (priv->model, &iter)); - if (priv->dnd_select_folder_handle) + if (priv->dnd_select_folder_cancellable) { - gtk_file_system_cancel_operation (priv->dnd_select_folder_handle); - priv->dnd_select_folder_handle = NULL; + g_cancellable_cancel (priv->dnd_select_folder_cancellable); + priv->dnd_select_folder_cancellable = NULL; } - if (priv->update_button_handle) + if (priv->update_button_cancellable) { - gtk_file_system_cancel_operation (priv->update_button_handle); - priv->update_button_handle = NULL; + g_cancellable_cancel (priv->update_button_cancellable); + priv->update_button_cancellable = NULL; } - if (priv->change_icon_theme_handles) + if (priv->change_icon_theme_cancellables) { - for (l = priv->change_icon_theme_handles; l; l = l->next) + for (l = priv->change_icon_theme_cancellables; l; l = l->next) { - GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (l->data); - gtk_file_system_cancel_operation (handle); + GCancellable *cancellable = G_CANCELLABLE (l->data); + g_cancellable_cancel (cancellable); } - g_slist_free (priv->change_icon_theme_handles); - priv->change_icon_theme_handles = NULL; + g_slist_free (priv->change_icon_theme_cancellables); + priv->change_icon_theme_cancellables = NULL; } if (priv->model) @@ -948,83 +1151,81 @@ gtk_file_chooser_button_destroy (GtkObject *object) priv->fs = NULL; } - if (GTK_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->destroy != 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; GtkFileChooserButton *button; GtkFileChooserAction action; - GtkFilePath *path; + GFile *file; gchar **uris; guint i; gboolean selected; }; static void -dnd_select_folder_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +dnd_select_folder_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); struct DndSelectFolderData *data = user_data; - if (handle != data->button->priv->dnd_select_folder_handle) + if (cancellable != data->button->priv->dnd_select_folder_cancellable) { g_object_unref (data->button); - gtk_file_path_free (data->path); + g_object_unref (data->file); g_strfreev (data->uris); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); return; } - data->button->priv->dnd_select_folder_handle = NULL; + data->button->priv->dnd_select_folder_cancellable = NULL; if (!cancelled && !error && info != NULL) { - data->selected = - (((data->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER && - gtk_file_info_get_is_folder (info)) || - (data->action == GTK_FILE_CHOOSER_ACTION_OPEN && - !gtk_file_info_get_is_folder (info))) && - _gtk_file_chooser_select_path (GTK_FILE_CHOOSER (data->button->priv->dialog), - data->path, NULL)); + gboolean is_folder; + + is_folder = _gtk_file_info_consider_as_directory (info); + + data->selected = + (((data->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER && is_folder) || + (data->action == GTK_FILE_CHOOSER_ACTION_OPEN && !is_folder)) && + gtk_file_chooser_select_file (GTK_FILE_CHOOSER (data->button->priv->dialog), + data->file, NULL)); } else data->selected = FALSE; if (data->selected || data->uris[++data->i] == NULL) { + g_signal_emit (data->button, file_chooser_button_signals[FILE_SET], 0); + g_object_unref (data->button); - gtk_file_path_free (data->path); + g_object_unref (data->file); g_strfreev (data->uris); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); return; } - if (data->path) - gtk_file_path_free (data->path); + if (data->file) + g_object_unref (data->file); - data->path = gtk_file_system_uri_to_path (handle->file_system, - data->uris[data->i]); + data->file = g_file_new_for_uri (data->uris[data->i]); - data->button->priv->dnd_select_folder_handle = - gtk_file_system_get_info (handle->file_system, data->path, - GTK_FILE_INFO_IS_FOLDER, - dnd_select_folder_get_info_cb, user_data); + data->button->priv->dnd_select_folder_cancellable = + _gtk_file_system_get_info (data->file_system, data->file, + "standard::type", + dnd_select_folder_get_info_cb, user_data); - g_object_unref (handle); + g_object_unref (cancellable); } static void @@ -1033,25 +1234,25 @@ gtk_file_chooser_button_drag_data_received (GtkWidget *widget, gint x, gint y, GtkSelectionData *data, - guint info, + guint type, guint drag_time) { GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget); GtkFileChooserButtonPrivate *priv = button->priv; - GtkFilePath *path; + GFile *file; gchar *text; if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->drag_data_received != NULL) - (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->drag_data_received) (widget, - context, - x, y, - data, info, - drag_time); + GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->drag_data_received (widget, + context, + x, y, + 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 (info) + switch (type) { case TEXT_URI_LIST: { @@ -1068,27 +1269,29 @@ gtk_file_chooser_button_drag_data_received (GtkWidget *widget, info->i = 0; info->uris = uris; info->selected = FALSE; + info->file_system = priv->fs; g_object_get (priv->dialog, "action", &info->action, NULL); - info->path = gtk_file_system_uri_to_path (priv->fs, - info->uris[info->i]); + info->file = g_file_new_for_uri (info->uris[info->i]); - if (priv->dnd_select_folder_handle) - gtk_file_system_cancel_operation (priv->dnd_select_folder_handle); + if (priv->dnd_select_folder_cancellable) + g_cancellable_cancel (priv->dnd_select_folder_cancellable); - priv->dnd_select_folder_handle = - gtk_file_system_get_info (priv->fs, info->path, - GTK_FILE_INFO_IS_FOLDER, - dnd_select_folder_get_info_cb, info); + priv->dnd_select_folder_cancellable = + _gtk_file_system_get_info (priv->fs, info->file, + "standard::type", + dnd_select_folder_get_info_cb, info); } break; case TEXT_PLAIN: text = (char*) gtk_selection_data_get_text (data); - path = gtk_file_path_new_steal (text); - _gtk_file_chooser_select_path (GTK_FILE_CHOOSER (priv->dialog), path, - NULL); - gtk_file_path_free (path); + file = g_file_new_for_uri (text); + gtk_file_chooser_select_file (GTK_FILE_CHOOSER (priv->dialog), file, + NULL); + g_object_unref (file); + g_free (text); + g_signal_emit (button, file_chooser_button_signals[FILE_SET], 0); break; default: @@ -1104,12 +1307,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) { @@ -1117,7 +1314,7 @@ gtk_file_chooser_button_show (GtkWidget *widget) GtkFileChooserButtonPrivate *priv = button->priv; if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->show) - (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->show) (widget); + GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->show (widget); if (priv->active) open_dialog (GTK_FILE_CHOOSER_BUTTON (widget)); @@ -1132,28 +1329,13 @@ gtk_file_chooser_button_hide (GtkWidget *widget) gtk_widget_hide (priv->dialog); if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->hide) - (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->hide) (widget); + GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->hide (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; - } - - if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->map) - (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->map) (widget); + GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->map (widget); } static gboolean @@ -1187,26 +1369,25 @@ struct ChangeIconThemeData }; static void -change_icon_theme_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +change_icon_theme_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GdkPixbuf *pixbuf; struct ChangeIconThemeData *data = user_data; - if (!g_slist_find (data->button->priv->change_icon_theme_handles, handle)) + if (!g_slist_find (data->button->priv->change_icon_theme_cancellables, cancellable)) goto out; - data->button->priv->change_icon_theme_handles = - g_slist_remove (data->button->priv->change_icon_theme_handles, handle); + data->button->priv->change_icon_theme_cancellables = + g_slist_remove (data->button->priv->change_icon_theme_cancellables, cancellable); if (cancelled || error) goto out; - pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->button), - data->button->priv->icon_size, NULL); + pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (data->button), data->button->priv->icon_size); if (pixbuf) { @@ -1217,17 +1398,20 @@ change_icon_theme_get_info_cb (GtkFileSystemHandle *handle, width = MAX (width, gdk_pixbuf_get_width (pixbuf)); path = gtk_tree_row_reference_get_path (data->row_ref); - gtk_tree_model_get_iter (data->button->priv->model, &iter, path); - gtk_tree_path_free (path); + if (path) + { + gtk_tree_model_get_iter (data->button->priv->model, &iter, path); + gtk_tree_path_free (path); - gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter, - ICON_COLUMN, pixbuf, - -1); - g_object_unref (pixbuf); + gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter, + ICON_COLUMN, pixbuf, + -1); - g_object_set (data->button->priv->icon_cell, - "width", width, - NULL); + g_object_set (data->button->priv->icon_cell, + "width", width, + NULL); + } + g_object_unref (pixbuf); } out: @@ -1235,7 +1419,7 @@ out: gtk_tree_row_reference_free (data->row_ref); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } static void @@ -1248,13 +1432,13 @@ change_icon_theme (GtkFileChooserButton *button) GSList *l; gint width = 0, height = 0; - for (l = button->priv->change_icon_theme_handles; l; l = l->next) + for (l = button->priv->change_icon_theme_cancellables; l; l = l->next) { - GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (l->data); - gtk_file_system_cancel_operation (handle); + GCancellable *cancellable = G_CANCELLABLE (l->data); + g_cancellable_cancel (cancellable); } - g_slist_free (button->priv->change_icon_theme_handles); - button->priv->change_icon_theme_handles = NULL; + g_slist_free (button->priv->change_icon_theme_cancellables); + button->priv->change_icon_theme_cancellables = NULL; settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (button))); @@ -1290,10 +1474,10 @@ change_icon_theme (GtkFileChooserButton *button) case ROW_TYPE_CURRENT_FOLDER: if (data) { - if (gtk_file_system_path_is_local (priv->fs, (GtkFilePath *)data)) + if (g_file_is_native (G_FILE (data))) { GtkTreePath *path; - GtkFileSystemHandle *handle; + GCancellable *cancellable; struct ChangeIconThemeData *info; info = g_new0 (struct ChangeIconThemeData, 1); @@ -1301,13 +1485,14 @@ change_icon_theme (GtkFileChooserButton *button) path = gtk_tree_model_get_path (priv->model, &iter); info->row_ref = gtk_tree_row_reference_new (priv->model, path); gtk_tree_path_free (path); - - handle = - gtk_file_system_get_info (priv->fs, data, GTK_FILE_INFO_ICON, - change_icon_theme_get_info_cb, - info); - button->priv->change_icon_theme_handles = - g_slist_append (button->priv->change_icon_theme_handles, handle); + + cancellable = + _gtk_file_system_get_info (priv->fs, data, + "standard::icon", + change_icon_theme_get_info_cb, + info); + button->priv->change_icon_theme_cancellables = + g_slist_append (button->priv->change_icon_theme_cancellables, cancellable); pixbuf = NULL; } else @@ -1316,7 +1501,7 @@ change_icon_theme (GtkFileChooserButton *button) * If we switch to a better bookmarks file format (XBEL), we * should use mime info to get a better icon. */ - pixbuf = gtk_icon_theme_load_icon (theme, "gnome-fs-regular", + pixbuf = gtk_icon_theme_load_icon (theme, "folder-remote", priv->icon_size, 0, NULL); } else @@ -1325,10 +1510,10 @@ change_icon_theme (GtkFileChooserButton *button) break; case ROW_TYPE_VOLUME: if (data) - pixbuf = gtk_file_system_volume_render_icon (priv->fs, data, - GTK_WIDGET (button), - priv->icon_size, - NULL); + pixbuf = _gtk_file_system_volume_render_icon (data, + GTK_WIDGET (button), + priv->icon_size, + NULL); else pixbuf = gtk_icon_theme_load_icon (theme, FALLBACK_ICON_NAME, priv->icon_size, 0, NULL); @@ -1356,12 +1541,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) { - if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->style_set) - (*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)); @@ -1372,10 +1554,10 @@ gtk_file_chooser_button_screen_changed (GtkWidget *widget, GdkScreen *old_screen) { if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->screen_changed) - (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->screen_changed) (widget, - old_screen); + GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->screen_changed (widget, + old_screen); - change_icon_theme (GTK_FILE_CHOOSER_BUTTON (widget)); + change_icon_theme (GTK_FILE_CHOOSER_BUTTON (widget)); } @@ -1402,17 +1584,18 @@ struct SetDisplayNameData }; static void -set_info_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer callback_data) +set_info_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer callback_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GdkPixbuf *pixbuf; GtkTreePath *path; GtkTreeIter iter; - GtkFileSystemHandle *model_handle; + GCancellable *model_cancellable = NULL; struct SetDisplayNameData *data = callback_data; + gboolean is_folder; if (!data->button->priv->model) /* button got destroyed */ @@ -1420,37 +1603,38 @@ set_info_get_info_cb (GtkFileSystemHandle *handle, path = gtk_tree_row_reference_get_path (data->row_ref); if (!path) - /* Handle doesn't exist anymore in the model */ + /* Cancellable doesn't exist anymore in the model */ goto out; gtk_tree_model_get_iter (data->button->priv->model, &iter, path); gtk_tree_path_free (path); - /* Validate the handle */ + /* Validate the cancellable */ gtk_tree_model_get (data->button->priv->model, &iter, - HANDLE_COLUMN, &model_handle, + CANCELLABLE_COLUMN, &model_cancellable, -1); - if (handle != model_handle) + if (cancellable != model_cancellable) goto out; gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter, - HANDLE_COLUMN, NULL, + CANCELLABLE_COLUMN, NULL, -1); if (cancelled || error) /* There was an error, leave the fallback name in there */ goto out; - pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->button), - data->button->priv->icon_size, NULL); + pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (data->button), data->button->priv->icon_size); if (!data->label) - data->label = g_strdup (gtk_file_info_get_display_name (info)); + data->label = g_strdup (g_file_info_get_display_name (info)); + + is_folder = _gtk_file_info_consider_as_directory (info); gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter, ICON_COLUMN, pixbuf, DISPLAY_NAME_COLUMN, data->label, - IS_FOLDER_COLUMN, gtk_file_info_get_is_folder (info), + IS_FOLDER_COLUMN, is_folder, -1); if (pixbuf) @@ -1462,32 +1646,33 @@ out: gtk_tree_row_reference_free (data->row_ref); g_free (data); - g_object_unref (handle); + if (model_cancellable) + g_object_unref (model_cancellable); } static void -set_info_for_path_at_iter (GtkFileChooserButton *button, - const GtkFilePath *path, +set_info_for_file_at_iter (GtkFileChooserButton *button, + GFile *file, GtkTreeIter *iter) { struct SetDisplayNameData *data; GtkTreePath *tree_path; - GtkFileSystemHandle *handle; + GCancellable *cancellable; data = g_new0 (struct SetDisplayNameData, 1); data->button = g_object_ref (button); - data->label = gtk_file_system_get_bookmark_label (button->priv->fs, path); + data->label = _gtk_file_system_get_bookmark_label (button->priv->fs, file); tree_path = gtk_tree_model_get_path (button->priv->model, iter); data->row_ref = gtk_tree_row_reference_new (button->priv->model, tree_path); gtk_tree_path_free (tree_path); - handle = gtk_file_system_get_info (button->priv->fs, path, - GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_IS_FOLDER | GTK_FILE_INFO_ICON, - set_info_get_info_cb, data); + cancellable = _gtk_file_system_get_info (button->priv->fs, file, + "standard::type,standard::icon,standard::display-name", + set_info_get_info_cb, data); gtk_list_store_set (GTK_LIST_STORE (button->priv->model), iter, - HANDLE_COLUMN, handle, + CANCELLABLE_COLUMN, cancellable, -1); } @@ -1551,16 +1736,19 @@ model_free_row_data (GtkFileChooserButton *button, { gchar type; gpointer data; - GtkFileSystemHandle *handle; + GCancellable *cancellable; gtk_tree_model_get (button->priv->model, iter, TYPE_COLUMN, &type, DATA_COLUMN, &data, - HANDLE_COLUMN, &handle, + CANCELLABLE_COLUMN, &cancellable, -1); - if (handle) - gtk_file_system_cancel_operation (handle); + if (cancellable) + { + g_cancellable_cancel (cancellable); + g_object_unref (cancellable); + } switch (type) { @@ -1568,10 +1756,10 @@ model_free_row_data (GtkFileChooserButton *button, case ROW_TYPE_SHORTCUT: case ROW_TYPE_BOOKMARK: case ROW_TYPE_CURRENT_FOLDER: - gtk_file_path_free (data); + g_object_unref (data); break; case ROW_TYPE_VOLUME: - gtk_file_system_volume_free (button->priv->fs, data); + _gtk_file_system_volume_unref (data); break; default: break; @@ -1579,17 +1767,18 @@ model_free_row_data (GtkFileChooserButton *button, } static void -model_add_special_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +model_add_special_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GtkTreeIter iter; GtkTreePath *path; GdkPixbuf *pixbuf; - GtkFileSystemHandle *model_handle; + GCancellable *model_cancellable = NULL; struct ChangeIconThemeData *data = user_data; + gchar *name; if (!data->button->priv->model) /* button got destroyed */ @@ -1597,27 +1786,26 @@ model_add_special_get_info_cb (GtkFileSystemHandle *handle, path = gtk_tree_row_reference_get_path (data->row_ref); if (!path) - /* Handle doesn't exist anymore in the model */ + /* Cancellable doesn't exist anymore in the model */ goto out; gtk_tree_model_get_iter (data->button->priv->model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (data->button->priv->model, &iter, - HANDLE_COLUMN, &model_handle, + CANCELLABLE_COLUMN, &model_cancellable, -1); - if (handle != model_handle) + if (cancellable != model_cancellable) goto out; gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter, - HANDLE_COLUMN, NULL, + CANCELLABLE_COLUMN, NULL, -1); if (cancelled || error) goto out; - pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->button), - data->button->priv->icon_size, NULL); + pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (data->button), data->button->priv->icon_size); if (pixbuf) { @@ -1627,26 +1815,32 @@ model_add_special_get_info_cb (GtkFileSystemHandle *handle, g_object_unref (pixbuf); } - gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter, - DISPLAY_NAME_COLUMN, gtk_file_info_get_display_name (info), - -1); - + gtk_tree_model_get (data->button->priv->model, &iter, + DISPLAY_NAME_COLUMN, &name, + -1); + if (!name) + gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter, + DISPLAY_NAME_COLUMN, g_file_info_get_display_name (info), + -1); + g_free (name); + out: g_object_unref (data->button); gtk_tree_row_reference_free (data->row_ref); g_free (data); - g_object_unref (handle); + if (model_cancellable) + g_object_unref (model_cancellable); } static inline void model_add_special (GtkFileChooserButton *button) { const gchar *homedir; - gchar *desktopdir = NULL; + const gchar *desktopdir; GtkListStore *store; GtkTreeIter iter; - GtkFilePath *path; + GFile *file; gint pos; store = GTK_LIST_STORE (button->priv->model); @@ -1657,10 +1851,10 @@ model_add_special (GtkFileChooserButton *button) if (homedir) { GtkTreePath *tree_path; - GtkFileSystemHandle *handle; + GCancellable *cancellable; struct ChangeIconThemeData *info; - path = gtk_file_system_filename_to_path (button->priv->fs, homedir); + file = g_file_new_for_path (homedir); gtk_list_store_insert (store, &iter, pos); pos++; @@ -1671,38 +1865,34 @@ model_add_special (GtkFileChooserButton *button) tree_path); gtk_tree_path_free (tree_path); - handle = gtk_file_system_get_info (button->priv->fs, path, - GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_ICON, - model_add_special_get_info_cb, info); + cancellable = _gtk_file_system_get_info (button->priv->fs, file, + "standard::icon,standard::display-name", + model_add_special_get_info_cb, info); gtk_list_store_set (store, &iter, ICON_COLUMN, NULL, DISPLAY_NAME_COLUMN, NULL, TYPE_COLUMN, ROW_TYPE_SPECIAL, - DATA_COLUMN, path, + DATA_COLUMN, file, IS_FOLDER_COLUMN, TRUE, - HANDLE_COLUMN, handle, + CANCELLABLE_COLUMN, cancellable, -1); button->priv->n_special++; - -#ifndef G_OS_WIN32 - desktopdir = g_build_filename (homedir, DESKTOP_DISPLAY_NAME, NULL); -#endif } -#ifdef G_OS_WIN32 - desktopdir = _gtk_file_system_win32_get_desktop (); -#endif + 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; - GtkFileSystemHandle *handle; + GCancellable *cancellable; struct ChangeIconThemeData *info; - path = gtk_file_system_filename_to_path (button->priv->fs, desktopdir); - g_free (desktopdir); + file = g_file_new_for_path (desktopdir); gtk_list_store_insert (store, &iter, pos); pos++; @@ -1713,17 +1903,17 @@ model_add_special (GtkFileChooserButton *button) tree_path); gtk_tree_path_free (tree_path); - handle = gtk_file_system_get_info (button->priv->fs, path, - GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_ICON, - model_add_special_get_info_cb, info); + cancellable = _gtk_file_system_get_info (button->priv->fs, file, + "standard::icon,standard::display-name", + model_add_special_get_info_cb, info); gtk_list_store_set (store, &iter, TYPE_COLUMN, ROW_TYPE_SPECIAL, ICON_COLUMN, NULL, DISPLAY_NAME_COLUMN, _(DESKTOP_DISPLAY_NAME), - DATA_COLUMN, path, + DATA_COLUMN, file, IS_FOLDER_COLUMN, TRUE, - HANDLE_COLUMN, handle, + CANCELLABLE_COLUMN, cancellable, -1); button->priv->n_special++; @@ -1732,21 +1922,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) { @@ -1758,44 +1946,42 @@ model_add_volumes (GtkFileChooserButton *button, volume = l->data; if (local_only) - { - if (gtk_file_system_volume_get_is_mounted (file_system, volume)) - { - GtkFilePath *base_path; - - base_path = gtk_file_system_volume_get_base_path (file_system, volume); - if (base_path != NULL) - { - gboolean is_local = gtk_file_system_path_is_local (file_system, base_path); - gtk_file_path_free (base_path); - - if (!is_local) - { - gtk_file_system_volume_free (file_system, 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 (!g_file_is_native (base_file)) + { + g_object_unref (base_file); + continue; + } + else + g_object_unref (base_file); + } + } + } - pixbuf = gtk_file_system_volume_render_icon (file_system, - volume, - GTK_WIDGET (button), - button->priv->icon_size, - NULL); - display_name = gtk_file_system_volume_get_display_name (file_system, volume); + pixbuf = _gtk_file_system_volume_render_icon (volume, + 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++; @@ -1803,7 +1989,7 @@ model_add_volumes (GtkFileChooserButton *button, } } -extern gchar * _gtk_file_chooser_label_for_uri (const gchar *uri); +extern gchar * _gtk_file_chooser_label_for_file (GFile *file); static void model_add_bookmarks (GtkFileChooserButton *button, @@ -1824,21 +2010,21 @@ model_add_bookmarks (GtkFileChooserButton *button, for (l = bookmarks; l; l = l->next) { - GtkFilePath *path; + GFile *file; - path = l->data; + file = l->data; - if (gtk_file_system_path_is_local (button->priv->fs, path)) + if (g_file_is_native (file)) { 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_BOOKMARK, - DATA_COLUMN, gtk_file_path_copy (path), + DATA_COLUMN, g_object_ref (file), IS_FOLDER_COLUMN, FALSE, -1); - set_info_for_path_at_iter (button, path, &iter); + set_info_for_file_at_iter (button, file, &iter); } else { @@ -1854,18 +2040,12 @@ model_add_bookmarks (GtkFileChooserButton *button, * If we switch to a better bookmarks file format (XBEL), we * should use mime info to get a better icon. */ - label = gtk_file_system_get_bookmark_label (button->priv->fs, path); + label = _gtk_file_system_get_bookmark_label (button->priv->fs, file); if (!label) - { - gchar *uri; - - uri = gtk_file_system_path_to_uri (button->priv->fs, path); - label = _gtk_file_chooser_label_for_uri (uri); - g_free (uri); - } + label = _gtk_file_chooser_label_for_file (file); icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (button))); - pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-directory", + pixbuf = gtk_icon_theme_load_icon (icon_theme, "folder-remote", button->priv->icon_size, 0, NULL); gtk_list_store_insert (store, &iter, pos); @@ -1873,7 +2053,7 @@ model_add_bookmarks (GtkFileChooserButton *button, ICON_COLUMN, pixbuf, DISPLAY_NAME_COLUMN, label, TYPE_COLUMN, ROW_TYPE_BOOKMARK, - DATA_COLUMN, gtk_file_path_copy (path), + DATA_COLUMN, g_object_ref (file), IS_FOLDER_COLUMN, TRUE, -1); @@ -1904,13 +2084,13 @@ model_add_bookmarks (GtkFileChooserButton *button, static void model_update_current_folder (GtkFileChooserButton *button, - const GtkFilePath *path) + GFile *file) { GtkListStore *store; GtkTreeIter iter; gint pos; - if (!path) + if (!file) return; store = GTK_LIST_STORE (button->priv->model); @@ -1941,16 +2121,16 @@ model_update_current_folder (GtkFileChooserButton *button, model_free_row_data (button, &iter); } - if (gtk_file_system_path_is_local (button->priv->fs, path)) + if (g_file_is_native (file)) { gtk_list_store_set (store, &iter, ICON_COLUMN, NULL, DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME), TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER, - DATA_COLUMN, gtk_file_path_copy (path), + DATA_COLUMN, g_object_ref (file), IS_FOLDER_COLUMN, FALSE, -1); - set_info_for_path_at_iter (button, path, &iter); + set_info_for_file_at_iter (button, file, &iter); } else { @@ -1963,28 +2143,27 @@ model_update_current_folder (GtkFileChooserButton *button, * If we switch to a better bookmarks file format (XBEL), we * should use mime info to get a better icon. */ - label = gtk_file_system_get_bookmark_label (button->priv->fs, path); + label = _gtk_file_system_get_bookmark_label (button->priv->fs, file); if (!label) - { - gchar *uri; - - uri = gtk_file_system_path_to_uri (button->priv->fs, path); - label = _gtk_file_chooser_label_for_uri (uri); - g_free (uri); - } - + label = _gtk_file_chooser_label_for_file (file); + icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (button))); - pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-directory", - button->priv->icon_size, 0, NULL); - + + if (g_file_is_native (file)) + pixbuf = gtk_icon_theme_load_icon (icon_theme, "folder", + button->priv->icon_size, 0, NULL); + else + pixbuf = gtk_icon_theme_load_icon (icon_theme, "folder-remote", + button->priv->icon_size, 0, NULL); + gtk_list_store_set (store, &iter, ICON_COLUMN, pixbuf, DISPLAY_NAME_COLUMN, label, TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER, - DATA_COLUMN, gtk_file_path_copy (path), + DATA_COLUMN, g_object_ref (file), IS_FOLDER_COLUMN, TRUE, -1); - + g_free (label); g_object_unref (pixbuf); } @@ -2014,7 +2193,7 @@ 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, @@ -2049,15 +2228,15 @@ model_remove_rows (GtkFileChooserButton *button, /* Filter Model */ static inline gboolean -test_if_path_is_visible (GtkFileSystem *fs, - const GtkFilePath *path, - gboolean local_only, - gboolean is_folder) +test_if_file_is_visible (GtkFileSystem *fs, + GFile *file, + gboolean local_only, + gboolean is_folder) { - if (!path) + if (!file) return FALSE; - if (local_only && !gtk_file_system_path_is_local (fs, path)) + if (local_only && !g_file_is_native (file)) return FALSE; if (!is_folder) @@ -2095,26 +2274,24 @@ filter_model_visible_func (GtkTreeModel *model, case ROW_TYPE_SPECIAL: case ROW_TYPE_SHORTCUT: case ROW_TYPE_BOOKMARK: - retval = test_if_path_is_visible (priv->fs, data, local_only, is_folder); + retval = test_if_file_is_visible (priv->fs, data, local_only, is_folder); break; case ROW_TYPE_VOLUME: { retval = TRUE; if (local_only) { - if (gtk_file_system_volume_get_is_mounted (priv->fs, data)) + if (_gtk_file_system_volume_is_mounted (data)) { - GtkFilePath *base_path; - - base_path = gtk_file_system_volume_get_base_path (priv->fs, data); - if (base_path) - { - gboolean is_local = gtk_file_system_path_is_local (priv->fs, base_path); - - gtk_file_path_free (base_path); + GFile *base_file; + + base_file = _gtk_file_system_volume_get_root (data); - if (!is_local) + if (base_file) + { + if (!g_file_is_native (base_file)) retval = FALSE; + g_object_unref (base_file); } else retval = FALSE; @@ -2169,13 +2346,13 @@ static void update_combo_box (GtkFileChooserButton *button) { GtkFileChooserButtonPrivate *priv = button->priv; - GSList *paths; + GFile *file; GtkTreeIter iter; gboolean row_found; gtk_tree_model_get_iter_first (priv->filter_model, &iter); - paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog)); + file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (priv->dialog)); row_found = FALSE; @@ -2198,19 +2375,18 @@ update_combo_box (GtkFileChooserButton *button) case ROW_TYPE_SHORTCUT: case ROW_TYPE_BOOKMARK: case ROW_TYPE_CURRENT_FOLDER: - row_found = (paths && - paths->data && - gtk_file_path_compare (data, paths->data) == 0); + row_found = (file && g_file_equal (data, file)); break; case ROW_TYPE_VOLUME: { - GtkFilePath *base_path; - - base_path = gtk_file_system_volume_get_base_path (priv->fs, data); - row_found = (paths && - paths->data && - gtk_file_path_compare (base_path, paths->data) == 0); - gtk_file_path_free (base_path); + GFile *base_file; + + base_file = _gtk_file_system_volume_get_root (data); + if (base_file) + { + row_found = (file && g_file_equal (base_file, file)); + g_object_unref (base_file); + } } break; default: @@ -2230,12 +2406,12 @@ 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 && paths && paths->data) + if (!row_found && file) { GtkTreeIter filter_iter; gint pos; - model_update_current_folder (button, paths->data); + model_update_current_folder (button, file); gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model)); pos = model_get_type_position (button, ROW_TYPE_CURRENT_FOLDER); @@ -2249,33 +2425,34 @@ update_combo_box (GtkFileChooserButton *button) g_signal_handler_unblock (priv->combo_box, priv->combo_box_changed_id); } - gtk_file_paths_free (paths); + if (file) + g_object_unref (file); } /* Button */ static void -update_label_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer data) +update_label_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GdkPixbuf *pixbuf; GtkFileChooserButton *button = data; GtkFileChooserButtonPrivate *priv = button->priv; - if (handle != priv->update_button_handle) + if (cancellable != priv->update_button_cancellable) goto out; - priv->update_button_handle = NULL; + priv->update_button_cancellable = NULL; if (cancelled || error) goto out; - gtk_label_set_text (GTK_LABEL (priv->label), gtk_file_info_get_display_name (info)); + gtk_label_set_text (GTK_LABEL (priv->label), g_file_info_get_display_name (info)); + + pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (priv->image), priv->icon_size); - pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (priv->image), - priv->icon_size, NULL); if (!pixbuf) pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (priv->image)), FALLBACK_ICON_NAME, @@ -2287,85 +2464,82 @@ update_label_get_info_cb (GtkFileSystemHandle *handle, out: g_object_unref (button); - g_object_unref (handle); + g_object_unref (cancellable); } static void update_label_and_image (GtkFileChooserButton *button) { GtkFileChooserButtonPrivate *priv = button->priv; - GdkPixbuf *pixbuf; gchar *label_text; - GSList *paths; + GFile *file; - paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog)); + file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (priv->dialog)); label_text = NULL; - pixbuf = NULL; - if (paths && paths->data) + if (priv->update_button_cancellable) + { + g_cancellable_cancel (priv->update_button_cancellable); + priv->update_button_cancellable = NULL; + } + + if (file) { - GtkFilePath *path; GtkFileSystemVolume *volume = NULL; - - path = paths->data; - volume = gtk_file_system_get_volume_for_path (priv->fs, path); + volume = _gtk_file_system_get_volume_for_file (priv->fs, file); if (volume) - { - GtkFilePath *base_path; - - base_path = gtk_file_system_volume_get_base_path (priv->fs, volume); - if (base_path && gtk_file_path_compare (base_path, path) == 0) - { - label_text = gtk_file_system_volume_get_display_name (priv->fs, - volume); - pixbuf = gtk_file_system_volume_render_icon (priv->fs, volume, - GTK_WIDGET (button), - priv->icon_size, - NULL); - } - - if (base_path) - gtk_file_path_free (base_path); - - gtk_file_system_volume_free (priv->fs, volume); - - if (label_text) - goto out; - } + { + GFile *base_file; + + base_file = _gtk_file_system_volume_get_root (volume); + if (base_file && g_file_equal (base_file, file)) + { + GdkPixbuf *pixbuf; + + 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); + } + + if (base_file) + g_object_unref (base_file); + + _gtk_file_system_volume_unref (volume); + + if (label_text) + goto out; + } - if (priv->update_button_handle) - { - gtk_file_system_cancel_operation (priv->update_button_handle); - priv->upate_button_handle = NULL; - } - - if (gtk_file_system_path_is_local (priv->fs, path)) - { - priv->update_button_handle = - gtk_file_system_get_info (priv->fs, path, - GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_ICON, - update_label_get_info_cb, - g_object_ref (button)); - } + 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)); + } else - { - GdkPixbuf *pixbuf; - - label_text = gtk_file_system_get_bookmark_label (button->priv->fs, path); - - pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (priv->image)), - "gnome-fs-regular", - priv->icon_size, 0, NULL); - - gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), 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); + if (pixbuf) + g_object_unref (pixbuf); + } - if (pixbuf) - g_object_unref (pixbuf); - } + g_object_unref (file); } out: - gtk_file_paths_free (paths); if (label_text) { @@ -2373,7 +2547,10 @@ out: g_free (label_text); } else - gtk_label_set_text (GTK_LABEL (priv->label), _(FALLBACK_DISPLAY_NAME)); + { + gtk_label_set_text (GTK_LABEL (priv->label), _(FALLBACK_DISPLAY_NAME)); + gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), NULL); + } } @@ -2396,7 +2573,7 @@ fs_volumes_changed_cb (GtkFileSystem *fs, priv->n_volumes = 0; - volumes = gtk_file_system_list_volumes (fs); + volumes = _gtk_file_system_list_volumes (fs); model_add_volumes (user_data, volumes); g_slist_free (volumes); @@ -2414,7 +2591,7 @@ fs_bookmarks_changed_cb (GtkFileSystem *fs, GtkFileChooserButtonPrivate *priv = button->priv; GSList *bookmarks; - bookmarks = gtk_file_system_list_bookmarks (fs); + bookmarks = _gtk_file_system_list_bookmarks (fs); model_remove_rows (user_data, model_get_type_position (user_data, ROW_TYPE_BOOKMARK_SEPARATOR), @@ -2422,7 +2599,8 @@ fs_bookmarks_changed_cb (GtkFileSystem *fs, priv->has_bookmark_separator = FALSE; priv->n_bookmarks = 0; model_add_bookmarks (user_data, bookmarks); - gtk_file_paths_free (bookmarks); + g_slist_foreach (bookmarks, (GFunc) g_object_unref, NULL); + g_slist_free (bookmarks); gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model)); @@ -2430,6 +2608,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) @@ -2438,13 +2645,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), @@ -2457,22 +2664,14 @@ open_dialog (GtkFileChooserButton *button) if (!priv->active) { - GSList *paths; - 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); - paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog)); - if (paths) - { - if (paths->data) - priv->old_path = gtk_file_path_copy (paths->data); - gtk_file_paths_free (paths); - } + restore_inactive_state (button); priv->active = TRUE; } @@ -2511,20 +2710,20 @@ combo_box_changed_cb (GtkComboBox *combo_box, case ROW_TYPE_CURRENT_FOLDER: gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog)); if (data) - _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog), - data, NULL); + gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (priv->dialog), + data, NULL); break; case ROW_TYPE_VOLUME: { - GtkFilePath *base_path; + GFile *base_file; gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog)); - base_path = gtk_file_system_volume_get_base_path (priv->fs, data); - if (base_path) + base_file = _gtk_file_system_volume_get_root (data); + if (base_file) { - _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog), - base_path, NULL); - gtk_file_path_free (base_path); + gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (priv->dialog), + base_file, NULL); + g_object_unref (base_file); } } break; @@ -2551,9 +2750,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"); } @@ -2613,9 +2809,8 @@ 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 && - (!gtk_file_system_path_is_local (priv->fs, data) && - gtk_file_chooser_get_local_only (GTK_FILE_CHOOSER (priv->dialog)))) + if (data && g_file_is_native (G_FILE (data)) && + gtk_file_chooser_get_local_only (GTK_FILE_CHOOSER (priv->dialog))) { pos--; model_remove_rows (user_data, pos, 2); @@ -2645,40 +2840,22 @@ dialog_response_cb (GtkDialog *dialog, GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (user_data); GtkFileChooserButtonPrivate *priv = button->priv; - if (response == GTK_RESPONSE_ACCEPT) - { - g_signal_emit_by_name (user_data, "current-folder-changed"); - g_signal_emit_by_name (user_data, "selection-changed"); - } - else if (priv->old_path) + if (response == GTK_RESPONSE_ACCEPT || + response == GTK_RESPONSE_OK) { - switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog))) - { - case GTK_FILE_CHOOSER_ACTION_OPEN: - _gtk_file_chooser_select_path (GTK_FILE_CHOOSER (dialog), priv->old_path, - NULL); - break; - case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: - _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (dialog), - priv->old_path, 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"); + + update_label_and_image (button); + update_combo_box (button); } else - gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (dialog)); - - if (priv->old_path) { - gtk_file_path_free (priv->old_path); - priv->old_path = 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, @@ -2692,6 +2869,10 @@ dialog_response_cb (GtkDialog *dialog, 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 (button, file_chooser_button_signals[FILE_SET], 0); } @@ -2723,49 +2904,29 @@ 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 - **/ -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)), - "file-system-backend", backend, - NULL); -} - /** * gtk_file_chooser_button_new_with_dialog: - * @dialog: the #GtkFileChooserDialog widget to use. - * - * Creates a #GtkFileChooserButton widget which uses @dialog as it's - * file-picking window. Note that @dialog must be a #GtkFileChooserDialog (or - * subclass) and must not have %GTK_DIALOG_DESTROY_WITH_PARENT set. - * + * @dialog: the widget to use as dialog + * + * Creates a #GtkFileChooserButton widget which uses @dialog as its + * file-picking window. + * + * Note that @dialog must be a #GtkDialog (or subclass) which + * implements the #GtkFileChooser interface and must not have + * %GTK_DIALOG_DESTROY_WITH_PARENT set. + * + * Also note that the dialog needs to have its confirmative button + * added with response %GTK_RESPONSE_ACCEPT or %GTK_RESPONSE_OK in + * order for the button to take over the file selected in the dialog. + * * Returns: a new button widget. - * + * * Since: 2.6 **/ GtkWidget * gtk_file_chooser_button_new_with_dialog (GtkWidget *dialog) { - g_return_val_if_fail (GTK_IS_FILE_CHOOSER_DIALOG (dialog), NULL); + g_return_val_if_fail (GTK_IS_FILE_CHOOSER (dialog) && GTK_IS_DIALOG (dialog), NULL); return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON, "dialog", dialog, @@ -2802,7 +2963,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); @@ -2900,6 +3061,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"