diff --git a/demos/gtk-demo/listview_words.c b/demos/gtk-demo/listview_words.c index 867f74e652..e2a5a1e2fa 100644 --- a/demos/gtk-demo/listview_words.c +++ b/demos/gtk-demo/listview_words.c @@ -142,16 +142,42 @@ load_file (GtkStringList *list, } static void -file_selected_cb (GtkWidget *button, +open_response_cb (GtkWidget *dialog, + int response, GtkStringList *stringlist) { - GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (button)); + gtk_widget_hide (dialog); - if (file) + if (response == GTK_RESPONSE_ACCEPT) { + GFile *file; + + file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)); load_file (stringlist, file); g_object_unref (file); } + + gtk_window_destroy (GTK_WINDOW (dialog)); +} + +static void +file_open_cb (GtkWidget *button, + GtkStringList *stringlist) +{ + GtkWidget *dialog; + + dialog = gtk_file_chooser_dialog_new ("Open file", + GTK_WINDOW (gtk_widget_get_root (button)), + GTK_FILE_CHOOSER_ACTION_OPEN, + "_Cancel", GTK_RESPONSE_CANCEL, + "_Load", GTK_RESPONSE_ACCEPT, + NULL); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), stringlist); + gtk_widget_show (dialog); } GtkWidget * @@ -189,8 +215,8 @@ do_listview_words (GtkWidget *do_widget) header = gtk_header_bar_new (); gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE); - open_button = gtk_file_chooser_button_new ("_Open", GTK_FILE_CHOOSER_ACTION_OPEN); - g_signal_connect (open_button, "file-set", G_CALLBACK (file_selected_cb), stringlist); + open_button = gtk_button_new_with_mnemonic ("_Open"); + g_signal_connect (open_button, "clicked", G_CALLBACK (file_open_cb), stringlist); gtk_header_bar_pack_start (GTK_HEADER_BAR (header), open_button); gtk_window_set_titlebar (GTK_WINDOW (window), header); diff --git a/demos/gtk-demo/paintable_svg.c b/demos/gtk-demo/paintable_svg.c index eab506f4ed..9d87f121ac 100644 --- a/demos/gtk-demo/paintable_svg.c +++ b/demos/gtk-demo/paintable_svg.c @@ -13,19 +13,50 @@ static void -file_set (GtkFileChooserButton *button, - GtkWidget *picture) +open_response_cb (GtkWidget *dialog, + int response, + GtkPicture *picture) { - GFile *file; - GdkPaintable *paintable; + gtk_widget_hide (dialog); - file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (button)); + if (response == GTK_RESPONSE_ACCEPT) + { + GFile *file; + GdkPaintable *paintable; - paintable = svg_paintable_new (file); - gtk_picture_set_paintable (GTK_PICTURE (picture), paintable); + file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)); + paintable = svg_paintable_new (file); + gtk_picture_set_paintable (GTK_PICTURE (picture), paintable); + g_object_unref (paintable); + g_object_unref (file); + } - g_object_unref (paintable); - g_object_unref (file); + gtk_window_destroy (GTK_WINDOW (dialog)); +} + +static void +show_file_open (GtkWidget *button, + GtkPicture *picture) +{ + GtkFileFilter *filter; + GtkWidget *dialog; + + dialog = gtk_file_chooser_dialog_new ("Open node file", + GTK_WINDOW (gtk_widget_get_root (button)), + GTK_FILE_CHOOSER_ACTION_OPEN, + "_Cancel", GTK_RESPONSE_CANCEL, + "_Load", GTK_RESPONSE_ACCEPT, + NULL); + + filter = gtk_file_filter_new (); + gtk_file_filter_add_mime_type (filter, "image/svg+xml"); + gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), picture); + gtk_widget_show (dialog); } static GtkWidget *window; @@ -35,7 +66,6 @@ do_paintable_svg (GtkWidget *do_widget) { GtkWidget *header; GtkWidget *picture; - GtkFileFilter *filter; GtkWidget *button; GFile *file; GdkPaintable *paintable; @@ -49,17 +79,14 @@ do_paintable_svg (GtkWidget *do_widget) gtk_window_set_title (GTK_WINDOW (window), "Paintable — SVG"); g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window); - button = gtk_file_chooser_button_new ("Select an SVG file", GTK_FILE_CHOOSER_ACTION_OPEN); - filter = gtk_file_filter_new (); - gtk_file_filter_add_mime_type (filter, "image/svg+xml"); - gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (button), filter); + button = gtk_button_new_with_mnemonic ("_Open"); gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button); picture = gtk_picture_new (); gtk_picture_set_can_shrink (GTK_PICTURE (picture), TRUE); gtk_widget_set_size_request (picture, 16, 16); - g_signal_connect (button, "file-set", G_CALLBACK (file_set), picture); + g_signal_connect (button, "clicked", G_CALLBACK (show_file_open), picture); gtk_window_set_child (GTK_WINDOW (window), picture); diff --git a/demos/gtk-demo/pickers.c b/demos/gtk-demo/pickers.c index 0b42034030..e5f6ef99d4 100644 --- a/demos/gtk-demo/pickers.c +++ b/demos/gtk-demo/pickers.c @@ -63,9 +63,6 @@ do_pickers (GtkWidget *do_widget) if (!window) { - char *dir; - GFile *file; - window = gtk_window_new (); gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget)); @@ -129,41 +126,6 @@ do_pickers (GtkWidget *do_widget) gtk_widget_set_hexpand (label, TRUE); gtk_grid_attach (GTK_GRID (table), label, 0, 2, 1, 1); - picker = gtk_file_chooser_button_new ("Pick a File", - GTK_FILE_CHOOSER_ACTION_OPEN); - gtk_grid_attach (GTK_GRID (table), picker, 1, 2, 1, 1); - - picker = gtk_file_chooser_button_new ("Pick a File", - GTK_FILE_CHOOSER_ACTION_OPEN); - - dir = g_get_current_dir (); - file = g_file_new_for_path (dir); - gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (picker), file, NULL); - g_object_unref (file); - g_free (dir); - - gtk_file_chooser_add_choice (GTK_FILE_CHOOSER (picker), - "choice", - "Encoding", - (const char *[]) { "option1", "option2", NULL }, - (const char *[]) { "UTF-8", "Other Encoding", NULL }); - gtk_file_chooser_set_choice (GTK_FILE_CHOOSER (picker), "choice", "option1"); - gtk_file_chooser_add_choice (GTK_FILE_CHOOSER (picker), - "check", - "Read backwards", - NULL, NULL); - gtk_file_chooser_set_choice (GTK_FILE_CHOOSER (picker), "check", "false"); - - gtk_grid_attach (GTK_GRID (table), picker, 2, 2, 1, 1); - - label = gtk_label_new ("Folder:"); - gtk_widget_set_halign (label, GTK_ALIGN_START); - gtk_widget_set_valign (label, GTK_ALIGN_CENTER); - picker = gtk_file_chooser_button_new ("Pick a Folder", - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); - gtk_grid_attach (GTK_GRID (table), label, 0, 3, 1, 1); - gtk_grid_attach (GTK_GRID (table), picker, 1, 3, 1, 1); - label = gtk_label_new ("Mail:"); gtk_widget_set_halign (label, GTK_ALIGN_START); gtk_widget_set_valign (label, GTK_ALIGN_CENTER); diff --git a/demos/widget-factory/widget-factory.ui b/demos/widget-factory/widget-factory.ui index ba2378ba34..6d6f539140 100644 --- a/demos/widget-factory/widget-factory.ui +++ b/demos/widget-factory/widget-factory.ui @@ -878,9 +878,6 @@ Suspendisse feugiat quam quis dolor accumsan cursus. 1 - - - link button diff --git a/docs/reference/gtk/gtk4-docs.xml b/docs/reference/gtk/gtk4-docs.xml index 25ed9eebd7..faae8a2de6 100644 --- a/docs/reference/gtk/gtk4-docs.xml +++ b/docs/reference/gtk/gtk4-docs.xml @@ -283,7 +283,6 @@ - diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index c6e8f87a58..faad758464 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -1339,31 +1339,6 @@ gtk_file_chooser_widget_get_type GtkFileChooserWidgetPrivate -
-gtkfilechooserbutton -GtkFileChooserButton -GtkFileChooserButton -gtk_file_chooser_button_new -gtk_file_chooser_button_new_with_dialog -gtk_file_chooser_button_get_title -gtk_file_chooser_button_set_title -gtk_file_chooser_button_get_width_chars -gtk_file_chooser_button_set_width_chars -gtk_file_chooser_button_get_modal -gtk_file_chooser_button_set_modal - - -GTK_FILE_CHOOSER_BUTTON -GTK_IS_FILE_CHOOSER_BUTTON -GTK_TYPE_FILE_CHOOSER_BUTTON -GTK_FILE_CHOOSER_BUTTON_CLASS -GTK_IS_FILE_CHOOSER_BUTTON_CLASS -GTK_FILE_CHOOSER_BUTTON_GET_CLASS - -gtk_file_chooser_button_get_type -GtkFileChooserButtonPrivate -
-
gtkfilefilter GtkFileFilter diff --git a/docs/reference/gtk/gtk4.types.in b/docs/reference/gtk/gtk4.types.in index 5981ffb897..9bc79517f7 100644 --- a/docs/reference/gtk/gtk4.types.in +++ b/docs/reference/gtk/gtk4.types.in @@ -87,7 +87,6 @@ gtk_event_controller_motion_get_type gtk_event_controller_scroll_get_type gtk_every_filter_get_type gtk_expander_get_type -gtk_file_chooser_button_get_type gtk_file_chooser_dialog_get_type gtk_file_chooser_get_type gtk_file_chooser_native_get_type diff --git a/docs/tools/widgets.c b/docs/tools/widgets.c index 51889d8e96..884939adb5 100644 --- a/docs/tools/widgets.c +++ b/docs/tools/widgets.c @@ -615,51 +615,6 @@ create_font_button (void) return new_widget_info ("font-button", vbox, SMALL); } -static WidgetInfo * -create_file_button (void) -{ - GtkWidget *vbox; - GtkWidget *vbox2; - GtkWidget *picker; - char *path; - GFile *file; - - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); - vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3); - picker = gtk_file_chooser_button_new ("File Chooser Button", - GTK_FILE_CHOOSER_ACTION_OPEN); - gtk_widget_set_size_request (picker, 150, -1); - gtk_widget_set_halign (picker, GTK_ALIGN_CENTER); - gtk_widget_set_valign (picker, GTK_ALIGN_CENTER); - gtk_box_append (GTK_BOX (vbox2), picker); - gtk_box_append (GTK_BOX (vbox2), - gtk_label_new ("File Button (Files)")); - - gtk_box_append (GTK_BOX (vbox), - vbox2); - gtk_box_append (GTK_BOX (vbox), - gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)); - - vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3); - picker = gtk_file_chooser_button_new ("File Chooser Button", - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); - gtk_widget_set_size_request (picker, 150, -1); - path = g_build_filename (g_get_home_dir (), "Documents", NULL); - file = g_file_new_for_path (path); - gtk_file_chooser_set_file (GTK_FILE_CHOOSER (picker), file, NULL); - g_free (path); - g_object_unref (file); - gtk_widget_set_halign (picker, GTK_ALIGN_CENTER); - gtk_widget_set_valign (picker, GTK_ALIGN_CENTER); - gtk_box_append (GTK_BOX (vbox2), picker); - gtk_box_append (GTK_BOX (vbox2), gtk_label_new ("File Button (Select Folder)")); - gtk_box_append (GTK_BOX (vbox), vbox2); - - add_margin (vbox); - - return new_widget_info ("file-button", vbox, MEDIUM); -} - static WidgetInfo * create_editable_label (void) { @@ -2144,7 +2099,6 @@ get_all_widgets (void) retval = g_list_prepend (retval, create_combo_box_entry ()); retval = g_list_prepend (retval, create_combo_box_text ()); retval = g_list_prepend (retval, create_entry ()); - retval = g_list_prepend (retval, create_file_button ()); retval = g_list_prepend (retval, create_font_button ()); retval = g_list_prepend (retval, create_frame ()); retval = g_list_prepend (retval, create_icon_view ()); diff --git a/gtk/gtk-autocleanups.h b/gtk/gtk-autocleanups.h index 127a63c4a8..561e8dbb84 100644 --- a/gtk/gtk-autocleanups.h +++ b/gtk/gtk-autocleanups.h @@ -66,7 +66,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEntry, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEntryCompletion, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEventController, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkExpander, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFileChooserButton, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFileChooserDialog, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFileChooserWidget, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFileFilter, g_object_unref) diff --git a/gtk/gtk.h b/gtk/gtk.h index be942b218b..d5f50a86b3 100644 --- a/gtk/gtk.h +++ b/gtk/gtk.h @@ -119,7 +119,6 @@ #include #include #include -#include #include #include #include diff --git a/gtk/gtkfilechooser.c b/gtk/gtkfilechooser.c index fd7162a539..decad3fcc8 100644 --- a/gtk/gtkfilechooser.c +++ b/gtk/gtkfilechooser.c @@ -29,15 +29,14 @@ * SECTION:gtkfilechooser * @Short_description: File chooser interface used by GtkFileChooserWidget and GtkFileChooserDialog * @Title: GtkFileChooser - * @See_also: #GtkFileChooserDialog, #GtkFileChooserWidget, #GtkFileChooserButton + * @See_also: #GtkFileChooserDialog, #GtkFileChooserWidget * * #GtkFileChooser is an interface that can be implemented by file * selection widgets. In GTK, the main objects that implement this - * interface are #GtkFileChooserWidget, #GtkFileChooserDialog, and - * #GtkFileChooserButton. You do not need to write an object that - * implements the #GtkFileChooser interface unless you are trying to - * adapt an existing file selector to expose a standard programming - * interface. + * interface are #GtkFileChooserWidget and #GtkFileChooserDialog. You do not + * need to write an object that implements the #GtkFileChooser interface + * unless you are trying to adapt an existing file selector to expose a + * standard programming interface. * * #GtkFileChooser allows for shortcuts to various places in the filesystem. * In the default implementation these are displayed in the left pane. It diff --git a/gtk/gtkfilechooserbutton.c b/gtk/gtkfilechooserbutton.c deleted file mode 100644 index 3830d69ef9..0000000000 --- a/gtk/gtkfilechooserbutton.c +++ /dev/null @@ -1,2930 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */ - -/* gtkfilechooserbutton.c - * - * Copyright (c) 2004 James M. Cape - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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, see . - */ - -#include "config.h" - -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif - -#include -#include - -#include "gtkintl.h" -#include "gtkbookmarksmanagerprivate.h" -#include "gtkbutton.h" -#include "gtkcelllayout.h" -#include "gtkcellrenderertext.h" -#include "gtkcellrendererpixbuf.h" -#include "gtkcombobox.h" -#include "gtkdroptarget.h" -#include "gtkicontheme.h" -#include "gtkimage.h" -#include "gtklabel.h" -#include "gtkliststore.h" -#include "gtktreemodelfilter.h" -#include "gtkseparator.h" -#include "gtkfilechooserdialog.h" -#include "gtkfilechoosernative.h" -#include "gtkfilechooserprivate.h" -#include "gtkfilechooserutils.h" -#include "gtkmarshalers.h" -#include "gtkbinlayout.h" - -#include "gtkfilechooserbutton.h" - -#include "gtkorientable.h" - -#include "gtktypebuiltins.h" -#include "gtkprivate.h" -#include "gtksettings.h" -#include "gtkstylecontextprivate.h" -#include "gtkbitmaskprivate.h" -#include "gtkeventcontroller.h" -#include "gtkwidgetprivate.h" - -/** - * SECTION:gtkfilechooserbutton - * @Short_description: A button to launch a file chooser 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; - * GFile *cwd = g_file_new_for_path ("/etc"); - * - * button = gtk_file_chooser_button_new (_("Select a file"), - * GTK_FILE_CHOOSER_ACTION_OPEN); - * gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (button), cwd, NULL); - * g_object_unref (cwd); - * } - * ]| - * - * The #GtkFileChooserButton supports the #GtkFileChooserActions - * %GTK_FILE_CHOOSER_ACTION_OPEN and %GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER. - * - * > The #GtkFileChooserButton will ellipsize the label, and 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. - * - * # CSS nodes - * - * GtkFileChooserButton has a single CSS node with the name “filechooserbutton”. - */ - - -/* **************** * - * Private Macros * - * **************** */ - -#define ICON_SIZE 16 -#define DEFAULT_TITLE N_("Select a File") -#define DESKTOP_DISPLAY_NAME N_("Desktop") -#define FALLBACK_DISPLAY_NAME N_("(None)") - - -/* ********************** * - * Private Enumerations * - * ********************** */ - -/* Property IDs */ -enum -{ - PROP_0, - - PROP_DIALOG, - PROP_TITLE, - PROP_WIDTH_CHARS, - PROP_MODAL -}; - -/* Signals */ -enum -{ - FILE_SET, - LAST_SIGNAL -}; - -/* TreeModel Columns - */ -enum -{ - ICON_COLUMN, - DISPLAY_NAME_COLUMN, - TYPE_COLUMN, - DATA_COLUMN, - IS_FOLDER_COLUMN, - CANCELLABLE_COLUMN, - NUM_COLUMNS -}; - -/* TreeModel Row Types */ -typedef enum -{ - ROW_TYPE_SPECIAL, - ROW_TYPE_VOLUME, - ROW_TYPE_SHORTCUT, - ROW_TYPE_BOOKMARK_SEPARATOR, - ROW_TYPE_BOOKMARK, - ROW_TYPE_CURRENT_FOLDER_SEPARATOR, - ROW_TYPE_CURRENT_FOLDER, - ROW_TYPE_OTHER_SEPARATOR, - ROW_TYPE_OTHER, - - ROW_TYPE_INVALID = -1 -} -RowType; - - -/* ******************** * - * Private Structures * - * ******************** */ - -typedef struct _GtkFileChooserButtonClass GtkFileChooserButtonClass; - -struct _GtkFileChooserButton -{ - GtkWidget parent_instance; - - GtkFileChooser *chooser; /* Points to either dialog or native, depending on which is set */ - GtkWidget *dialog; /* Set if you explicitly enable */ - GtkFileChooserNative *native; /* Otherwise this is set */ - GtkWidget *box; - GtkWidget *button; - GtkWidget *image; - GtkWidget *label; - GtkWidget *combo_box; - GtkCellRenderer *icon_cell; - GtkCellRenderer *name_cell; - - GtkTreeModel *model; - GtkTreeModel *filter_model; - - GFile *selection_while_inactive; - GFile *current_folder_while_inactive; - - GVolumeMonitor *volume_monitor; - - GCancellable *dnd_select_folder_cancellable; - GCancellable *update_button_cancellable; - GSList *change_icon_theme_cancellables; - - GtkBookmarksManager *bookmarks_manager; - - guint8 n_special; - guint8 n_volumes; - guint8 n_shortcuts; - guint8 n_bookmarks; - 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 */ - guint active : 1; - - /* Whether the next async callback from GIO should emit the "selection-changed" signal */ - guint is_changing_selection : 1; -}; - -struct _GtkFileChooserButtonClass -{ - GtkWidgetClass parent_class; - - void (* file_set) (GtkFileChooserButton *fc); -}; - - -/* ********************* * - * Function Prototypes * - * ********************* */ - -/* 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 GListModel *gtk_file_chooser_button_get_files (GtkFileChooser *chooser); -static gboolean gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser, - GFile *file, - GError **error); -static gboolean gtk_file_chooser_button_remove_shortcut_folder (GtkFileChooser *chooser, - GFile *file, - GError **error); - -/* GObject Functions */ -static void gtk_file_chooser_button_constructed (GObject *object); -static void gtk_file_chooser_button_dispose (GObject *object); -static void gtk_file_chooser_button_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); -static void gtk_file_chooser_button_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -static void gtk_file_chooser_button_finalize (GObject *object); - -/* GtkWidget Functions */ -static void gtk_file_chooser_button_show (GtkWidget *widget); -static void gtk_file_chooser_button_hide (GtkWidget *widget); -static void gtk_file_chooser_button_root (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_state_flags_changed (GtkWidget *widget, - GtkStateFlags previous_state); - -/* Utility Functions */ -static void set_info_for_file_at_iter (GtkFileChooserButton *button, - GFile *file, - GtkTreeIter *iter); - -static int model_get_type_position (GtkFileChooserButton *button, - RowType row_type); -static void model_free_row_data (GtkFileChooserButton *button, - GtkTreeIter *iter); -static void model_add_special (GtkFileChooserButton *button); -static void model_add_other (GtkFileChooserButton *button); -static void model_add_volumes (GtkFileChooserButton *button, - GSList *volumes); -static void model_add_bookmarks (GtkFileChooserButton *button, - GSList *bookmarks); -static void model_update_current_folder (GtkFileChooserButton *button, - GFile *file); -static void model_remove_rows (GtkFileChooserButton *button, - int pos, - int n_rows); - -static gboolean filter_model_visible_func (GtkTreeModel *model, - GtkTreeIter *iter, - gpointer user_data); - -static gboolean combo_box_row_separator_func (GtkTreeModel *model, - GtkTreeIter *iter, - gpointer user_data); -static void name_cell_data_func (GtkCellLayout *layout, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer user_data); -static void open_dialog (GtkFileChooserButton *button); -static void update_combo_box (GtkFileChooserButton *button); -static void update_label_and_image (GtkFileChooserButton *button); - -/* Child Object Callbacks */ -static void bookmarks_changed_cb (gpointer user_data); - -static void combo_box_changed_cb (GtkComboBox *combo_box, - gpointer user_data); - -static void button_clicked_cb (GtkButton *real_button, - gpointer user_data); - -static void dialog_response_cb (GtkDialog *dialog, - int response, - gpointer user_data); -static void native_response_cb (GtkFileChooserNative *native, - int response, - gpointer user_data); -static void volumes_changed (GVolumeMonitor *volume_monitor, - gpointer volume, - gpointer user_data); -static GSList * get_volumes_list (GVolumeMonitor *volume_monitor); - -static guint file_chooser_button_signals[LAST_SIGNAL] = { 0 }; - -/* ******************* * - * GType Declaration * - * ******************* */ - -G_DEFINE_TYPE_WITH_CODE (GtkFileChooserButton, gtk_file_chooser_button, GTK_TYPE_WIDGET, - G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER, - gtk_file_chooser_button_file_chooser_iface_init)) - -struct DndSelectFolderData -{ - GtkFileChooserButton *button; - GtkFileChooserAction action; - GCancellable *cancellable; - GFile *file; - char **uris; - guint i; - gboolean selected; -}; - -static void -dnd_select_folder_get_info_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - GFile *file = G_FILE (object); - struct DndSelectFolderData *data = user_data; - GFileInfo *info; - GtkFileChooserButton *button = data->button; - - if (g_cancellable_is_cancelled (data->cancellable)) - { - g_object_unref (data->button); - g_object_unref (data->file); - g_object_unref (data->cancellable); - g_strfreev (data->uris); - g_free (data); - return; - } - - button->dnd_select_folder_cancellable = NULL; - - info = g_file_query_info_finish (file, result, NULL); - if (info) - { - 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), data->file, NULL)); - } - else - data->selected = FALSE; - - g_clear_object (&info); - - 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); - g_object_unref (data->file); - g_object_unref (data->cancellable); - g_strfreev (data->uris); - g_free (data); - - return; - } - - if (data->file) - g_object_unref (data->file); - - data->file = g_file_new_for_uri (data->uris[data->i]); - - g_clear_object (&data->cancellable); - data->cancellable = g_cancellable_new (); - button->dnd_select_folder_cancellable = data->cancellable; - - g_file_query_info_async (data->file, - "standard::type", - G_FILE_QUERY_INFO_NONE, - G_PRIORITY_DEFAULT, - data->cancellable, - dnd_select_folder_get_info_cb, - user_data); -} - -static gboolean -gtk_file_chooser_button_drop (GtkDropTarget *target, - const GValue *value, - double x, - double y, - GtkFileChooserButton *button) -{ - struct DndSelectFolderData *info; - GFile *file; - - file = g_value_get_object (value); - - info = g_new0 (struct DndSelectFolderData, 1); - info->button = g_object_ref (button); - info->i = 0; - info->uris = g_new0 (char *, 2); - info->selected = FALSE; - g_object_get (button->chooser, "action", &info->action, NULL); - - info->file = g_object_ref (file); - - g_clear_pointer (&button->dnd_select_folder_cancellable, g_cancellable_cancel); - - info->cancellable = g_cancellable_new (); - button->dnd_select_folder_cancellable = info->cancellable; - g_file_query_info_async (info->file, - "standard::type", - G_FILE_QUERY_INFO_NONE, - G_PRIORITY_DEFAULT, - info->cancellable, - dnd_select_folder_get_info_cb, - info); - - return TRUE; -} - -static void -gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class) -{ - GObjectClass *gobject_class; - GtkWidgetClass *widget_class; - - gobject_class = G_OBJECT_CLASS (class); - widget_class = GTK_WIDGET_CLASS (class); - - gobject_class->constructed = gtk_file_chooser_button_constructed; - gobject_class->set_property = gtk_file_chooser_button_set_property; - gobject_class->get_property = gtk_file_chooser_button_get_property; - gobject_class->finalize = gtk_file_chooser_button_finalize; - gobject_class->dispose = gtk_file_chooser_button_dispose; - - 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->root = gtk_file_chooser_button_root; - widget_class->mnemonic_activate = gtk_file_chooser_button_mnemonic_activate; - widget_class->state_flags_changed = gtk_file_chooser_button_state_flags_changed; - widget_class->grab_focus = gtk_widget_grab_focus_child; - widget_class->focus = gtk_widget_focus_child; - - /** - * 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. - */ - 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, - NULL, - G_TYPE_NONE, 0); - - /** - * GtkFileChooserButton:dialog: - * - * Instance of the #GtkFileChooserDialog associated with the button. - */ - g_object_class_install_property (gobject_class, PROP_DIALOG, - g_param_spec_object ("dialog", - P_("Dialog"), - P_("The file chooser dialog to use."), - GTK_TYPE_FILE_CHOOSER, - (GTK_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY))); - - /** - * GtkFileChooserButton:title: - * - * Title to put on the #GtkFileChooserDialog associated with the button. - */ - g_object_class_install_property (gobject_class, PROP_TITLE, - g_param_spec_string ("title", - P_("Title"), - P_("The title of the file chooser dialog."), - _(DEFAULT_TITLE), - GTK_PARAM_READWRITE)); - - /** - * GtkFileChooserButton:width-chars: - * - * The width of the entry and label inside the button, in characters. - */ - g_object_class_install_property (gobject_class, PROP_WIDTH_CHARS, - g_param_spec_int ("width-chars", - P_("Width In Characters"), - P_("The desired width of the button widget, in characters."), - -1, G_MAXINT, -1, - GTK_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_MODAL, - g_param_spec_boolean ("modal", - P_("Modal"), - P_("Whether to make the dialog modal"), - TRUE, - GTK_PARAM_READWRITE)); - - _gtk_file_chooser_install_properties (gobject_class); - - gtk_widget_class_set_css_name (widget_class, I_("filechooserbutton")); - - gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); -} - -static void -gtk_file_chooser_button_init (GtkFileChooserButton *button) -{ - GtkWidget *box; - GtkWidget *icon; - GtkDropTarget *target; - - button->button = gtk_button_new (); - g_signal_connect (button->button, "clicked", G_CALLBACK (button_clicked_cb), button); - button->image = gtk_image_new (); - button->label = gtk_label_new (_(FALLBACK_DISPLAY_NAME)); - gtk_label_set_xalign (GTK_LABEL (button->label), 0.0f); - gtk_widget_set_hexpand (button->label, TRUE); - icon = gtk_image_new_from_icon_name ("document-open-symbolic"); - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_set_valign (button->image, GTK_ALIGN_BASELINE); - gtk_box_append (GTK_BOX (box), button->image); - gtk_widget_set_valign (button->label, GTK_ALIGN_BASELINE); - gtk_box_append (GTK_BOX (box), button->label); - gtk_widget_set_valign (icon, GTK_ALIGN_BASELINE); - gtk_box_append (GTK_BOX (box), icon); - gtk_button_set_child (GTK_BUTTON (button->button), box); - - gtk_widget_set_parent (button->button, GTK_WIDGET (button)); - - button->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLUMNS, - G_TYPE_ICON, - G_TYPE_STRING, - G_TYPE_CHAR, - G_TYPE_POINTER, - G_TYPE_BOOLEAN, - G_TYPE_POINTER)); - - button->combo_box = gtk_combo_box_new (); - g_signal_connect (button->combo_box, "changed", G_CALLBACK (combo_box_changed_cb), button); - button->icon_cell = gtk_cell_renderer_pixbuf_new (); - button->name_cell = gtk_cell_renderer_text_new (); - g_object_set (button->name_cell, "xpad", 6, NULL); - - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (button->combo_box), button->icon_cell, FALSE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (button->combo_box), - button->icon_cell, "gicon", ICON_COLUMN, NULL); - - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (button->combo_box), button->name_cell, FALSE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (button->combo_box), - button->name_cell, "text", DISPLAY_NAME_COLUMN, NULL); - - gtk_widget_hide (button->combo_box); - gtk_widget_set_parent (button->combo_box, GTK_WIDGET (button)); - - /* Bookmarks manager */ - button->bookmarks_manager = _gtk_bookmarks_manager_new (bookmarks_changed_cb, button); - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (button->combo_box), - button->name_cell, name_cell_data_func, - NULL, NULL); - - /* DnD */ - target = gtk_drop_target_new (G_TYPE_FILE, GDK_ACTION_COPY); - g_signal_connect (target, "drop", G_CALLBACK (gtk_file_chooser_button_drop), button); - gtk_widget_add_controller (GTK_WIDGET (button), GTK_EVENT_CONTROLLER (target)); -} - - -/* ******************************* * - * GtkFileChooserIface Functions * - * ******************************* */ -static void -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) -{ - if (button->is_changing_selection) - { - button->is_changing_selection = FALSE; - } -} - -static gboolean -gtk_file_chooser_button_set_current_folder (GtkFileChooser *chooser, - GFile *file, - GError **error) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser); - - if (button->current_folder_while_inactive) - g_object_unref (button->current_folder_while_inactive); - - button->current_folder_while_inactive = g_object_ref (file); - - update_combo_box (button); - - if (button->active) - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (button->chooser), file, NULL); - - return TRUE; -} - -static GFile * -gtk_file_chooser_button_get_current_folder (GtkFileChooser *chooser) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser); - - if (button->current_folder_while_inactive) - return g_object_ref (button->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); - - if (button->selection_while_inactive) - g_object_unref (button->selection_while_inactive); - - button->selection_while_inactive = g_object_ref (file); - - button->is_changing_selection = TRUE; - - update_label_and_image (button); - update_combo_box (button); - - if (button->active) - gtk_file_chooser_select_file (GTK_FILE_CHOOSER (button->chooser), file, NULL); - - return TRUE; -} - -static void -unselect_current_file (GtkFileChooserButton *button) -{ - if (button->selection_while_inactive) - { - g_object_unref (button->selection_while_inactive); - button->selection_while_inactive = NULL; - } - - button->is_changing_selection = TRUE; - - update_label_and_image (button); - update_combo_box (button); -} - -static void -gtk_file_chooser_button_unselect_file (GtkFileChooser *chooser, - GFile *file) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser); - - if (g_file_equal (button->selection_while_inactive, file)) - unselect_current_file (button); - - if (button->active) - gtk_file_chooser_unselect_file (GTK_FILE_CHOOSER (button->chooser), file); -} - -static void -gtk_file_chooser_button_unselect_all (GtkFileChooser *chooser) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser); - - unselect_current_file (button); - - if (button->active) - gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (button->chooser)); -} - -static GFile * -get_selected_file (GtkFileChooserButton *button) -{ - GFile *retval; - - retval = NULL; - - if (button->selection_while_inactive) - retval = button->selection_while_inactive; - else if (button->chooser && gtk_file_chooser_get_action (button->chooser) == 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 GtkFileChooserWidget would do. - */ - if (button->current_folder_while_inactive) - retval = button->current_folder_while_inactive; - } - - if (retval) - return g_object_ref (retval); - else - return NULL; -} - -static GListModel * -gtk_file_chooser_button_get_files (GtkFileChooser *chooser) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser); - GFile *file; - GListStore *store; - - store = g_list_store_new (G_TYPE_FILE); - - file = get_selected_file (button); - if (file) - { - g_list_store_append (store, file); - g_object_unref (file); - } - - return G_LIST_MODEL (store); -} - -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, file, error); - - if (retval) - { - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser); - GtkTreeIter iter; - int pos; - - pos = model_get_type_position (button, ROW_TYPE_SHORTCUT); - pos += button->n_shortcuts; - - gtk_list_store_insert (GTK_LIST_STORE (button->model), &iter, pos); - gtk_list_store_set (GTK_LIST_STORE (button->model), &iter, - ICON_COLUMN, NULL, - DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME), - TYPE_COLUMN, ROW_TYPE_SHORTCUT, - DATA_COLUMN, g_object_ref (file), - IS_FOLDER_COLUMN, FALSE, - -1); - set_info_for_file_at_iter (button, file, &iter); - button->n_shortcuts++; - - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (button->filter_model)); - } - - return retval; -} - -static gboolean -gtk_file_chooser_button_remove_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_remove_shortcut_folder (delegate, file, error); - - if (retval) - { - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser); - GtkTreeIter iter; - int pos; - char type; - - pos = model_get_type_position (button, ROW_TYPE_SHORTCUT); - gtk_tree_model_iter_nth_child (button->model, &iter, NULL, pos); - - do - { - gpointer data; - - gtk_tree_model_get (button->model, &iter, - TYPE_COLUMN, &type, - DATA_COLUMN, &data, - -1); - - if (type == ROW_TYPE_SHORTCUT && - data && g_file_equal (data, file)) - { - model_free_row_data (GTK_FILE_CHOOSER_BUTTON (chooser), &iter); - gtk_list_store_remove (GTK_LIST_STORE (button->model), &iter); - button->n_shortcuts--; - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (button->filter_model)); - update_combo_box (GTK_FILE_CHOOSER_BUTTON (chooser)); - break; - } - } - while (type == ROW_TYPE_SHORTCUT && - gtk_tree_model_iter_next (button->model, &iter)); - } - - return retval; -} - - -/* ******************* * - * GObject Functions * - * ******************* */ - -static void -gtk_file_chooser_button_constructed (GObject *object) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object); - GSList *list; - - G_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->constructed (object); - - if (!button->dialog) - { - button->native = gtk_file_chooser_native_new (NULL, - NULL, - GTK_FILE_CHOOSER_ACTION_OPEN, - NULL, - NULL); - button->chooser = GTK_FILE_CHOOSER (button->native); - gtk_file_chooser_button_set_title (button, _(DEFAULT_TITLE)); - gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (button->native), TRUE); - - g_signal_connect (button->native, "response", - G_CALLBACK (native_response_cb), object); - } - else /* dialog set */ - { - button->chooser = GTK_FILE_CHOOSER (button->dialog); - gtk_window_set_hide_on_close (GTK_WINDOW (button->chooser), TRUE); - - if (!gtk_window_get_title (GTK_WINDOW (button->dialog))) - gtk_file_chooser_button_set_title (button, _(DEFAULT_TITLE)); - - g_signal_connect (button->dialog, "response", - G_CALLBACK (dialog_response_cb), object); - - g_object_add_weak_pointer (G_OBJECT (button->dialog), - (gpointer) (&button->dialog)); - } - - /* This is used, instead of the standard delegate, to ensure that signals are only - * delegated when the OK button is pressed. */ - g_object_set_qdata (object, GTK_FILE_CHOOSER_DELEGATE_QUARK, button->chooser); - - model_add_special (button); - - button->volume_monitor = g_volume_monitor_get (); - g_signal_connect (button->volume_monitor, "mount-added", - G_CALLBACK (volumes_changed), button); - g_signal_connect (button->volume_monitor, "mount-removed", - G_CALLBACK (volumes_changed), button); - g_signal_connect (button->volume_monitor, "mount-changed", - G_CALLBACK (volumes_changed), button); - g_signal_connect (button->volume_monitor, "volume-added", - G_CALLBACK (volumes_changed), button); - g_signal_connect (button->volume_monitor, "volume-removed", - G_CALLBACK (volumes_changed), button); - g_signal_connect (button->volume_monitor, "volume-changed", - G_CALLBACK (volumes_changed), button); - g_signal_connect (button->volume_monitor, "drive-connected", - G_CALLBACK (volumes_changed), button); - g_signal_connect (button->volume_monitor, "drive-disconnected", - G_CALLBACK (volumes_changed), button); - g_signal_connect (button->volume_monitor, "drive-changed", - G_CALLBACK (volumes_changed), button); - - list = get_volumes_list (button->volume_monitor); - model_add_volumes (button, list); - g_slist_free_full (list, g_object_unref); - - list = _gtk_bookmarks_manager_list_bookmarks (button->bookmarks_manager); - model_add_bookmarks (button, list); - g_slist_free_full (list, g_object_unref); - - model_add_other (button); - - button->filter_model = gtk_tree_model_filter_new (button->model, NULL); - gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (button->filter_model), - filter_model_visible_func, - object, NULL); - - gtk_combo_box_set_model (GTK_COMBO_BOX (button->combo_box), button->filter_model); - gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (button->combo_box), - combo_box_row_separator_func, - NULL, NULL); - - /* set up the action for a user-provided dialog, this also updates - * the label, image and combobox - */ - g_object_set (object, - "action", gtk_file_chooser_get_action (GTK_FILE_CHOOSER (button->chooser)), - NULL); - - update_label_and_image (button); - update_combo_box (button); -} - -static void -gtk_file_chooser_button_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object); - - switch (param_id) - { - case PROP_DIALOG: - /* Construct-only */ - button->dialog = g_value_get_object (value); - break; - case PROP_WIDTH_CHARS: - gtk_file_chooser_button_set_width_chars (GTK_FILE_CHOOSER_BUTTON (object), - g_value_get_int (value)); - break; - case GTK_FILE_CHOOSER_PROP_ACTION: - switch (g_value_get_enum (value)) - { - case GTK_FILE_CHOOSER_ACTION_SAVE: - { - GEnumClass *eclass; - GEnumValue *eval; - - eclass = g_type_class_peek (GTK_TYPE_FILE_CHOOSER_ACTION); - eval = g_enum_get_value (eclass, g_value_get_enum (value)); - g_warning ("%s: Choosers of type '%s' do not support '%s'.", - G_STRFUNC, G_OBJECT_TYPE_NAME (object), eval->value_name); - - g_value_set_enum ((GValue *) value, GTK_FILE_CHOOSER_ACTION_OPEN); - } - break; - default: - break; - } - - g_object_set_property (G_OBJECT (button->chooser), pspec->name, value); - update_label_and_image (GTK_FILE_CHOOSER_BUTTON (object)); - update_combo_box (GTK_FILE_CHOOSER_BUTTON (object)); - - switch (g_value_get_enum (value)) - { - case GTK_FILE_CHOOSER_ACTION_OPEN: - gtk_widget_hide (button->combo_box); - gtk_widget_show (button->button); - gtk_widget_queue_resize (GTK_WIDGET (button)); - break; - case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: - gtk_widget_show (button->combo_box); - gtk_widget_hide (button->button); - gtk_widget_queue_resize (GTK_WIDGET (button)); - break; - default: - g_assert_not_reached (); - break; - } - break; - - case PROP_TITLE: - case PROP_MODAL: - case GTK_FILE_CHOOSER_PROP_FILTER: - case GTK_FILE_CHOOSER_PROP_CREATE_FOLDERS: - g_object_set_property (G_OBJECT (button->chooser), pspec->name, 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)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -gtk_file_chooser_button_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object); - - switch (param_id) - { - case PROP_WIDTH_CHARS: - g_value_set_int (value, - gtk_label_get_width_chars (GTK_LABEL (button->label))); - break; - - case PROP_TITLE: - case PROP_MODAL: - case GTK_FILE_CHOOSER_PROP_ACTION: - case GTK_FILE_CHOOSER_PROP_FILTER: - case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE: - case GTK_FILE_CHOOSER_PROP_CREATE_FOLDERS: - case GTK_FILE_CHOOSER_PROP_FILTERS: - case GTK_FILE_CHOOSER_PROP_SHORTCUT_FOLDERS: - g_object_get_property (G_OBJECT (button->chooser), pspec->name, value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -gtk_file_chooser_button_finalize (GObject *object) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object); - - g_clear_object (&button->selection_while_inactive); - g_clear_object (&button->current_folder_while_inactive); - - gtk_widget_unparent (button->button); - gtk_widget_unparent (button->combo_box); - - G_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->finalize (object); -} - -/* ********************* * - * GtkWidget Functions * - * ********************* */ - -static void -gtk_file_chooser_button_state_flags_changed (GtkWidget *widget, - GtkStateFlags previous_state) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget); - - if (gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_DROP_ACTIVE) - { - gtk_widget_set_state_flags (button->button, GTK_STATE_FLAG_DROP_ACTIVE, FALSE); - gtk_widget_set_state_flags (button->combo_box, GTK_STATE_FLAG_DROP_ACTIVE, FALSE); - } - else - { - gtk_widget_unset_state_flags (button->button, GTK_STATE_FLAG_DROP_ACTIVE); - gtk_widget_unset_state_flags (button->combo_box, GTK_STATE_FLAG_DROP_ACTIVE); - } - - GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->state_flags_changed (widget, previous_state); -} - -static void -gtk_file_chooser_button_dispose (GObject *object) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object); - - if (button->model) - { - model_remove_rows (button, 0, gtk_tree_model_iter_n_children (button->model, NULL)); - g_clear_object (&button->model); - } - - g_clear_pointer ((GtkWindow **)&button->dialog, gtk_window_destroy); - - if (button->native) - gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (button->native)); - - g_clear_object (&button->native); - button->chooser = NULL; /* Was either button->dialog or button->native! */ - - g_clear_pointer (&button->dnd_select_folder_cancellable, g_cancellable_cancel); - g_clear_pointer (&button->update_button_cancellable, g_cancellable_cancel); - - g_slist_free_full (button->change_icon_theme_cancellables, (GDestroyNotify)g_cancellable_cancel); - button->change_icon_theme_cancellables = NULL; - - g_clear_object (&button->filter_model); - - if (button->volume_monitor) - g_signal_handlers_disconnect_by_func (button->volume_monitor, volumes_changed, button); - g_clear_object (&button->volume_monitor); - - g_clear_pointer (&button->bookmarks_manager, _gtk_bookmarks_manager_free); - - G_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->dispose (object); -} - -static void -gtk_file_chooser_button_show (GtkWidget *widget) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget); - - if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->show) - GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->show (widget); - - if (button->active) - open_dialog (GTK_FILE_CHOOSER_BUTTON (widget)); -} - -static void -gtk_file_chooser_button_hide (GtkWidget *widget) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget); - - if (button->dialog) - gtk_widget_hide (button->dialog); - else if (button->native) - gtk_native_dialog_hide (GTK_NATIVE_DIALOG (button->native)); - - if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->hide) - GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->hide (widget); -} - -static void -gtk_file_chooser_button_map (GtkWidget *widget) -{ - GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->map (widget); -} - -static gboolean -gtk_file_chooser_button_mnemonic_activate (GtkWidget *widget, - gboolean group_cycling) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget); - - switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (button->chooser))) - { - case GTK_FILE_CHOOSER_ACTION_OPEN: - gtk_widget_grab_focus (button->button); - break; - case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: - return gtk_widget_mnemonic_activate (button->combo_box, group_cycling); - break; - case GTK_FILE_CHOOSER_ACTION_SAVE: - default: - g_assert_not_reached (); - break; - } - - return TRUE; -} - -/* Changes the icons wherever it is needed */ -struct ChangeIconThemeData -{ - GtkFileChooserButton *button; - GtkTreeRowReference *row_ref; - GCancellable *cancellable; -}; - -static void -change_icon_theme_get_info_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GFile *file = G_FILE (source); - struct ChangeIconThemeData *data = user_data; - GFileInfo *info; - GIcon *icon; - GtkFileChooserButton *button = data->button; - - if (g_cancellable_is_cancelled (data->cancellable)) - { - g_object_unref (data->button); - g_object_unref (data->cancellable); - gtk_tree_row_reference_free (data->row_ref); - g_free (data); - return; - } - - button->change_icon_theme_cancellables = - g_slist_remove (button->change_icon_theme_cancellables, data->cancellable); - - info = g_file_query_info_finish (file, result, NULL); - if (!info) - goto out; - - icon = _gtk_file_info_get_icon (info, ICON_SIZE, gtk_widget_get_scale_factor (GTK_WIDGET (data->button))); - if (icon) - { - int width = 0; - GtkTreeIter iter; - GtkTreePath *path; - - width = MAX (width, ICON_SIZE); - - path = gtk_tree_row_reference_get_path (data->row_ref); - if (path) - { - gtk_tree_model_get_iter (button->model, &iter, path); - gtk_tree_path_free (path); - - gtk_list_store_set (GTK_LIST_STORE (button->model), &iter, - ICON_COLUMN, icon, - -1); - - g_object_set (button->icon_cell, - "width", width, - NULL); - } - g_object_unref (icon); - } - -out: - g_object_unref (data->button); - g_object_unref (data->cancellable); - gtk_tree_row_reference_free (data->row_ref); - g_free (data); - - g_clear_object (&info); -} - -static void -change_icon_theme (GtkFileChooserButton *button) -{ - GtkTreeIter iter; - int width = 0; - - g_slist_free_full (button->change_icon_theme_cancellables, (GDestroyNotify)g_cancellable_cancel); - button->change_icon_theme_cancellables = NULL; - - update_label_and_image (button); - - gtk_tree_model_get_iter_first (button->model, &iter); - - do - { - GIcon *icon = NULL; - char type; - gpointer data; - - type = ROW_TYPE_INVALID; - gtk_tree_model_get (button->model, &iter, - TYPE_COLUMN, &type, - DATA_COLUMN, &data, - -1); - - switch (type) - { - case ROW_TYPE_SPECIAL: - case ROW_TYPE_SHORTCUT: - case ROW_TYPE_BOOKMARK: - case ROW_TYPE_CURRENT_FOLDER: - if (data) - { - if (g_file_is_native (G_FILE (data))) - { - GtkTreePath *path; - struct ChangeIconThemeData *info; - - info = g_new0 (struct ChangeIconThemeData, 1); - info->button = g_object_ref (button); - path = gtk_tree_model_get_path (button->model, &iter); - info->row_ref = gtk_tree_row_reference_new (button->model, path); - gtk_tree_path_free (path); - - info->cancellable = g_cancellable_new (); - g_file_query_info_async (data, - "standard::icon", - G_FILE_QUERY_INFO_NONE, - G_PRIORITY_DEFAULT, - info->cancellable, - change_icon_theme_get_info_cb, - info); - - button->change_icon_theme_cancellables = - g_slist_append (button->change_icon_theme_cancellables, info->cancellable); - icon = NULL; - } - else - { - /* Don't call get_info for remote paths to avoid latency and - * auth dialogs. - * If we switch to a better bookmarks file format (XBEL), we - * should use mime info to get a better icon. - */ - icon = g_themed_icon_new ("folder-remote"); - } - } - break; - case ROW_TYPE_VOLUME: - if (G_IS_DRIVE (data)) - icon = g_drive_get_icon (G_DRIVE (data)); - else if (G_IS_VOLUME (data)) - icon = g_volume_get_icon (G_VOLUME (data)); - else if (G_IS_MOUNT (data)) - icon = g_mount_get_icon (G_MOUNT (data)); - else - icon = NULL; - break; - default: - continue; - break; - } - - if (icon) - width = MAX (width, ICON_SIZE); - - gtk_list_store_set (GTK_LIST_STORE (button->model), &iter, - ICON_COLUMN, icon, - -1); - - if (icon) - g_object_unref (icon); - } - while (gtk_tree_model_iter_next (button->model, &iter)); - - g_object_set (button->icon_cell, - "width", width, - NULL); -} - -static void -gtk_file_chooser_button_root (GtkWidget *widget) -{ - GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->root (widget); - - change_icon_theme (GTK_FILE_CHOOSER_BUTTON (widget)); -} - -/* ******************* * - * Utility Functions * - * ******************* */ - -/* General */ - -struct SetDisplayNameData -{ - GtkFileChooserButton *button; - char *label; - GtkTreeRowReference *row_ref; -}; - -static void -set_info_get_info_cb (GObject *source, - GAsyncResult *result, - gpointer callback_data) -{ - GFile *file = G_FILE (source); - struct SetDisplayNameData *data = callback_data; - GFileInfo *info = NULL; - GIcon *icon; - GtkTreePath *path; - GtkTreeIter iter; - GCancellable *model_cancellable = NULL; - GtkFileChooserButton *button = data->button; - gboolean is_folder; - - if (!button->model) - /* button got destroyed */ - goto out; - - path = gtk_tree_row_reference_get_path (data->row_ref); - if (!path) - /* Cancellable doesn't exist anymore in the model */ - goto out; - - gtk_tree_model_get_iter (button->model, &iter, path); - gtk_tree_path_free (path); - - /* Validate the cancellable */ - gtk_tree_model_get (button->model, &iter, - CANCELLABLE_COLUMN, &model_cancellable, - -1); - - gtk_list_store_set (GTK_LIST_STORE (button->model), &iter, - CANCELLABLE_COLUMN, NULL, - -1); - - info = g_file_query_info_finish (file, result, NULL); - if (!info) - goto out; - - icon = _gtk_file_info_get_icon (info, ICON_SIZE, gtk_widget_get_scale_factor (GTK_WIDGET (data->button))); - - if (!data->label) - 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 (button->model), &iter, - ICON_COLUMN, icon, - DISPLAY_NAME_COLUMN, data->label, - IS_FOLDER_COLUMN, is_folder, - -1); - - if (icon) - g_object_unref (icon); - -out: - g_object_unref (data->button); - g_free (data->label); - gtk_tree_row_reference_free (data->row_ref); - g_free (data); - - g_clear_object (&info); -} - -static void -set_info_for_file_at_iter (GtkFileChooserButton *button, - GFile *file, - GtkTreeIter *iter) -{ - struct SetDisplayNameData *data; - GtkTreePath *tree_path; - GCancellable *cancellable; - - data = g_new0 (struct SetDisplayNameData, 1); - data->button = g_object_ref (button); - data->label = _gtk_bookmarks_manager_get_bookmark_label (button->bookmarks_manager, file); - - tree_path = gtk_tree_model_get_path (button->model, iter); - data->row_ref = gtk_tree_row_reference_new (button->model, tree_path); - gtk_tree_path_free (tree_path); - - cancellable = g_cancellable_new (); - g_file_query_info_async (file, - "standard::type,standard::icon,standard::display-name", - G_FILE_QUERY_INFO_NONE, - G_PRIORITY_DEFAULT, - cancellable, - set_info_get_info_cb, - data); - - gtk_list_store_set (GTK_LIST_STORE (button->model), iter, - CANCELLABLE_COLUMN, cancellable, - -1); -} - -/* Shortcuts Model */ -static int -model_get_type_position (GtkFileChooserButton *button, - RowType row_type) -{ - int retval = 0; - - if (row_type == ROW_TYPE_SPECIAL) - return retval; - - retval += button->n_special; - - if (row_type == ROW_TYPE_VOLUME) - return retval; - - retval += button->n_volumes; - - if (row_type == ROW_TYPE_SHORTCUT) - return retval; - - retval += button->n_shortcuts; - - if (row_type == ROW_TYPE_BOOKMARK_SEPARATOR) - return retval; - - retval += button->has_bookmark_separator; - - if (row_type == ROW_TYPE_BOOKMARK) - return retval; - - retval += button->n_bookmarks; - - if (row_type == ROW_TYPE_CURRENT_FOLDER_SEPARATOR) - return retval; - - retval += button->has_current_folder_separator; - - if (row_type == ROW_TYPE_CURRENT_FOLDER) - return retval; - - retval += button->has_current_folder; - - if (row_type == ROW_TYPE_OTHER_SEPARATOR) - return retval; - - retval += button->has_other_separator; - - if (row_type == ROW_TYPE_OTHER) - return retval; - - retval++; - - g_assert_not_reached (); - return -1; -} - -static void -model_free_row_data (GtkFileChooserButton *button, - GtkTreeIter *iter) -{ - char type; - gpointer data; - GCancellable *cancellable; - - gtk_tree_model_get (button->model, iter, - TYPE_COLUMN, &type, - DATA_COLUMN, &data, - CANCELLABLE_COLUMN, &cancellable, - -1); - - if (cancellable) - g_cancellable_cancel (cancellable); - - switch (type) - { - case ROW_TYPE_SPECIAL: - case ROW_TYPE_SHORTCUT: - case ROW_TYPE_BOOKMARK: - case ROW_TYPE_CURRENT_FOLDER: - case ROW_TYPE_VOLUME: - g_object_unref (data); - break; - default: - break; - } -} - -static void -model_add_special_get_info_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GFile *file = G_FILE (source); - struct ChangeIconThemeData *data = user_data; - GtkTreeIter iter; - GtkTreePath *path; - GIcon *icon; - GCancellable *model_cancellable = NULL; - GtkFileChooserButton *button = data->button; - GFileInfo *info = NULL; - char *name; - - if (!button->model) - /* button got destroyed */ - goto out; - - path = gtk_tree_row_reference_get_path (data->row_ref); - if (!path) - /* Cancellable doesn't exist anymore in the model */ - goto out; - - gtk_tree_model_get_iter (button->model, &iter, path); - gtk_tree_path_free (path); - - gtk_tree_model_get (button->model, &iter, - CANCELLABLE_COLUMN, &model_cancellable, - -1); - - gtk_list_store_set (GTK_LIST_STORE (button->model), &iter, - CANCELLABLE_COLUMN, NULL, - -1); - - info = g_file_query_info_finish (file, result, NULL); - if (!info) - goto out; - - icon = _gtk_file_info_get_icon (info, ICON_SIZE, gtk_widget_get_scale_factor (GTK_WIDGET (data->button))); - if (icon) - { - gtk_list_store_set (GTK_LIST_STORE (button->model), &iter, - ICON_COLUMN, icon, - -1); - g_object_unref (icon); - } - - gtk_tree_model_get (button->model, &iter, - DISPLAY_NAME_COLUMN, &name, - -1); - if (!name) - gtk_list_store_set (GTK_LIST_STORE (button->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_clear_object (&info); -} - -static void -model_add_special (GtkFileChooserButton *button) -{ - const char *homedir; - const char *desktopdir; - GtkListStore *store; - GtkTreeIter iter; - GFile *file; - int pos; - - store = GTK_LIST_STORE (button->model); - pos = model_get_type_position (button, ROW_TYPE_SPECIAL); - - homedir = g_get_home_dir (); - - if (homedir) - { - GtkTreePath *tree_path; - GCancellable *cancellable; - struct ChangeIconThemeData *info; - - file = g_file_new_for_path (homedir); - gtk_list_store_insert (store, &iter, pos); - pos++; - - info = g_new0 (struct ChangeIconThemeData, 1); - info->button = g_object_ref (button); - tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter); - info->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), - tree_path); - gtk_tree_path_free (tree_path); - - cancellable = g_cancellable_new (); - g_file_query_info_async (file, - "standard::icon,standard::display-name", - G_FILE_QUERY_INFO_NONE, - G_PRIORITY_DEFAULT, - cancellable, - 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, file, - IS_FOLDER_COLUMN, TRUE, - CANCELLABLE_COLUMN, cancellable, - -1); - - button->n_special++; - } - - desktopdir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP); - - /* "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; - struct ChangeIconThemeData *info; - - file = g_file_new_for_path (desktopdir); - gtk_list_store_insert (store, &iter, pos); - pos++; - - info = g_new0 (struct ChangeIconThemeData, 1); - info->button = g_object_ref (button); - tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter); - info->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), - tree_path); - gtk_tree_path_free (tree_path); - - cancellable = g_cancellable_new (); - g_file_query_info_async (file, - "standard::icon,standard::display-name", - G_FILE_QUERY_INFO_NONE, - G_PRIORITY_DEFAULT, - cancellable, - 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, file, - IS_FOLDER_COLUMN, TRUE, - CANCELLABLE_COLUMN, cancellable, - -1); - - button->n_special++; - } -} - -static void -model_add_volumes (GtkFileChooserButton *button, - GSList *volumes) -{ - GtkListStore *store; - int pos; - GSList *l; - - if (!volumes) - return; - - store = GTK_LIST_STORE (button->model); - pos = model_get_type_position (button, ROW_TYPE_VOLUME); - - for (l = volumes; l; l = l->next) - { - gpointer *volume; - GtkTreeIter iter; - GIcon *icon; - char *display_name; - - volume = l->data; - if (G_IS_DRIVE (volume)) - { - icon = g_drive_get_icon (G_DRIVE (volume)); - display_name = g_drive_get_name (G_DRIVE (volume)); - } - else if (G_IS_VOLUME (volume)) - { - icon = g_volume_get_icon (G_VOLUME (volume)); - display_name = g_volume_get_name (G_VOLUME (volume)); - } - else if (G_IS_MOUNT (volume)) - { - icon = g_mount_get_icon (G_MOUNT (volume)); - display_name = g_mount_get_name (G_MOUNT (volume)); - } - else - { - icon = NULL; - display_name = NULL; - } - - gtk_list_store_insert (store, &iter, pos); - gtk_list_store_set (store, &iter, - ICON_COLUMN, icon, - DISPLAY_NAME_COLUMN, display_name, - TYPE_COLUMN, ROW_TYPE_VOLUME, - DATA_COLUMN, g_object_ref (volume), - IS_FOLDER_COLUMN, TRUE, - -1); - - g_clear_object (&icon); - g_free (display_name); - - button->n_volumes++; - pos++; - } -} - -static void -model_add_bookmarks (GtkFileChooserButton *button, - GSList *bookmarks) -{ - GtkListStore *store; - GtkTreeIter iter; - int pos; - GSList *l; - - if (!bookmarks) - return; - - store = GTK_LIST_STORE (button->model); - pos = model_get_type_position (button, ROW_TYPE_BOOKMARK); - - for (l = bookmarks; l; l = l->next) - { - GFile *file; - - file = l->data; - - if (_gtk_file_has_native_path (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, g_object_ref (file), - IS_FOLDER_COLUMN, FALSE, - -1); - set_info_for_file_at_iter (button, file, &iter); - } - else - { - char *label; - GIcon *icon; - - /* Don't call get_info for remote paths to avoid latency and - * auth dialogs. - * If we switch to a better bookmarks file format (XBEL), we - * should use mime info to get a better icon. - */ - label = _gtk_bookmarks_manager_get_bookmark_label (button->bookmarks_manager, file); - if (!label) - label = _gtk_file_chooser_label_for_file (file); - - icon = g_themed_icon_new ("folder-remote"); - - gtk_list_store_insert (store, &iter, pos); - gtk_list_store_set (store, &iter, - ICON_COLUMN, icon, - DISPLAY_NAME_COLUMN, label, - TYPE_COLUMN, ROW_TYPE_BOOKMARK, - DATA_COLUMN, g_object_ref (file), - IS_FOLDER_COLUMN, TRUE, - -1); - - g_free (label); - if (icon) - g_object_unref (icon); - } - - button->n_bookmarks++; - pos++; - } - - if (button->n_bookmarks > 0 && - !button->has_bookmark_separator) - { - pos = model_get_type_position (button, ROW_TYPE_BOOKMARK_SEPARATOR); - - gtk_list_store_insert (store, &iter, pos); - gtk_list_store_set (store, &iter, - ICON_COLUMN, NULL, - DISPLAY_NAME_COLUMN, NULL, - TYPE_COLUMN, ROW_TYPE_BOOKMARK_SEPARATOR, - DATA_COLUMN, NULL, - IS_FOLDER_COLUMN, FALSE, - -1); - button->has_bookmark_separator = TRUE; - } -} - -static void -model_update_current_folder (GtkFileChooserButton *button, - GFile *file) -{ - GtkListStore *store; - GtkTreeIter iter; - int pos; - - if (!file) - return; - - store = GTK_LIST_STORE (button->model); - - if (!button->has_current_folder_separator) - { - pos = model_get_type_position (button, ROW_TYPE_CURRENT_FOLDER_SEPARATOR); - gtk_list_store_insert (store, &iter, pos); - gtk_list_store_set (store, &iter, - ICON_COLUMN, NULL, - DISPLAY_NAME_COLUMN, NULL, - TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER_SEPARATOR, - DATA_COLUMN, NULL, - IS_FOLDER_COLUMN, FALSE, - -1); - button->has_current_folder_separator = TRUE; - } - - pos = model_get_type_position (button, ROW_TYPE_CURRENT_FOLDER); - if (!button->has_current_folder) - { - gtk_list_store_insert (store, &iter, pos); - button->has_current_folder = TRUE; - } - else - { - gtk_tree_model_iter_nth_child (button->model, &iter, NULL, pos); - model_free_row_data (button, &iter); - } - - 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, g_object_ref (file), - IS_FOLDER_COLUMN, FALSE, - -1); - set_info_for_file_at_iter (button, file, &iter); - } - else - { - char *label; - GIcon *icon; - - /* Don't call get_info for remote paths to avoid latency and - * auth dialogs. - * If we switch to a better bookmarks file format (XBEL), we - * should use mime info to get a better icon. - */ - label = _gtk_bookmarks_manager_get_bookmark_label (button->bookmarks_manager, file); - if (!label) - label = _gtk_file_chooser_label_for_file (file); - - if (g_file_is_native (file)) - icon = g_themed_icon_new ("folder"); - else - icon = g_themed_icon_new ("folder-remote"); - - gtk_list_store_set (store, &iter, - ICON_COLUMN, icon, - DISPLAY_NAME_COLUMN, label, - TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER, - DATA_COLUMN, g_object_ref (file), - IS_FOLDER_COLUMN, TRUE, - -1); - - g_free (label); - if (icon) - g_object_unref (icon); - } -} - -static void -model_add_other (GtkFileChooserButton *button) -{ - GtkListStore *store; - GtkTreeIter iter; - int pos; - GIcon *icon; - - store = GTK_LIST_STORE (button->model); - pos = model_get_type_position (button, ROW_TYPE_OTHER_SEPARATOR); - icon = g_themed_icon_new ("document-open-symbolic"); - - gtk_list_store_insert (store, &iter, pos); - gtk_list_store_set (store, &iter, - ICON_COLUMN, icon, - DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME), - TYPE_COLUMN, ROW_TYPE_OTHER_SEPARATOR, - DATA_COLUMN, NULL, - IS_FOLDER_COLUMN, FALSE, - -1); - button->has_other_separator = TRUE; - pos++; - - gtk_list_store_insert (store, &iter, pos); - gtk_list_store_set (store, &iter, - ICON_COLUMN, NULL, - DISPLAY_NAME_COLUMN, _("Other…"), - TYPE_COLUMN, ROW_TYPE_OTHER, - DATA_COLUMN, NULL, - IS_FOLDER_COLUMN, FALSE, - -1); - - g_object_unref (icon); -} - -static void -model_remove_rows (GtkFileChooserButton *button, - int pos, - int n_rows) -{ - GtkListStore *store; - - if (!n_rows) - return; - - store = GTK_LIST_STORE (button->model); - - do - { - GtkTreeIter iter; - - if (!gtk_tree_model_iter_nth_child (button->model, &iter, NULL, pos)) - g_assert_not_reached (); - - model_free_row_data (button, &iter); - gtk_list_store_remove (store, &iter); - n_rows--; - } - while (n_rows); -} - -/* Filter Model */ -static gboolean -test_if_file_is_visible (GFile *file, - gboolean is_folder) -{ - if (!file) - return FALSE; - - if (!is_folder) - return FALSE; - - return TRUE; -} - -static gboolean -filter_model_visible_func (GtkTreeModel *model, - GtkTreeIter *iter, - gpointer user_data) -{ - char type; - gpointer data; - gboolean retval, is_folder; - - type = ROW_TYPE_INVALID; - data = NULL; - - gtk_tree_model_get (model, iter, - TYPE_COLUMN, &type, - DATA_COLUMN, &data, - IS_FOLDER_COLUMN, &is_folder, - -1); - - switch (type) - { - case ROW_TYPE_CURRENT_FOLDER: - retval = TRUE; - break; - case ROW_TYPE_SPECIAL: - case ROW_TYPE_SHORTCUT: - case ROW_TYPE_BOOKMARK: - retval = test_if_file_is_visible (data, is_folder); - break; - case ROW_TYPE_VOLUME: - retval = TRUE; - break; - default: - retval = TRUE; - break; - } - - return retval; -} - -/* Combo Box */ -static void -name_cell_data_func (GtkCellLayout *layout, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer user_data) -{ - char type; - - type = 0; - gtk_tree_model_get (model, iter, - TYPE_COLUMN, &type, - -1); - - if (type == ROW_TYPE_CURRENT_FOLDER) - g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL); - else if (type == ROW_TYPE_BOOKMARK || type == ROW_TYPE_SHORTCUT) - g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_MIDDLE, NULL); - else - g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_NONE, NULL); -} - -static gboolean -combo_box_row_separator_func (GtkTreeModel *model, - GtkTreeIter *iter, - gpointer user_data) -{ - char type = ROW_TYPE_INVALID; - - gtk_tree_model_get (model, iter, TYPE_COLUMN, &type, -1); - - 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) -{ - GtkTreeIter iter, filter_iter; - - gtk_tree_model_iter_nth_child (button->model, &iter, NULL, pos); - gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (button->filter_model), - &filter_iter, &iter); - - g_signal_handlers_block_by_func (button->combo_box, combo_box_changed_cb, button); - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (button->combo_box), &filter_iter); - g_signal_handlers_unblock_by_func (button->combo_box, combo_box_changed_cb, button); -} - -static void -update_combo_box (GtkFileChooserButton *button) -{ - GFile *file; - GtkTreeIter iter; - gboolean row_found; - - file = get_selected_file (button); - - row_found = FALSE; - - gtk_tree_model_get_iter_first (button->filter_model, &iter); - - do - { - char type; - gpointer data; - - type = ROW_TYPE_INVALID; - data = NULL; - - gtk_tree_model_get (button->filter_model, &iter, - TYPE_COLUMN, &type, - DATA_COLUMN, &data, - -1); - - switch (type) - { - case ROW_TYPE_SPECIAL: - case ROW_TYPE_SHORTCUT: - case ROW_TYPE_BOOKMARK: - case ROW_TYPE_CURRENT_FOLDER: - row_found = (file && g_file_equal (data, file)); - break; - case ROW_TYPE_VOLUME: - { - GFile *base_file = g_file_new_for_uri ("file:///"); - row_found = (file && g_file_equal (base_file, file)); - g_object_unref (base_file); - } - break; - default: - row_found = FALSE; - break; - } - - if (row_found) - { - g_signal_handlers_block_by_func (button->combo_box, combo_box_changed_cb, button); - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (button->combo_box), - &iter); - g_signal_handlers_unblock_by_func (button->combo_box, combo_box_changed_cb, button); - } - } - while (!row_found && gtk_tree_model_iter_next (button->filter_model, &iter)); - - if (!row_found) - { - int 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 */ - - pos = model_get_type_position (button, ROW_TYPE_OTHER_SEPARATOR); - } - - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (button->filter_model)); - - select_combo_box_row_no_notify (button, pos); - } - - if (file) - g_object_unref (file); -} - -/* Button */ -static void -update_label_get_info_cb (GObject *source, - GAsyncResult *result, - gpointer data) -{ - GFile *file = G_FILE (source); - GtkFileChooserButton *button = data; - GIcon *icon; - GFileInfo *info; - - g_clear_object (&button->update_button_cancellable); - - info = g_file_query_info_finish (file, result, NULL); - if (!info) - goto out; - - gtk_label_set_text (GTK_LABEL (button->label), g_file_info_get_display_name (info)); - - icon = _gtk_file_info_get_icon (info, ICON_SIZE, gtk_widget_get_scale_factor (GTK_WIDGET (button))); - gtk_image_set_from_gicon (GTK_IMAGE (button->image), icon); - gtk_image_set_pixel_size (GTK_IMAGE (button->image), ICON_SIZE); - if (icon) - g_object_unref (icon); - -out: - emit_selection_changed_if_changing_selection (button); - - g_clear_object (&info); - g_object_unref (button); -} - -static void -update_label_and_image (GtkFileChooserButton *button) -{ - char *label_text; - GFile *file; - gboolean done_changing_selection; - - file = get_selected_file (button); - - label_text = NULL; - done_changing_selection = FALSE; - - if (button->update_button_cancellable) - { - g_cancellable_cancel (button->update_button_cancellable); - button->update_button_cancellable = NULL; - } - - if (file) - { - GMount *mount; - GFile *base_file; - - mount = g_file_find_enclosing_mount (file, NULL, NULL); - if (!mount && g_file_is_native (file)) - base_file = g_file_new_for_uri ("file:///"); - else if (mount) - base_file = g_mount_get_root (mount); - else - base_file = NULL; - - if (base_file && g_file_equal (base_file, file)) - { - GIcon *icon; - - label_text = g_mount_get_name (mount); - icon = g_mount_get_icon (mount); - gtk_image_set_from_gicon (GTK_IMAGE (button->image), icon); - gtk_image_set_pixel_size (GTK_IMAGE (button->image), ICON_SIZE); - g_clear_object (&icon); - } - - g_clear_object (&base_file); - g_clear_object (&mount); - - if (label_text) - { - done_changing_selection = TRUE; - goto out; - } - - if (g_file_is_native (file) || - !_gtk_bookmarks_manager_has_bookmark (button->bookmarks_manager, file)) - { - button->update_button_cancellable = g_cancellable_new (); - g_file_query_info_async (file, - "standard::icon,standard::display-name", - G_FILE_QUERY_INFO_NONE, - G_PRIORITY_DEFAULT, - button->update_button_cancellable, - update_label_get_info_cb, - g_object_ref (button)); - } - else - { - GIcon *icon; - - label_text = _gtk_bookmarks_manager_get_bookmark_label (button->bookmarks_manager, file); - icon = g_themed_icon_new ("text-x-generic"); - gtk_image_set_from_gicon (GTK_IMAGE (button->image), icon); - gtk_image_set_pixel_size (GTK_IMAGE (button->image), ICON_SIZE); - if (icon) - g_object_unref (icon); - - done_changing_selection = TRUE; - } - } - else - { - /* We know the selection is empty */ - done_changing_selection = TRUE; - } - -out: - - g_clear_object (&file); - - if (label_text) - { - gtk_label_set_text (GTK_LABEL (button->label), label_text); - g_free (label_text); - } - else - { - gtk_label_set_text (GTK_LABEL (button->label), _(FALLBACK_DISPLAY_NAME)); - gtk_image_set_from_gicon (GTK_IMAGE (button->image), NULL); - } - - if (done_changing_selection) - emit_selection_changed_if_changing_selection (button); -} - - -/* ************************ * - * Child Object Callbacks * - * ************************ */ - -static gboolean -mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount) -{ - GList *l; - GFile *mount_root; - gboolean ret; - - ret = FALSE; - - mount_root = g_mount_get_root (mount); - - for (l = volumes; l != NULL; l = l->next) - { - GVolume *volume = G_VOLUME (l->data); - GFile *volume_activation_root; - - volume_activation_root = g_volume_get_activation_root (volume); - if (volume_activation_root != NULL) - { - if (g_file_has_prefix (volume_activation_root, mount_root)) - { - ret = TRUE; - g_object_unref (volume_activation_root); - break; - } - g_object_unref (volume_activation_root); - } - } - - g_object_unref (mount_root); - return ret; -} - -static GSList * -get_volumes_list (GVolumeMonitor *volume_monitor) -{ - GSList *result; - GList *l, *ll; - GList *drives; - GList *volumes; - GList *mounts; - GDrive *drive; - GVolume *volume; - GMount *mount; - - result = NULL; - - /* first go through all connected drives */ - drives = g_volume_monitor_get_connected_drives (volume_monitor); - - for (l = drives; l != NULL; l = l->next) - { - drive = l->data; - volumes = g_drive_get_volumes (drive); - - if (volumes) - { - for (ll = volumes; ll != NULL; ll = ll->next) - { - volume = ll->data; - mount = g_volume_get_mount (volume); - - if (mount) - { - /* Show mounted volume */ - result = g_slist_prepend (result, g_object_ref (mount)); - g_object_unref (mount); - } - else - { - /* Do show the unmounted volumes in the sidebar; - * this is so the user can mount it (in case automounting - * is off). - * - * Also, even if automounting is enabled, this gives a visual - * cue that the user should remember to yank out the media if - * he just unmounted it. - */ - result = g_slist_prepend (result, g_object_ref (volume)); - } - - g_object_unref (volume); - } - - g_list_free (volumes); - } - else if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive)) - { - /* If the drive has no mountable volumes and we cannot detect media change.. we - * display the drive in the sidebar so the user can manually poll the drive by - * right clicking and selecting "Rescan..." - * - * This is mainly for drives like floppies where media detection doesn't - * work.. but it's also for human beings who like to turn off media detection - * in the OS to save battery juice. - */ - - result = g_slist_prepend (result, g_object_ref (drive)); - } - - g_object_unref (drive); - } - - g_list_free (drives); - - /* add all volumes that is not associated with a drive */ - volumes = g_volume_monitor_get_volumes (volume_monitor); - - for (l = volumes; l != NULL; l = l->next) - { - volume = l->data; - drive = g_volume_get_drive (volume); - - if (drive) - { - g_object_unref (drive); - continue; - } - - mount = g_volume_get_mount (volume); - - if (mount) - { - /* show this mount */ - result = g_slist_prepend (result, g_object_ref (mount)); - g_object_unref (mount); - } - else - { - /* see comment above in why we add an icon for a volume */ - result = g_slist_prepend (result, g_object_ref (volume)); - } - - g_object_unref (volume); - } - - /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */ - mounts = g_volume_monitor_get_mounts (volume_monitor); - - for (l = mounts; l != NULL; l = l->next) - { - mount = l->data; - volume = g_mount_get_volume (mount); - - if (volume) - { - g_object_unref (volume); - continue; - } - - /* if there's exists one or more volumes with an activation root - * inside the mount, don't display the mount - */ - if (mount_referenced_by_volume_activation_root (volumes, mount)) - { - g_object_unref (mount); - continue; - } - - /* show this mount */ - result = g_slist_prepend (result, g_object_ref (mount)); - g_object_unref (mount); - } - - g_list_free (volumes); - g_list_free (mounts); - - return result; -} - -static void -volumes_changed (GVolumeMonitor *volume_monitor, - gpointer volume, - gpointer user_data) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (user_data); - GSList *volumes; - - model_remove_rows (user_data, - model_get_type_position (user_data, ROW_TYPE_VOLUME), - button->n_volumes); - - button->n_volumes = 0; - - volumes = get_volumes_list (volume_monitor); - model_add_volumes (user_data, volumes); - g_slist_free_full (volumes, g_object_unref); - - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (button->filter_model)); - - update_label_and_image (user_data); - update_combo_box (user_data); -} - -static void -bookmarks_changed_cb (gpointer user_data) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (user_data); - GSList *bookmarks; - - bookmarks = _gtk_bookmarks_manager_list_bookmarks (button->bookmarks_manager); - model_remove_rows (user_data, - model_get_type_position (user_data, ROW_TYPE_BOOKMARK_SEPARATOR), - button->n_bookmarks + button->has_bookmark_separator); - button->has_bookmark_separator = FALSE; - button->n_bookmarks = 0; - model_add_bookmarks (user_data, bookmarks); - g_slist_free_full (bookmarks, g_object_unref); - - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (button->filter_model)); - - update_label_and_image (user_data); - update_combo_box (user_data); -} - -static void -save_inactive_state (GtkFileChooserButton *button) -{ - if (button->current_folder_while_inactive) - g_object_unref (button->current_folder_while_inactive); - - if (button->selection_while_inactive) - g_object_unref (button->selection_while_inactive); - - button->current_folder_while_inactive = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button->chooser)); - button->selection_while_inactive = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (button->chooser)); -} - -static void -restore_inactive_state (GtkFileChooserButton *button) -{ - if (button->current_folder_while_inactive) - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (button->chooser), button->current_folder_while_inactive, NULL); - - if (button->selection_while_inactive) - gtk_file_chooser_select_file (GTK_FILE_CHOOSER (button->chooser), button->selection_while_inactive, NULL); - else - gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (button->chooser)); -} - -/* Dialog */ -static void -open_dialog (GtkFileChooserButton *button) -{ - GtkWidget *toplevel; - - toplevel = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (button))); - - /* Setup the dialog parent to be chooser button's toplevel, and be modal - as needed. */ - if (button->dialog != NULL) - { - if (!gtk_widget_get_visible (button->dialog)) - { - if (GTK_IS_WINDOW (toplevel)) - { - if (GTK_WINDOW (toplevel) != gtk_window_get_transient_for (GTK_WINDOW (button->dialog))) - gtk_window_set_transient_for (GTK_WINDOW (button->dialog), - GTK_WINDOW (toplevel)); - if (gtk_window_get_modal (GTK_WINDOW (toplevel))) - gtk_window_set_modal (GTK_WINDOW (button->dialog), TRUE); - } - } - } - else - { - if (!gtk_native_dialog_get_visible (GTK_NATIVE_DIALOG (button->native))) - { - if (GTK_IS_WINDOW (toplevel)) - { - if (GTK_WINDOW (toplevel) != gtk_native_dialog_get_transient_for (GTK_NATIVE_DIALOG (button->native))) - gtk_native_dialog_set_transient_for (GTK_NATIVE_DIALOG (button->native), - GTK_WINDOW (toplevel)); - - if (gtk_window_get_modal (GTK_WINDOW (toplevel))) - gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (button->native), TRUE); - } - } - } - - if (!button->active) - { - restore_inactive_state (button); - button->active = TRUE; - } - - gtk_widget_set_sensitive (button->combo_box, FALSE); - if (button->dialog) - gtk_window_present (GTK_WINDOW (button->dialog)); - else - gtk_native_dialog_show (GTK_NATIVE_DIALOG (button->native)); -} - -/* Combo Box */ -static void -combo_box_changed_cb (GtkComboBox *combo_box, - gpointer user_data) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (user_data); - GtkTreeIter iter; - gboolean file_was_set; - - file_was_set = FALSE; - - if (gtk_combo_box_get_active_iter (combo_box, &iter)) - { - char type; - gpointer data; - - type = ROW_TYPE_INVALID; - data = NULL; - - gtk_tree_model_get (button->filter_model, &iter, - TYPE_COLUMN, &type, - DATA_COLUMN, &data, - -1); - - switch (type) - { - case ROW_TYPE_SPECIAL: - case ROW_TYPE_SHORTCUT: - case ROW_TYPE_BOOKMARK: - case ROW_TYPE_CURRENT_FOLDER: - if (data) - { - gtk_file_chooser_button_select_file (GTK_FILE_CHOOSER (button), data, NULL); - file_was_set = TRUE; - } - break; - case ROW_TYPE_VOLUME: - { - GFile *base_file = g_file_new_for_uri ("file:///"); - gtk_file_chooser_button_select_file (GTK_FILE_CHOOSER (button), base_file, NULL); - file_was_set = TRUE; - g_object_unref (base_file); - } - break; - case ROW_TYPE_OTHER: - open_dialog (user_data); - break; - default: - break; - } - } - - if (file_was_set) - g_signal_emit (button, file_chooser_button_signals[FILE_SET], 0); -} - -/* Button */ -static void -button_clicked_cb (GtkButton *real_button, - gpointer user_data) -{ - open_dialog (user_data); -} - -/* Dialog */ - -static void -common_response_cb (GtkFileChooserButton *button, - int response) -{ - if (response == GTK_RESPONSE_ACCEPT || - response == GTK_RESPONSE_OK) - { - save_inactive_state (button); - } - else - { - restore_inactive_state (button); - } - - if (button->active) - button->active = FALSE; - - update_label_and_image (button); - update_combo_box (button); - - gtk_widget_set_sensitive (button->combo_box, TRUE); -} - - -static void -dialog_response_cb (GtkDialog *dialog, - int response, - gpointer user_data) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (user_data); - - common_response_cb (button, response); - - gtk_widget_hide (button->dialog); - - if (response == GTK_RESPONSE_ACCEPT || - response == GTK_RESPONSE_OK) - g_signal_emit (button, file_chooser_button_signals[FILE_SET], 0); -} - -static void -native_response_cb (GtkFileChooserNative *native, - int response, - gpointer user_data) -{ - GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (user_data); - - common_response_cb (button, response); - - /* dialog already hidden */ - - if (response == GTK_RESPONSE_ACCEPT || - response == GTK_RESPONSE_OK) - g_signal_emit (button, file_chooser_button_signals[FILE_SET], 0); -} - - -/* ************************************************************************** * - * Public API * - * ************************************************************************** */ - -/** - * gtk_file_chooser_button_new: - * @title: the title of the browse dialog. - * @action: the open mode for the widget. - * - * Creates a new file-selecting button widget. - * - * Returns: a new button widget. - */ -GtkWidget * -gtk_file_chooser_button_new (const char *title, - GtkFileChooserAction action) -{ - 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: (type Gtk.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. - */ -GtkWidget * -gtk_file_chooser_button_new_with_dialog (GtkWidget *dialog) -{ - 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, - NULL); -} - -/** - * gtk_file_chooser_button_set_title: - * @button: the button widget to modify. - * @title: the new browse dialog title. - * - * Modifies the @title of the browse dialog used by @button. - */ -void -gtk_file_chooser_button_set_title (GtkFileChooserButton *button, - const char *title) -{ - g_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button)); - - if (button->dialog) - gtk_window_set_title (GTK_WINDOW (button->dialog), title); - else - gtk_native_dialog_set_title (GTK_NATIVE_DIALOG (button->native), title); - g_object_notify (G_OBJECT (button), "title"); -} - -/** - * gtk_file_chooser_button_get_title: - * @button: the button widget to examine. - * - * Retrieves the title of the browse dialog used by @button. The returned value - * should not be modified or freed. - * - * Returns: a pointer to the browse dialog’s title. - */ -const char * -gtk_file_chooser_button_get_title (GtkFileChooserButton *button) -{ - g_return_val_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button), NULL); - - if (button->dialog) - return gtk_window_get_title (GTK_WINDOW (button->dialog)); - else - return gtk_native_dialog_get_title (GTK_NATIVE_DIALOG (button->native)); -} - -/** - * gtk_file_chooser_button_get_width_chars: - * @button: the button widget to examine. - * - * Retrieves the width in characters of the @button widget’s entry and/or label. - * - * Returns: an integer width (in characters) that the button will use to size itself. - */ -int -gtk_file_chooser_button_get_width_chars (GtkFileChooserButton *button) -{ - g_return_val_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button), -1); - - return gtk_label_get_width_chars (GTK_LABEL (button->label)); -} - -/** - * gtk_file_chooser_button_set_width_chars: - * @button: the button widget to examine. - * @n_chars: the new width, in characters. - * - * Sets the width (in characters) that @button will use to @n_chars. - */ -void -gtk_file_chooser_button_set_width_chars (GtkFileChooserButton *button, - int n_chars) -{ - g_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button)); - - gtk_label_set_width_chars (GTK_LABEL (button->label), n_chars); - g_object_notify (G_OBJECT (button), "width-chars"); -} - -/** - * gtk_file_chooser_button_set_modal: - * @button: a #GtkFileChooserButton - * @modal: %TRUE to make the dialog modal - * - * Sets whether the dialog should be modal. - */ -void -gtk_file_chooser_button_set_modal (GtkFileChooserButton *button, - gboolean modal) -{ - g_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button)); - - g_object_set (button, "modal", modal, NULL); -} - -/** - * gtk_file_chooser_button_get_modal: - * @button: a #GtkFileChooserButton - * - * Gets whether the dialog is modal. - * - * Returns: %TRUE if the dialog is modal - */ -gboolean -gtk_file_chooser_button_get_modal (GtkFileChooserButton *button) -{ - gboolean modal; - - g_return_val_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button), FALSE); - - g_object_get (button, "modal", &modal, NULL); - - return modal; -} diff --git a/gtk/gtkfilechooserbutton.h b/gtk/gtkfilechooserbutton.h deleted file mode 100644 index cf4b1aaea5..0000000000 --- a/gtk/gtkfilechooserbutton.h +++ /dev/null @@ -1,62 +0,0 @@ -/* gtkfilechooserbutton.h - * - * Copyright (c) 2004 James M. Cape - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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, see . - */ - -#ifndef __GTK_FILE_CHOOSER_BUTTON_H__ -#define __GTK_FILE_CHOOSER_BUTTON_H__ - -#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) -#error "Only can be included directly." -#endif - -#include -#include - -G_BEGIN_DECLS - -#define GTK_TYPE_FILE_CHOOSER_BUTTON (gtk_file_chooser_button_get_type ()) -#define GTK_FILE_CHOOSER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER_BUTTON, GtkFileChooserButton)) -#define GTK_IS_FILE_CHOOSER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_CHOOSER_BUTTON)) - -typedef struct _GtkFileChooserButton GtkFileChooserButton; - -GDK_AVAILABLE_IN_ALL -GType gtk_file_chooser_button_get_type (void) G_GNUC_CONST; -GDK_AVAILABLE_IN_ALL -GtkWidget * gtk_file_chooser_button_new (const char *title, - GtkFileChooserAction action); -GDK_AVAILABLE_IN_ALL -GtkWidget * gtk_file_chooser_button_new_with_dialog (GtkWidget *dialog); -GDK_AVAILABLE_IN_ALL -const char * gtk_file_chooser_button_get_title (GtkFileChooserButton *button); -GDK_AVAILABLE_IN_ALL -void gtk_file_chooser_button_set_title (GtkFileChooserButton *button, - const char *title); -GDK_AVAILABLE_IN_ALL -int gtk_file_chooser_button_get_width_chars (GtkFileChooserButton *button); -GDK_AVAILABLE_IN_ALL -void gtk_file_chooser_button_set_width_chars (GtkFileChooserButton *button, - int n_chars); -GDK_AVAILABLE_IN_ALL -gboolean gtk_file_chooser_button_get_modal (GtkFileChooserButton *button); -GDK_AVAILABLE_IN_ALL -void gtk_file_chooser_button_set_modal (GtkFileChooserButton *button, - gboolean modal); - -G_END_DECLS - -#endif /* !__GTK_FILE_CHOOSER_BUTTON_H__ */ diff --git a/gtk/meson.build b/gtk/meson.build index d7f206c231..0e0239a8a6 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -241,7 +241,6 @@ gtk_public_sources = files([ 'gtkexpander.c', 'gtkexpression.c', 'gtkfilechooser.c', - 'gtkfilechooserbutton.c', 'gtkfilechooserdialog.c', 'gtkfilechoosernative.c', 'gtkfilechooserwidget.c', @@ -529,7 +528,6 @@ gtk_public_headers = files([ 'gtkexpander.h', 'gtkexpression.h', 'gtkfilechooser.h', - 'gtkfilechooserbutton.h', 'gtkfilechooserdialog.h', 'gtkfilechoosernative.h', 'gtkfilechooserwidget.h', diff --git a/tests/meson.build b/tests/meson.build index 4acdc7dcaf..51b2311a80 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -33,7 +33,6 @@ gtk_tests = [ ['testentrycompletion'], ['testentryicons'], ['testfilechooser'], - ['testfilechooserbutton'], ['testflowbox'], ['testfontoptions'], ['testframe'], diff --git a/tests/testfilechooserbutton.c b/tests/testfilechooserbutton.c deleted file mode 100644 index 239790c8af..0000000000 --- a/tests/testfilechooserbutton.c +++ /dev/null @@ -1,283 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 2 -*- */ - -/* GTK+: gtkfilechooserbutton.c - * - * Copyright (c) 2004 James M. Cape - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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, see . - */ - -#include "config.h" - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include -#include - -#include - -#include - -static const char *backend = "gtk+"; -static gboolean rtl = FALSE; -static GOptionEntry entries[] = { - { "backend", 'b', 0, G_OPTION_ARG_STRING, &backend, "The filesystem backend to use.", "gtk+" }, - { "right-to-left", 'r', 0, G_OPTION_ARG_NONE, &rtl, "Force right-to-left layout.", NULL }, - { NULL } -}; - -static char *gtk_src_dir = NULL; - -static void -print_selected_path_clicked_cb (GtkWidget *button, - gpointer user_data) -{ - GFile *folder, *filename; - char *folder_uri, *filename_uri; - - folder = gtk_file_chooser_get_current_folder (user_data); - filename = gtk_file_chooser_get_file (user_data); - - folder_uri = g_file_get_uri (folder); - filename_uri = g_file_get_uri (filename); - g_message ("Currently Selected:\n\tFolder: `%s'\n\tFilename: `%s'\nDone.\n", - folder_uri, filename_uri); - g_free (folder_uri); - g_free (filename_uri); - - g_object_unref (folder); - g_object_unref (filename); -} - -static void -add_pwds_parent_as_shortcut_clicked_cb (GtkWidget *button, - gpointer user_data) -{ - GFile *path = g_file_new_for_path (gtk_src_dir); - GError *err = NULL; - - if (!gtk_file_chooser_add_shortcut_folder (user_data, path, &err)) - { - g_message ("Couldn't add `%s' as shortcut folder: %s", gtk_src_dir, - err->message); - g_error_free (err); - } - else - { - g_message ("Added `%s' as shortcut folder.", gtk_src_dir); - } - - g_object_unref (path); -} - -static void -del_pwds_parent_as_shortcut_clicked_cb (GtkWidget *button, - gpointer user_data) -{ - GFile *path = g_file_new_for_path (gtk_src_dir); - GError *err = NULL; - - if (!gtk_file_chooser_remove_shortcut_folder (user_data, path, &err)) - { - g_message ("Couldn't remove `%s' as shortcut folder: %s", gtk_src_dir, - err->message); - g_error_free (err); - } - else - { - g_message ("Removed `%s' as shortcut folder.", gtk_src_dir); - } - - g_object_unref (path); -} - -static void -tests_button_clicked_cb (GtkButton *real_button, - gpointer user_data) -{ - GtkWidget *tests; - - tests = g_object_get_data (user_data, "tests-dialog"); - - if (tests == NULL) - { - GtkWidget *box, *button; - - tests = gtk_window_new (); - gtk_window_set_hide_on_close (GTK_WINDOW (tests), TRUE); - gtk_window_set_title (GTK_WINDOW (tests), - "Tests - TestFileChooserButton"); - gtk_window_set_transient_for (GTK_WINDOW (tests), - GTK_WINDOW (gtk_widget_get_root (user_data))); - - box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_box_append (GTK_BOX (tests), box); - - button = gtk_button_new_with_label ("Print Selected Path"); - g_signal_connect (button, "clicked", - G_CALLBACK (print_selected_path_clicked_cb), user_data); - gtk_box_append (GTK_BOX (box), button); - - button = gtk_button_new_with_label ("Add $PWD's Parent as Shortcut"); - g_signal_connect (button, "clicked", - G_CALLBACK (add_pwds_parent_as_shortcut_clicked_cb), user_data); - gtk_box_append (GTK_BOX (box), button); - - button = gtk_button_new_with_label ("Remove $PWD's Parent as Shortcut"); - g_signal_connect (button, "clicked", - G_CALLBACK (del_pwds_parent_as_shortcut_clicked_cb), user_data); - gtk_box_append (GTK_BOX (box), button); - - g_object_set_data (user_data, "tests-dialog", tests); - } - - gtk_window_present (GTK_WINDOW (tests)); -} - -static void -chooser_selection_changed_cb (GtkFileChooser *chooser, - gpointer user_data) -{ - GFile *filename; - char *uri; - - filename = gtk_file_chooser_get_file (chooser); - - uri = g_file_get_uri (filename); - g_message ("%s::selection-changed\n\tSelection:`%s'\nDone.\n", - G_OBJECT_TYPE_NAME (chooser), uri); - g_free (uri); - - g_object_unref (filename); -} - -static void -add_new_filechooser_button (const char *mnemonic, - const char *chooser_title, - GtkFileChooserAction action, - GtkWidget *group_box, - GtkSizeGroup *label_group) -{ - GtkWidget *hbox, *label, *chooser, *button; - GFile *path; - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_box_append (GTK_BOX (group_box), hbox); - - label = gtk_label_new_with_mnemonic (mnemonic); - gtk_size_group_add_widget (GTK_SIZE_GROUP (label_group), label); - gtk_label_set_xalign (GTK_LABEL (label), 0.0); - gtk_box_append (GTK_BOX (hbox), label); - - chooser = gtk_file_chooser_button_new (g_strconcat(chooser_title, - " - testfilechooserbutton", NULL), - action); - gtk_widget_set_hexpand (chooser, TRUE); - - path = g_file_new_for_path (gtk_src_dir); - gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (chooser), path, NULL); - gtk_file_chooser_remove_shortcut_folder (GTK_FILE_CHOOSER (chooser), path, NULL); - g_object_unref (path); - - gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser); - g_signal_connect (chooser, "selection-changed", G_CALLBACK (chooser_selection_changed_cb), NULL); - gtk_box_append (GTK_BOX (hbox), chooser); - - button = gtk_button_new_with_label ("Tests"); - g_signal_connect (button, "clicked", G_CALLBACK (tests_button_clicked_cb), chooser); - gtk_box_append (GTK_BOX (hbox), button); -} - -static void -quit_cb (GtkWidget *widget, - gpointer data) -{ - gboolean *done = data; - - *done = TRUE; - - g_main_context_wakeup (NULL); -} - -int -main (int argc, - char *argv[]) -{ - GtkWidget *win, *vbox, *frame, *group_box; - GtkSizeGroup *label_group; - GOptionContext *context; - char *cwd; - gboolean done = FALSE; - - context = g_option_context_new ("- test GtkFileChooserButton widget"); - g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); - g_option_context_parse (context, &argc, &argv, NULL); - g_option_context_free (context); - - gtk_init (); - - /* to test rtl layout, use "--right-to-left" */ - if (rtl) - gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL); - - cwd = g_get_current_dir(); - gtk_src_dir = g_path_get_dirname (cwd); - g_free (cwd); - - win = gtk_dialog_new_with_buttons ("TestFileChooserButton", NULL, 0, - "_Quit", GTK_RESPONSE_CLOSE, NULL); - g_signal_connect (win, "response", G_CALLBACK (quit_cb), &done); - - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 18); - gtk_widget_set_margin_start (vbox, 6); - gtk_widget_set_margin_end (vbox, 6); - gtk_widget_set_margin_top (vbox, 6); - gtk_widget_set_margin_bottom (vbox, 6); - gtk_box_append (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (win))), vbox); - - frame = gtk_frame_new ("GtkFileChooserButton"); - gtk_label_set_use_markup (GTK_LABEL (gtk_frame_get_label_widget (GTK_FRAME (frame))), TRUE); - gtk_box_append (GTK_BOX (vbox), frame); - - gtk_widget_set_halign (frame, GTK_ALIGN_FILL); - gtk_widget_set_valign (frame, GTK_ALIGN_FILL); - g_object_set (frame, "margin-top", 6, "margin-start", 12, NULL); - - label_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); - - group_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); - gtk_frame_set_child (GTK_FRAME (frame), group_box); - - /* OPEN */ - add_new_filechooser_button ("_Open:", "Select A File", - GTK_FILE_CHOOSER_ACTION_OPEN, - group_box, label_group); - - /* SELECT_FOLDER */ - add_new_filechooser_button ("Select _Folder:", "Select A Folder", - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - group_box, label_group); - - g_object_unref (label_group); - - gtk_widget_show (win); - gtk_window_present (GTK_WINDOW (win)); - - while (!done) - g_main_context_iteration (NULL, TRUE); - - return 0; -} diff --git a/testsuite/gtk/defaultvalue.c b/testsuite/gtk/defaultvalue.c index 22146a5c90..d55e6d5381 100644 --- a/testsuite/gtk/defaultvalue.c +++ b/testsuite/gtk/defaultvalue.c @@ -94,8 +94,7 @@ test_type (gconstpointer data) return; /* These leak their GDBusConnections */ - if (g_type_is_a (type, GTK_TYPE_FILE_CHOOSER_BUTTON) || - g_type_is_a (type, GTK_TYPE_FILE_CHOOSER_DIALOG) || + if (g_type_is_a (type, GTK_TYPE_FILE_CHOOSER_DIALOG) || g_type_is_a (type, GTK_TYPE_FILE_CHOOSER_WIDGET) || g_str_equal (g_type_name (type), "GtkPlacesSidebar")) return; diff --git a/testsuite/gtk/focus-chain/widget-factory.tab b/testsuite/gtk/focus-chain/widget-factory.tab index 468e4560fd..b10898543d 100644 --- a/testsuite/gtk/focus-chain/widget-factory.tab +++ b/testsuite/gtk/focus-chain/widget-factory.tab @@ -16,7 +16,6 @@ GtkToggleButton GtkToggleButton GtkButton GtkButton -GtkButton GtkLinkButton GtkSwitch GtkScale diff --git a/testsuite/gtk/focus-chain/widget-factory.tab-backward b/testsuite/gtk/focus-chain/widget-factory.tab-backward index dd7582889a..4025f6adf6 100644 --- a/testsuite/gtk/focus-chain/widget-factory.tab-backward +++ b/testsuite/gtk/focus-chain/widget-factory.tab-backward @@ -12,7 +12,6 @@ GtkSwitch GtkLinkButton GtkButton GtkButton -GtkButton GtkToggleButton GtkToggleButton GtkToggleButton diff --git a/testsuite/gtk/focus-chain/widget-factory.ui b/testsuite/gtk/focus-chain/widget-factory.ui index 654671b4fd..cfa86b68fe 100644 --- a/testsuite/gtk/focus-chain/widget-factory.ui +++ b/testsuite/gtk/focus-chain/widget-factory.ui @@ -854,9 +854,6 @@ Suspendisse feugiat quam quis dolor accumsan cursus. 1
- - - link button diff --git a/testsuite/gtk/focus-chain/widget-factory2.ui b/testsuite/gtk/focus-chain/widget-factory2.ui index 5dd9037329..748c98ffde 100644 --- a/testsuite/gtk/focus-chain/widget-factory2.ui +++ b/testsuite/gtk/focus-chain/widget-factory2.ui @@ -855,9 +855,6 @@ Suspendisse feugiat quam quis dolor accumsan cursus. 1 - - - link button diff --git a/testsuite/gtk/focus-chain/widget-factory3.ui b/testsuite/gtk/focus-chain/widget-factory3.ui index b6d52bea51..d7a2643843 100644 --- a/testsuite/gtk/focus-chain/widget-factory3.ui +++ b/testsuite/gtk/focus-chain/widget-factory3.ui @@ -855,9 +855,6 @@ Suspendisse feugiat quam quis dolor accumsan cursus. 1 - - - link button diff --git a/testsuite/gtk/notify.c b/testsuite/gtk/notify.c index f90fb66be2..12ae9edb89 100644 --- a/testsuite/gtk/notify.c +++ b/testsuite/gtk/notify.c @@ -401,8 +401,7 @@ test_type (gconstpointer data) return; /* These leak their GDBusConnections */ - if (g_type_is_a (type, GTK_TYPE_FILE_CHOOSER_BUTTON) || - g_type_is_a (type, GTK_TYPE_FILE_CHOOSER_DIALOG) || + if (g_type_is_a (type, GTK_TYPE_FILE_CHOOSER_DIALOG) || g_type_is_a (type, GTK_TYPE_FILE_CHOOSER_WIDGET) || g_type_is_a (type, GTK_TYPE_FILE_CHOOSER_NATIVE)) return; diff --git a/testsuite/gtk/object.c b/testsuite/gtk/object.c index d4c13339c8..2efe3cdb65 100644 --- a/testsuite/gtk/object.c +++ b/testsuite/gtk/object.c @@ -57,8 +57,6 @@ list_ignore_properties (gboolean buglist) { "GtkWidget", "has-default", (void*) TRUE, }, /* conflicts with toplevel-less widgets */ { "GtkWidget", "display", (void*) MATCH_ANY_VALUE }, { "GtkCellView", "background", (void*) "", }, /* "" is not a valid background color */ - { "GtkFileChooserButton", "select-multiple", (void*) MATCH_ANY_VALUE }, /* property disabled */ - { "GtkFileChooserButton", "action", (void*) GTK_FILE_CHOOSER_ACTION_SAVE }, { "GtkFileChooserWidget", "select-multiple", (void*) 0x1 }, /* property conflicts */ { "GtkFileChooserDialog", "select-multiple", (void*) MATCH_ANY_VALUE }, /* property disabled */ { "GtkTextView", "overwrite", (void*) MATCH_ANY_VALUE }, /* needs text buffer */ diff --git a/testsuite/gtk/templates.c b/testsuite/gtk/templates.c index 9eb1974213..843fd500d9 100644 --- a/testsuite/gtk/templates.c +++ b/testsuite/gtk/templates.c @@ -330,23 +330,6 @@ test_file_chooser_dialog_show (void) gtk_window_destroy (GTK_WINDOW (widget)); } -static void -test_file_chooser_button_basic (void) -{ - GtkWidget *widget; - gboolean done = FALSE; - - g_test_log_set_fatal_handler (ignore_gvfs_warning, NULL); - - widget = gtk_file_chooser_button_new ("Choose a file !", GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); - g_assert (GTK_IS_FILE_CHOOSER_BUTTON (widget)); - g_timeout_add (100, main_loop_quit_cb, &done); - while (!done) - g_main_context_iteration (NULL, TRUE); - - g_object_unref (g_object_ref_sink (widget)); -} - static void test_font_button_basic (void) { @@ -469,7 +452,6 @@ main (int argc, char **argv) g_test_add_func ("/template/GtkFileChooserWidget/basic", test_file_chooser_widget_basic); g_test_add_func ("/template/GtkFileChooserDialog/basic", test_file_chooser_dialog_basic); g_test_add_func ("/template/GtkFileChooserDialog/show", test_file_chooser_dialog_show); - g_test_add_func ("/template/GtkFileChooserButton/basic", test_file_chooser_button_basic); g_test_add_func ("/template/GtkFontButton/basic", test_font_button_basic); g_test_add_func ("/template/GtkFontChooserWidget/basic", test_font_chooser_widget_basic); g_test_add_func ("/template/GtkFontChooserDialog/basic", test_font_chooser_dialog_basic);