static gboolean handle_save_file (XdpFileChooser *object, GDBusMethodInvocation *invocation, const gchar *arg_parent_window, const gchar *arg_title, GVariant *arg_options) { Request *request = request_from_invocation (invocation); const char *app_id = request->app_id; g_autoptr(GError) error = NULL; XdpImplRequest *impl_request; GVariantBuilder options; REQUEST_AUTOLOCK (request); g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT); xdp_filter_options (arg_options, &options, save_file_options, G_N_ELEMENTS (save_file_options)); impl_request = xdp_impl_request_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (impl)), G_DBUS_PROXY_FLAGS_NONE, g_dbus_proxy_get_name (G_DBUS_PROXY (impl)), request->id, NULL, &error); if (!impl_request) { g_dbus_method_invocation_return_gerror (invocation, error); return TRUE; } g_object_set_data (G_OBJECT (request), "for-save", GINT_TO_POINTER (TRUE)); request_set_impl_request (request, impl_request); request_export (request, g_dbus_method_invocation_get_connection (invocation)); xdp_impl_file_chooser_call_save_file (impl, request->id, app_id, arg_parent_window, arg_title, g_variant_builder_end (&options), NULL, save_file_done, g_object_ref (request)); xdp_file_chooser_complete_open_file (object, invocation, request->id); return TRUE; }
static gboolean handle_save_file (XdpFileChooser *object, GDBusMethodInvocation *invocation, const gchar *arg_parent_window, const gchar *arg_title, GVariant *arg_options) { Request *request = request_from_invocation (invocation); const char *app_id = request->app_id; const gchar *sender = g_dbus_method_invocation_get_sender (invocation); g_autoptr(GError) error = NULL; g_autofree char *impl_handle = NULL; GVariantBuilder options; g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT); copy_options (arg_options, &options, save_file_options, G_N_ELEMENTS (save_file_options)); if (!xdp_impl_file_chooser_call_save_file_sync (impl, sender, app_id, arg_parent_window, arg_title, g_variant_builder_end (&options), &impl_handle, NULL, &error)) { g_dbus_method_invocation_return_gerror (invocation, error); return TRUE; } g_object_set_data_full (G_OBJECT (request), "impl-handle", g_strdup (impl_handle), g_free); register_handle (impl_handle, request); g_signal_connect (request, "handle-close", (GCallback)handle_close, request); REQUEST_AUTOLOCK (request); request_export (request, g_dbus_method_invocation_get_connection (invocation)); xdp_file_chooser_complete_open_file (object, invocation, request->id); return TRUE; }
static gboolean handle_file_chooser_open (XdpFileChooser *object, GDBusMethodInvocation *invocation, const gchar *arg_sender, const gchar *arg_app_id, const gchar *arg_parent_window, const gchar *arg_title, GVariant *arg_options) { const gchar *method_name; GtkFileChooserAction action; gboolean multiple; GtkWidget *dialog; GdkWindow *foreign_parent = NULL; GtkWidget *fake_parent; FileDialogHandle *handle; XdpFileChooser *chooser = XDP_FILE_CHOOSER (g_dbus_method_invocation_get_user_data (invocation)); const char *cancel_label; const char *accept_label; GVariantIter *iter; const char *current_name; const char *path; g_autoptr (GVariant) choices = NULL; method_name = g_dbus_method_invocation_get_method_name (invocation); g_print ("%s, app_id: %s, object: %p, user_data: %p\n", method_name, arg_app_id, object, g_dbus_method_invocation_get_user_data (invocation)); fake_parent = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_object_ref_sink (fake_parent); action = GTK_FILE_CHOOSER_ACTION_OPEN; multiple = FALSE; if (strcmp (method_name, "SaveFile") == 0) action = GTK_FILE_CHOOSER_ACTION_SAVE; else if (strcmp (method_name, "OpenFiles") == 0) multiple = TRUE; if (!g_variant_lookup (arg_options, "accept_label", "&s", &accept_label)) accept_label = _("_Open"); cancel_label = _("_Cancel"); dialog = gtk_file_chooser_dialog_new (arg_title, GTK_WINDOW (fake_parent), action, cancel_label, GTK_RESPONSE_CANCEL, accept_label, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), multiple); handle = dialog_handle_new (arg_app_id, arg_sender, dialog, G_DBUS_INTERFACE_SKELETON (chooser)); handle->dialog = dialog; handle->action = action; handle->multiple = multiple; choices = g_variant_lookup_value (arg_options, "choices", G_VARIANT_TYPE ("a(ssa(ss)s)")); if (choices) { int i; GtkWidget *box; box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); gtk_widget_show (box); for (i = 0; i < g_variant_n_children (choices); i++) { GVariant *value = g_variant_get_child_value (choices, i); gtk_container_add (GTK_CONTAINER (box), deserialize_choice (value, handle)); } gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), box); } if (g_variant_lookup (arg_options, "filters", "a(sa(us))", &iter)) { GVariant *variant; while (g_variant_iter_next (iter, "@(sa(us))", &variant)) { GtkFileFilter *filter; filter = gtk_file_filter_from_gvariant (variant); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); g_variant_unref (variant); } g_variant_iter_free (iter); } if (strcmp (method_name, "SaveFile") == 0) { if (g_variant_lookup (arg_options, "current_name", "&s", ¤t_name)) gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), current_name); /* TODO: is this useful ? * In a sandboxed situation, the current folder and current file * are likely in the fuse filesystem */ if (g_variant_lookup (arg_options, "current_folder", "&ay", &path)) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), path); if (g_variant_lookup (arg_options, "current_file", "&ay", &path)) gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (dialog), path); } g_object_unref (fake_parent); #ifdef GDK_WINDOWING_X11 if (g_str_has_prefix (arg_parent_window, "x11:")) { int xid; if (sscanf (arg_parent_window, "x11:%x", &xid) != 1) g_warning ("invalid xid"); else foreign_parent = gdk_x11_window_foreign_new_for_display (gtk_widget_get_display (dialog), xid); } #endif else g_warning ("Unhandled parent window type %s\n", arg_parent_window); gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (handle_file_chooser_open_response), handle); if (action == GTK_FILE_CHOOSER_ACTION_OPEN) { GtkWidget *readonly; readonly = gtk_check_button_new_with_label ("Open files read-only"); gtk_widget_show (readonly); g_signal_connect (readonly, "toggled", G_CALLBACK (read_only_toggled), handle); gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), readonly); } gtk_widget_realize (dialog); if (foreign_parent) gdk_window_set_transient_for (gtk_widget_get_window (dialog), foreign_parent); gtk_widget_show (dialog); xdp_file_chooser_complete_open_file (chooser, invocation, handle->base.id); return TRUE; }
static gboolean handle_open_file (XdpFileChooser *object, GDBusMethodInvocation *invocation, const gchar *arg_parent_window, const gchar *arg_title, GVariant *arg_options) { Request *request = request_from_invocation (invocation); const char *app_id = request->app_id; g_autoptr(GError) error = NULL; g_autoptr(XdpImplRequest) impl_request = NULL; GVariantBuilder options; g_autoptr(GVariant) value = NULL; REQUEST_AUTOLOCK (request); value = g_variant_lookup_value (arg_options, "filters", NULL); if (value != NULL) { if (!check_filters (value, &error)) { g_prefix_error (&error, "invalid filters: "); g_dbus_method_invocation_return_gerror (invocation, error); return TRUE; } g_variant_unref (value); value = NULL; } value = g_variant_lookup_value (arg_options, "choices", NULL); if (value != NULL) { if (!check_choices (value, &error)) { g_prefix_error (&error, "invalid choices: "); g_dbus_method_invocation_return_gerror (invocation, error); return TRUE; } g_variant_unref (value); value = NULL; } g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT); xdp_filter_options (arg_options, &options, open_file_options, G_N_ELEMENTS (open_file_options)); impl_request = xdp_impl_request_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (impl)), G_DBUS_PROXY_FLAGS_NONE, g_dbus_proxy_get_name (G_DBUS_PROXY (impl)), request->id, NULL, &error); if (!impl_request) { g_dbus_method_invocation_return_gerror (invocation, error); return TRUE; } request_set_impl_request (request, impl_request); request_export (request, g_dbus_method_invocation_get_connection (invocation)); xdp_impl_file_chooser_call_open_file (impl, request->id, app_id, arg_parent_window, arg_title, g_variant_builder_end (&options), NULL, open_file_done, g_object_ref (request)); xdp_file_chooser_complete_open_file (object, invocation, request->id); return TRUE; }