static void ide_editor_perspective_actions_open_file (GSimpleAction *action, GVariant *variant, gpointer user_data) { IdeEditorPerspective *self = user_data; GtkFileChooserNative *chooser; IdeWorkbench *workbench; gint ret; g_assert (G_IS_SIMPLE_ACTION (action)); g_assert (IDE_IS_EDITOR_PERSPECTIVE (self)); workbench = ide_widget_get_workbench (GTK_WIDGET (self)); if (workbench == NULL) { g_warning ("Failed to locate workbench"); return; } chooser = gtk_file_chooser_native_new (_("Open File"), GTK_WINDOW (workbench), GTK_FILE_CHOOSER_ACTION_OPEN, _("Open"), _("Cancel")); gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), FALSE); gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), TRUE); ret = gtk_native_dialog_run (GTK_NATIVE_DIALOG (chooser)); if (ret == GTK_RESPONSE_ACCEPT) { g_autoptr(GPtrArray) ar = NULL; GSList *files; ar = g_ptr_array_new_with_free_func (g_object_unref); files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (chooser)); for (const GSList *iter = files; iter; iter = iter->next) g_ptr_array_add (ar, iter->data); g_slist_free (files); if (ar->len > 0) ide_workbench_open_files_async (workbench, (GFile **)ar->pdata, ar->len, "editor", IDE_WORKBENCH_OPEN_FLAGS_NONE, NULL, NULL, NULL); } gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (chooser)); }
static void gtk_native_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GtkNativeDialog *self = GTK_NATIVE_DIALOG (object); GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self); switch (prop_id) { case PROP_TITLE: g_value_set_string (value, priv->title); break; case PROP_MODAL: g_value_set_boolean (value, priv->modal); break; case PROP_VISIBLE: g_value_set_boolean (value, priv->visible); break; case PROP_TRANSIENT_FOR: g_value_set_object (value, priv->transient_for); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void gtk_native_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GtkNativeDialog *self = GTK_NATIVE_DIALOG (object); switch (prop_id) { case PROP_TITLE: gtk_native_dialog_set_title (self, g_value_get_string (value)); break; case PROP_MODAL: gtk_native_dialog_set_modal (self, g_value_get_boolean (value)); break; case PROP_VISIBLE: if (g_value_get_boolean (value)) gtk_native_dialog_show (self); else gtk_native_dialog_hide (self); break; case PROP_TRANSIENT_FOR: gtk_native_dialog_set_transient_for (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static int run_file_chooser(GtkFileChooser *dlg) { #ifdef USE_GTK_NATIVE_FILE_CHOOSER return gtk_native_dialog_run (GTK_NATIVE_DIALOG (dlg)); #else return gtk_dialog_run (GTK_DIALOG (dlg)); #endif }
static void destroy_file_chooser(GtkFileChooser *dlg) { #ifdef USE_GTK_NATIVE_FILE_CHOOSER gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (dlg)); #else gtk_widget_destroy (GTK_WIDGET (dlg)); #endif }
static void response_cb (GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) { GtkFileChooserNative *self = user_data; FilechooserPortalData *data = self->mode_data; guint32 portal_response; int gtk_response; const char **uris; int i; GVariant *response_data; g_autoptr (GVariant) choices = NULL; g_variant_get (parameters, "(u@a{sv})", &portal_response, &response_data); g_variant_lookup (response_data, "uris", "^a&s", &uris); choices = g_variant_lookup_value (response_data, "choices", G_VARIANT_TYPE ("a(ss)")); if (choices) for (i = 0; i < g_variant_n_children (choices); i++) { const char *id; const char *selected; g_variant_get_child (choices, i, "(&s&s)", &id, &selected); gtk_file_chooser_set_choice (GTK_FILE_CHOOSER (self), id, selected); } g_slist_free_full (self->custom_files, g_object_unref); self->custom_files = NULL; for (i = 0; uris[i]; i++) self->custom_files = g_slist_prepend (self->custom_files, g_file_new_for_uri (uris[i])); switch (portal_response) { case 0: gtk_response = GTK_RESPONSE_OK; break; case 1: gtk_response = GTK_RESPONSE_CANCEL; break; case 2: default: gtk_response = GTK_RESPONSE_DELETE_EVENT; break; } filechooser_portal_data_free (data); self->mode_data = NULL; _gtk_native_dialog_emit_response (GTK_NATIVE_DIALOG (self), gtk_response); }
static void gtk_native_dialog_finalize (GObject *object) { GtkNativeDialog *self = GTK_NATIVE_DIALOG (object); GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self); g_clear_pointer (&priv->title, g_free); g_clear_object (&priv->transient_for); G_OBJECT_CLASS (gtk_native_dialog_parent_class)->finalize (object); }
static void gtk_native_dialog_dispose (GObject *object) { GtkNativeDialog *self = GTK_NATIVE_DIALOG (object); GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self); if (priv->visible) gtk_native_dialog_hide (self); G_OBJECT_CLASS (gtk_native_dialog_parent_class)->dispose (object); }
static void show_dialog (GtkFileChooserNative *self) { GtkFileChooserAction action; const char *accept_label, *cancel_label; action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (self->dialog)); accept_label = self->accept_label; if (accept_label == NULL) accept_label = (action == GTK_FILE_CHOOSER_ACTION_SAVE) ? _("_Save") : _("_Open"); gtk_button_set_label (GTK_BUTTON (self->accept_button), accept_label); cancel_label = self->cancel_label; if (cancel_label == NULL) cancel_label = _("_Cancel"); gtk_button_set_label (GTK_BUTTON (self->cancel_button), cancel_label); gtk_window_set_title (GTK_WINDOW (self->dialog), gtk_native_dialog_get_title (GTK_NATIVE_DIALOG (self))); gtk_window_set_transient_for (GTK_WINDOW (self->dialog), gtk_native_dialog_get_transient_for (GTK_NATIVE_DIALOG (self))); gtk_window_set_modal (GTK_WINDOW (self->dialog), gtk_native_dialog_get_modal (GTK_NATIVE_DIALOG (self))); g_signal_connect (self->dialog, "response", G_CALLBACK (dialog_response_cb), self); g_signal_connect (self->dialog, "update-preview", G_CALLBACK (dialog_update_preview_cb), self); gtk_window_present (GTK_WINDOW (self->dialog)); }
static void dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer data) { GtkFileChooserNative *self = data; g_signal_handlers_disconnect_by_func (self->dialog, dialog_response_cb, self); gtk_widget_hide (self->dialog); _gtk_native_dialog_emit_response (GTK_NATIVE_DIALOG (self), response_id); }
static void open_file_msg_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { FilechooserPortalData *data = user_data; GtkFileChooserNative *self = data->self; GDBusMessage *reply; GError *error = NULL; reply = g_dbus_connection_send_message_with_reply_finish (data->connection, res, &error); if (reply && g_dbus_message_to_gerror (reply, &error)) g_clear_object (&reply); if (reply == NULL) { if (!data->hidden) _gtk_native_dialog_emit_response (GTK_NATIVE_DIALOG (self), GTK_RESPONSE_DELETE_EVENT); g_warning ("Can't open portal file chooser: %s", error->message); g_error_free (error); filechooser_portal_data_free (data); self->mode_data = NULL; return; } g_variant_get_child (g_dbus_message_get_body (reply), 0, "o", &data->portal_handle); if (data->hidden) { /* The dialog was hidden before we got the handle, close it now */ send_close (data); filechooser_portal_data_free (data); self->mode_data = NULL; } else { data->portal_response_signal_id = g_dbus_connection_signal_subscribe (data->connection, "org.freedesktop.portal.Desktop", "org.freedesktop.portal.Request", "Response", data->portal_handle, NULL, G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, response_cb, self, NULL); } g_object_unref (reply); }
static gboolean filechooser_win32_thread_done (gpointer _data) { FilechooserWin32ThreadData *data = _data; GtkFileChooserNative *self = data->self; self->mode_data = NULL; if (!data->skip_response) { g_slist_free_full (self->custom_files, g_object_unref); self->custom_files = g_slist_reverse(data->files); data->files = NULL; _gtk_native_dialog_emit_response (GTK_NATIVE_DIALOG (data->self), data->response); } filechooser_win32_thread_data_free (data); return FALSE; }
static void open_response_cb (GtkNativeDialog *dialog, gint response_id, gpointer user_data) { GtkFileChooserNative *native = user_data; GApplication *app = g_object_get_data (G_OBJECT (native), "app"); GtkWidget *message_dialog; GFile *file; char *contents; GError *error = NULL; if (response_id == GTK_RESPONSE_ACCEPT) { file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (native)); if (g_file_load_contents (file, NULL, &contents, NULL, NULL, &error)) { create_window (app, contents); g_free (contents); } else { message_dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Error loading file: \"%s\"", error->message); g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); gtk_widget_show (message_dialog); g_error_free (error); } } gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (native)); g_object_unref (native); }
static void activate_open (GSimpleAction *action, GVariant *parameter, gpointer user_data) { GApplication *app = user_data; GtkFileChooserNative *native; native = gtk_file_chooser_native_new ("Open File", NULL, GTK_FILE_CHOOSER_ACTION_OPEN, "_Open", "_Cancel"); g_object_set_data_full (G_OBJECT (native), "app", g_object_ref (app), g_object_unref); g_signal_connect (native, "response", G_CALLBACK (open_response_cb), native); gtk_native_dialog_show (GTK_NATIVE_DIALOG (native)); }
gboolean gtk_file_chooser_native_win32_show (GtkFileChooserNative *self) { GThread *thread; FilechooserWin32ThreadData *data; GtkWindow *transient_for; GtkFileChooserAction action; guint update_preview_signal; GSList *filters, *l; int n_filters, i; if (gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (self)) != NULL) return FALSE; update_preview_signal = g_signal_lookup ("update-preview", GTK_TYPE_FILE_CHOOSER); if (g_signal_has_handler_pending (self, update_preview_signal, 0, TRUE)) return FALSE; data = g_new0 (FilechooserWin32ThreadData, 1); filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (self)); n_filters = g_slist_length (filters); if (n_filters > 0) { data->filters = g_new0 (COMDLG_FILTERSPEC, n_filters + 1); for (l = filters, i = 0; l != NULL; l = l->next, i++) { if (!file_filter_to_win32 (l->data, &data->filters[i])) { filechooser_win32_thread_data_free (data); return FALSE; } } self->current_filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (self)); } else { self->current_filter = NULL; } self->mode_data = data; data->self = g_object_ref (self); data->shortcut_uris = gtk_file_chooser_list_shortcut_folder_uris (GTK_FILE_CHOOSER (self->dialog)); data->accept_label = translate_mnemonics (self->accept_label); data->cancel_label = translate_mnemonics (self->cancel_label); action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (self->dialog)); if (action == GTK_FILE_CHOOSER_ACTION_SAVE || action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) data->save = TRUE; if (action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) data->folder = TRUE; if ((action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || action == GTK_FILE_CHOOSER_ACTION_OPEN) && gtk_file_chooser_get_select_multiple (GTK_FILE_CHOOSER (self->dialog))) data->select_multiple = TRUE; if (gtk_file_chooser_get_do_overwrite_confirmation (GTK_FILE_CHOOSER (self->dialog))) data->overwrite_confirmation = TRUE; if (gtk_file_chooser_get_show_hidden (GTK_FILE_CHOOSER (self->dialog))) data->show_hidden = TRUE; transient_for = gtk_native_dialog_get_transient_for (GTK_NATIVE_DIALOG (self)); if (transient_for) { gtk_widget_realize (GTK_WIDGET (transient_for)); data->parent = gdk_win32_surface_get_handle (gtk_widget_get_surface (GTK_WIDGET (transient_for))); if (gtk_native_dialog_get_modal (GTK_NATIVE_DIALOG (self))) data->modal = TRUE; } data->title = g_strdup (gtk_native_dialog_get_title (GTK_NATIVE_DIALOG (self))); if (self->current_file) data->current_file = g_object_ref (self->current_file); else { if (self->current_folder) data->current_folder = g_object_ref (self->current_folder); if (action == GTK_FILE_CHOOSER_ACTION_SAVE || action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) data->current_name = g_strdup (self->current_name); } data->events = file_dialog_events_new (!data->modal, data); thread = g_thread_new ("win32 filechooser", filechooser_win32_thread, data); if (thread == NULL) { filechooser_win32_thread_data_free (data); return FALSE; } return TRUE; }
gboolean gtk_file_chooser_native_portal_show (GtkFileChooserNative *self) { FilechooserPortalData *data; GtkWindow *transient_for; GDBusConnection *connection; char *parent_window_str; GDBusMessage *message; GVariantBuilder opt_builder; GtkFileChooserAction action; gboolean multiple; const char *method_name; if (!gtk_should_use_portal ()) return FALSE; connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); if (connection == NULL) return FALSE; action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (self)); multiple = gtk_file_chooser_get_select_multiple (GTK_FILE_CHOOSER (self)); if (action == GTK_FILE_CHOOSER_ACTION_OPEN) method_name = "OpenFile"; else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) method_name = "SaveFile"; else { g_warning ("GTK_FILE_CHOOSER_ACTION_%s is not supported by GtkFileChooserNativePortal", action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ? "SELECT_FOLDER" : "CREATE_FOLDER"); return FALSE; } data = g_new0 (FilechooserPortalData, 1); data->self = g_object_ref (self); data->connection = connection; message = g_dbus_message_new_method_call ("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop", "org.freedesktop.portal.FileChooser", method_name); parent_window_str = NULL; transient_for = gtk_native_dialog_get_transient_for (GTK_NATIVE_DIALOG (self)); if (transient_for != NULL && gtk_widget_is_visible (GTK_WIDGET (transient_for))) { GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (transient_for)); #ifdef GDK_WINDOWING_X11 if (GDK_IS_X11_WINDOW(window)) parent_window_str = g_strdup_printf ("x11:%x", (guint32)gdk_x11_window_get_xid (window)); #endif } if (gtk_native_dialog_get_modal (GTK_NATIVE_DIALOG (self))) data->modal = TRUE; if (data->modal && transient_for != NULL) { data->grab_widget = gtk_invisible_new_for_screen (gtk_widget_get_screen (GTK_WIDGET (transient_for))); gtk_grab_add (GTK_WIDGET (data->grab_widget)); } g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT); g_variant_builder_add (&opt_builder, "{sv}", "multiple", g_variant_new_boolean (multiple)); if (self->accept_label) g_variant_builder_add (&opt_builder, "{sv}", "accept_label", g_variant_new_string (self->accept_label)); if (self->cancel_label) g_variant_builder_add (&opt_builder, "{sv}", "cancel_label", g_variant_new_string (self->cancel_label)); g_variant_builder_add (&opt_builder, "{sv}", "modal", g_variant_new_boolean (data->modal)); g_variant_builder_add (&opt_builder, "{sv}", "filters", get_filters (GTK_FILE_CHOOSER (self))); if (GTK_FILE_CHOOSER_NATIVE (self)->current_name) g_variant_builder_add (&opt_builder, "{sv}", "current_name", g_variant_new_string (GTK_FILE_CHOOSER_NATIVE (self)->current_name)); if (GTK_FILE_CHOOSER_NATIVE (self)->current_folder) { gchar *path; path = g_file_get_path (GTK_FILE_CHOOSER_NATIVE (self)->current_folder); g_variant_builder_add (&opt_builder, "{sv}", "current_folder", g_variant_new_bytestring (path)); g_free (path); } if (GTK_FILE_CHOOSER_NATIVE (self)->current_file) { gchar *path; path = g_file_get_path (GTK_FILE_CHOOSER_NATIVE (self)->current_file); g_variant_builder_add (&opt_builder, "{sv}", "current_file", g_variant_new_bytestring (path)); g_free (path); } if (GTK_FILE_CHOOSER_NATIVE (self)->choices) g_variant_builder_add (&opt_builder, "{sv}", "choices", serialize_choices (GTK_FILE_CHOOSER_NATIVE (self))); g_dbus_message_set_body (message, g_variant_new ("(ss@a{sv})", parent_window_str ? parent_window_str : "", gtk_native_dialog_get_title (GTK_NATIVE_DIALOG (self)), g_variant_builder_end (&opt_builder))); g_free (parent_window_str); g_dbus_connection_send_message_with_reply (data->connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, G_MAXINT, NULL, NULL, open_file_msg_cb, data); g_object_unref (message); self->mode_data = data; return TRUE; }
GtkFileChooser * ephy_create_file_chooser (const char *title, GtkWidget *parent, GtkFileChooserAction action, EphyFileFilterDefault default_filter) { GtkFileChooser *dialog; GtkFileFilter *filter[EPHY_FILE_FILTER_LAST]; g_autofree char *downloads_dir = NULL; GtkWidget *preview = gtk_image_new (); g_assert (GTK_IS_WINDOW (parent)); g_assert (default_filter >= 0 && default_filter <= EPHY_FILE_FILTER_LAST); dialog = GTK_FILE_CHOOSER (gtk_file_chooser_native_new (title, GTK_WINDOW (parent), action, NULL, _("_Cancel"))); gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE); downloads_dir = ephy_file_get_downloads_dir (); gtk_file_chooser_add_shortcut_folder (dialog, downloads_dir, NULL); if (action == GTK_FILE_CHOOSER_ACTION_OPEN || action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) { gtk_file_chooser_native_set_accept_label (GTK_FILE_CHOOSER_NATIVE (dialog), _("_Open")); } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) { gtk_file_chooser_native_set_accept_label (GTK_FILE_CHOOSER_NATIVE (dialog), _("_Save")); } gtk_file_chooser_set_preview_widget (dialog, preview); gtk_file_chooser_set_use_preview_label (dialog, FALSE); g_signal_connect (dialog, "update-preview", G_CALLBACK (update_preview_cb), preview); if (default_filter != EPHY_FILE_FILTER_NONE) { filter[EPHY_FILE_FILTER_ALL_SUPPORTED] = ephy_file_chooser_add_mime_filter (dialog, _("All supported types"), "text/html", "application/xhtml+xml", "text/xml", "message/rfc822", /* MHTML */ "multipart/related", /* MHTML */ "application/x-mimearchive", /* MHTML */ "image/png", "image/jpeg", "image/gif", "image/webp", NULL); filter[EPHY_FILE_FILTER_WEBPAGES] = ephy_file_chooser_add_mime_filter (dialog, _("Web pages"), "text/html", "application/xhtml+xml", "text/xml", "message/rfc822", /* MHTML */ "multipart/related", /* MHTML */ "application/x-mimearchive", /* MHTML */ NULL); filter[EPHY_FILE_FILTER_IMAGES] = ephy_file_chooser_add_mime_filter (dialog, _("Images"), "image/png", "image/jpeg", "image/gif", "image/webp", NULL); filter[EPHY_FILE_FILTER_ALL] = ephy_file_chooser_add_pattern_filter (dialog, _("All files"), "*", NULL); gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter[default_filter]); } return dialog; }