From 480bad83829567b8d89d67c56f6174ad9fbd7c5a Mon Sep 17 00:00:00 2001 From: robxnano <12855608-robxnano@users.noreply.gitlab.com> Date: Sun, 5 Nov 2023 21:17:22 +0000 Subject: Use GtkFileChooserNative --- src/remmina_ftp_client.c | 14 +++++++------- src/remmina_main.c | 29 ++++++++++++++++------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/remmina_ftp_client.c b/src/remmina_ftp_client.c index 3abd4a295..294f2db42 100644 --- a/src/remmina_ftp_client.c +++ b/src/remmina_ftp_client.c @@ -403,21 +403,21 @@ remmina_ftp_client_get_download_dir(RemminaFTPClient *client) { TRACE_CALL(__func__); RemminaFTPClientPriv *priv = (RemminaFTPClientPriv*)client->priv; - GtkWidget *dialog; + GtkFileChooserNative *dialog; gchar *localdir = NULL; - dialog = gtk_file_chooser_dialog_new(_("Choose download location"), + dialog = gtk_file_chooser_native_new(_("Choose download location"), GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(client))), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - "_Cancel", GTK_RESPONSE_CANCEL, "_OK", GTK_RESPONSE_ACCEPT, NULL); + _("_OK"), _("_Cancel")); if (priv->working_directory) { gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), priv->working_directory); } - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + if (gtk_native_dialog_run(GTK_NATIVE_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { g_free(priv->working_directory); priv->working_directory = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog)); localdir = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); } - gtk_widget_destroy(dialog); + gtk_native_dialog_destroy(GTK_NATIVE_DIALOG(dialog)); return localdir; } @@ -604,8 +604,8 @@ static void remmina_ftp_client_action_upload(GObject *object, RemminaFTPClient * struct stat st; dialog = gtk_file_chooser_dialog_new(_("Choose a file to upload"), - GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(client))), GTK_FILE_CHOOSER_ACTION_OPEN, "_Cancel", - GTK_RESPONSE_CANCEL, "_OK", GTK_RESPONSE_ACCEPT, NULL); + GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(client))), GTK_FILE_CHOOSER_ACTION_OPEN, _("_Cancel"), + GTK_RESPONSE_CANCEL, _("Upload"), GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); if (priv->working_directory) { gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), priv->working_directory); diff --git a/src/remmina_main.c b/src/remmina_main.c index f3de6a5c0..7aabc3e5e 100644 --- a/src/remmina_main.c +++ b/src/remmina_main.c @@ -1219,7 +1219,7 @@ static void remmina_main_import_file_list(GSList *files) remmina_main_load_files(); } -static void remmina_main_action_tools_import_on_response(GtkDialog *dialog, gint response_id, gpointer user_data) +static void remmina_main_action_tools_import_on_response(GtkNativeDialog *dialog, gint response_id, gpointer user_data) { TRACE_CALL(__func__); GSList *files; @@ -1228,19 +1228,20 @@ static void remmina_main_action_tools_import_on_response(GtkDialog *dialog, gint files = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); remmina_main_import_file_list(files); } - gtk_widget_destroy(GTK_WIDGET(dialog)); + gtk_native_dialog_destroy(dialog); } void remmina_main_on_action_tools_import(GSimpleAction *action, GVariant *param, gpointer data) { TRACE_CALL(__func__); - GtkWidget *dialog; + GtkFileChooserNative *chooser; - dialog = gtk_file_chooser_dialog_new(_("Import"), remminamain->window, GTK_FILE_CHOOSER_ACTION_OPEN, "Import", - GTK_RESPONSE_ACCEPT, NULL); - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); - g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(remmina_main_action_tools_import_on_response), NULL); - gtk_widget_show(dialog); + chooser = gtk_file_chooser_native_new(_("Import"), remminamain->window, + GTK_FILE_CHOOSER_ACTION_OPEN, _("Import"), _("_Cancel")); + gtk_native_dialog_set_modal(GTK_NATIVE_DIALOG(chooser), TRUE); + gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(chooser), TRUE); + g_signal_connect(chooser, "response", G_CALLBACK(remmina_main_action_tools_import_on_response), NULL); + gtk_native_dialog_show(GTK_NATIVE_DIALOG(chooser)); } void remmina_main_on_action_tools_export(GSimpleAction *action, GVariant *param, gpointer data) @@ -1249,6 +1250,7 @@ void remmina_main_on_action_tools_export(GSimpleAction *action, GVariant *param, RemminaFilePlugin *plugin; RemminaFile *remminafile; GtkWidget *dialog; + GtkFileChooserNative *chooser; if (!remminamain->priv->selected_filename) return; @@ -1258,11 +1260,12 @@ void remmina_main_on_action_tools_export(GSimpleAction *action, GVariant *param, return; plugin = remmina_plugin_manager_get_export_file_handler(remminafile); if (plugin) { - dialog = gtk_file_chooser_dialog_new(plugin->export_hints, remminamain->window, - GTK_FILE_CHOOSER_ACTION_SAVE, _("_Save"), GTK_RESPONSE_ACCEPT, NULL); - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) - plugin->export_func(plugin, remminafile, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog))); - gtk_widget_destroy(dialog); + chooser = gtk_file_chooser_native_new(plugin->export_hints, remminamain->window, + GTK_FILE_CHOOSER_ACTION_SAVE, _("_Save"), _("_Cancel")); + gtk_native_dialog_set_modal(GTK_NATIVE_DIALOG(chooser), TRUE); + if (gtk_native_dialog_run(GTK_NATIVE_DIALOG(chooser)) == GTK_RESPONSE_ACCEPT) + plugin->export_func(plugin, remminafile, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser))); + gtk_native_dialog_destroy(GTK_NATIVE_DIALOG(chooser)); } else { dialog = gtk_message_dialog_new(remminamain->window, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("This protocol does not support exporting.")); -- cgit v1.2.3 From 5855830865ba9c4a6fb7598eab654569ccf50902 Mon Sep 17 00:00:00 2001 From: robxnano <12855608-robxnano@users.noreply.gitlab.com> Date: Tue, 7 Nov 2023 14:23:34 +0000 Subject: Use callback for file chooser Backported from GTK4 development branch. Removes use of deprecated gtk_native_dialog_run function. --- src/remmina_main.c | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/src/remmina_main.c b/src/remmina_main.c index 7aabc3e5e..64c42aeec 100644 --- a/src/remmina_main.c +++ b/src/remmina_main.c @@ -1244,6 +1244,20 @@ void remmina_main_on_action_tools_import(GSimpleAction *action, GVariant *param, gtk_native_dialog_show(GTK_NATIVE_DIALOG(chooser)); } +static void on_export_save_response (GtkFileChooserNative *dialog, int response, RemminaFile *remminafile) +{ + if (response == GTK_RESPONSE_ACCEPT) { + RemminaFilePlugin *plugin = remmina_plugin_manager_get_export_file_handler(remminafile); + if (plugin){ + gchar *path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + plugin->export_func(plugin, remminafile, path); + g_free(path); + } + } + remmina_file_free(remminafile); + gtk_native_dialog_destroy(GTK_NATIVE_DIALOG(dialog)); +} + void remmina_main_on_action_tools_export(GSimpleAction *action, GVariant *param, gpointer data) { TRACE_CALL(__func__); @@ -1252,27 +1266,39 @@ void remmina_main_on_action_tools_export(GSimpleAction *action, GVariant *param, GtkWidget *dialog; GtkFileChooserNative *chooser; - if (!remminamain->priv->selected_filename) + if (!remminamain->priv->selected_filename) { + dialog = gtk_message_dialog_new(remminamain->window, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + _("Select the connection profile.")); + g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_widget_show(dialog); return; + } remminafile = remmina_file_load(remminamain->priv->selected_filename); - if (remminafile == NULL) + if (remminafile == NULL) { + dialog = gtk_message_dialog_new(remminamain->window, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + _("Remmina couldn't export.")); + g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_widget_show(dialog); return; + } + plugin = remmina_plugin_manager_get_export_file_handler(remminafile); if (plugin) { chooser = gtk_file_chooser_native_new(plugin->export_hints, remminamain->window, GTK_FILE_CHOOSER_ACTION_SAVE, _("_Save"), _("_Cancel")); gtk_native_dialog_set_modal(GTK_NATIVE_DIALOG(chooser), TRUE); - if (gtk_native_dialog_run(GTK_NATIVE_DIALOG(chooser)) == GTK_RESPONSE_ACCEPT) - plugin->export_func(plugin, remminafile, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser))); - gtk_native_dialog_destroy(GTK_NATIVE_DIALOG(chooser)); - } else { + g_signal_connect(chooser, "response", G_CALLBACK(on_export_save_response), remminafile); + gtk_native_dialog_show(GTK_NATIVE_DIALOG(chooser)); + } else + { + remmina_file_free(remminafile); dialog = gtk_message_dialog_new(remminamain->window, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("This protocol does not support exporting.")); g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), NULL); gtk_widget_show(dialog); + return; } - remmina_file_free(remminafile); } void remmina_main_on_action_application_plugins(GSimpleAction *action, GVariant *param, gpointer data) -- cgit v1.2.3 From de799c43940ee4a792dfacfe926bed07173f5f4e Mon Sep 17 00:00:00 2001 From: robxnano <12855608-robxnano@users.noreply.gitlab.com> Date: Tue, 7 Nov 2023 15:35:42 +0000 Subject: Add filters to import/export file choosers --- src/remmina_main.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/remmina_main.c b/src/remmina_main.c index 64c42aeec..f55d280cb 100644 --- a/src/remmina_main.c +++ b/src/remmina_main.c @@ -1231,6 +1231,27 @@ static void remmina_main_action_tools_import_on_response(GtkNativeDialog *dialog gtk_native_dialog_destroy(dialog); } +static void remmina_set_file_chooser_filters(GtkFileChooser *chooser) +{ + GtkFileFilter *filter; + + g_return_if_fail(GTK_IS_FILE_CHOOSER(chooser)); + + filter = gtk_file_filter_new(); + gtk_file_filter_set_name(filter, _("RDP Files")); + gtk_file_filter_add_pattern(filter, "*.rdp"); + gtk_file_filter_add_pattern(filter, "*.rdpx"); + gtk_file_filter_add_pattern(filter, "*.RDP"); + gtk_file_filter_add_pattern(filter, "*.RDPX"); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(chooser), filter); + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(chooser), filter); + + filter = gtk_file_filter_new(); + gtk_file_filter_set_name(filter, _("All Files")); + gtk_file_filter_add_pattern(filter, "*"); + gtk_file_chooser_add_filter(chooser, filter); +} + void remmina_main_on_action_tools_import(GSimpleAction *action, GVariant *param, gpointer data) { TRACE_CALL(__func__); @@ -1239,6 +1260,7 @@ void remmina_main_on_action_tools_import(GSimpleAction *action, GVariant *param, chooser = gtk_file_chooser_native_new(_("Import"), remminamain->window, GTK_FILE_CHOOSER_ACTION_OPEN, _("Import"), _("_Cancel")); gtk_native_dialog_set_modal(GTK_NATIVE_DIALOG(chooser), TRUE); + remmina_set_file_chooser_filters(GTK_FILE_CHOOSER(chooser)); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(chooser), TRUE); g_signal_connect(chooser, "response", G_CALLBACK(remmina_main_action_tools_import_on_response), NULL); gtk_native_dialog_show(GTK_NATIVE_DIALOG(chooser)); @@ -1288,6 +1310,7 @@ void remmina_main_on_action_tools_export(GSimpleAction *action, GVariant *param, chooser = gtk_file_chooser_native_new(plugin->export_hints, remminamain->window, GTK_FILE_CHOOSER_ACTION_SAVE, _("_Save"), _("_Cancel")); gtk_native_dialog_set_modal(GTK_NATIVE_DIALOG(chooser), TRUE); + remmina_set_file_chooser_filters(GTK_FILE_CHOOSER(chooser)); g_signal_connect(chooser, "response", G_CALLBACK(on_export_save_response), remminafile); gtk_native_dialog_show(GTK_NATIVE_DIALOG(chooser)); } else -- cgit v1.2.3 From 13651230b5b58b3988968868903a1736f6f2f212 Mon Sep 17 00:00:00 2001 From: robxnano <12855608-robxnano@users.noreply.gitlab.com> Date: Tue, 7 Nov 2023 15:38:39 +0000 Subject: Pre-fill export dialog with profile name --- src/remmina_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/remmina_main.c b/src/remmina_main.c index f55d280cb..60fc4e47a 100644 --- a/src/remmina_main.c +++ b/src/remmina_main.c @@ -1287,6 +1287,7 @@ void remmina_main_on_action_tools_export(GSimpleAction *action, GVariant *param, RemminaFile *remminafile; GtkWidget *dialog; GtkFileChooserNative *chooser; + gchar *export_name; if (!remminamain->priv->selected_filename) { dialog = gtk_message_dialog_new(remminamain->window, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, @@ -1311,6 +1312,9 @@ void remmina_main_on_action_tools_export(GSimpleAction *action, GVariant *param, GTK_FILE_CHOOSER_ACTION_SAVE, _("_Save"), _("_Cancel")); gtk_native_dialog_set_modal(GTK_NATIVE_DIALOG(chooser), TRUE); remmina_set_file_chooser_filters(GTK_FILE_CHOOSER(chooser)); + export_name = g_strdup_printf("%s.rdp", remminamain->priv->selected_name); + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(chooser), export_name); + g_free(export_name); g_signal_connect(chooser, "response", G_CALLBACK(on_export_save_response), remminafile); gtk_native_dialog_show(GTK_NATIVE_DIALOG(chooser)); } else -- cgit v1.2.3 From 6c06f87665ca100c23e867df60aeefa244272229 Mon Sep 17 00:00:00 2001 From: robxnano <12855608-robxnano@users.noreply.gitlab.com> Date: Tue, 7 Nov 2023 15:43:30 +0000 Subject: export: Don't automatically add file extension xdg-desktop-portal only allows access to the file named in the save dialog. Removing this code allows for better compatibility with sandboxing APIs. --- plugins/rdp/rdp_file.c | 14 ++------------ src/remmina_main.c | 1 + 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/plugins/rdp/rdp_file.c b/plugins/rdp/rdp_file.c index cfd8c3057..fc161e850 100644 --- a/plugins/rdp/rdp_file.c +++ b/plugins/rdp/rdp_file.c @@ -283,25 +283,15 @@ gboolean remmina_rdp_file_export(RemminaFilePlugin *plugin, RemminaFile *remmina { TRACE_CALL(__func__); FILE *fp; - gchar *p; gboolean ret; - p = strrchr(to_file, '.'); - - if (p && (g_strcmp0(p + 1, "rdp") == 0 || g_strcmp0(p + 1, "RDP") == 0)) - p = g_strdup(to_file); - else - p = g_strdup_printf("%s.rdp", to_file); - - fp = g_fopen(p, "w+"); + fp = g_fopen(to_file, "w+"); if (fp == NULL) { - g_print("Failed to export %s\n", p); - g_free(p); + g_print("Failed to export %s\n", to_file); return FALSE; } - g_free(p); ret = remmina_rdp_file_export_channel(remminafile, fp); fclose(fp); diff --git a/src/remmina_main.c b/src/remmina_main.c index 60fc4e47a..b4dd37233 100644 --- a/src/remmina_main.c +++ b/src/remmina_main.c @@ -1312,6 +1312,7 @@ void remmina_main_on_action_tools_export(GSimpleAction *action, GVariant *param, GTK_FILE_CHOOSER_ACTION_SAVE, _("_Save"), _("_Cancel")); gtk_native_dialog_set_modal(GTK_NATIVE_DIALOG(chooser), TRUE); remmina_set_file_chooser_filters(GTK_FILE_CHOOSER(chooser)); + gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(chooser), TRUE); export_name = g_strdup_printf("%s.rdp", remminamain->priv->selected_name); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(chooser), export_name); g_free(export_name); -- cgit v1.2.3