diff options
author | Antenore Gatta <antenore@simbiosi.org> | 2018-05-03 15:38:44 +0300 |
---|---|---|
committer | Antenore Gatta <antenore@simbiosi.org> | 2018-05-03 15:38:44 +0300 |
commit | d77997ca5c06c1dd971cf85383e81bd6584be746 (patch) | |
tree | 78a08a34126a30a25655ca748b9e2197e918102b /src/remmina_main.c | |
parent | bcf9990358f0ac9423734421be45c38fdccdf1f0 (diff) |
Renamed remmina in src and moved source files
Diffstat (limited to 'src/remmina_main.c')
-rw-r--r-- | src/remmina_main.c | 1272 |
1 files changed, 1272 insertions, 0 deletions
diff --git a/src/remmina_main.c b/src/remmina_main.c new file mode 100644 index 000000000..e73d16580 --- /dev/null +++ b/src/remmina_main.c @@ -0,0 +1,1272 @@ +/* + * Remmina - The GTK+ Remote Desktop Client + * Copyright (C) 2009-2011 Vic Lee + * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo + * Copyright (C) 2016-2018 Antenore Gatta, Giovanni Panozzo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. * If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. * If you + * do not wish to do so, delete this exception statement from your + * version. * If you delete this exception statement from all source + * files in the program, then also delete it here. + * + */ + +#include "config.h" +#include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> +#include <glib/gi18n.h> +#include "remmina_string_array.h" +#include "remmina_public.h" +#include "remmina_file.h" +#include "remmina_file_manager.h" +#include "remmina_file_editor.h" +#include "remmina_connection_window.h" +#include "remmina_about.h" +#include "remmina_pref.h" +#include "remmina_pref_dialog.h" +#include "remmina_widget_pool.h" +#include "remmina_plugin_manager.h" +#include "remmina_log.h" +#include "remmina_icon.h" +#include "remmina_main.h" +#include "remmina_exec.h" +#include "remmina_mpchange.h" +#include "remmina_external_tools.h" +#include "remmina/remmina_trace_calls.h" +#include "remmina_stats_sender.h" + +static RemminaMain *remminamain; + +#define GET_OBJECT(object_name) gtk_builder_get_object(remminamain->builder, object_name) + +enum { + PROTOCOL_COLUMN, + NAME_COLUMN, + GROUP_COLUMN, + SERVER_COLUMN, + DATE_COLUMN, + FILENAME_COLUMN, + N_COLUMNS +}; + +static GtkTargetEntry remmina_drop_types[] = +{ + { "text/uri-list", 0, 1 } +}; + +static char *quick_connect_plugin_list[] = +{ + "RDP", "VNC", "SSH", "NX", "SPICE" +}; + +static void remmina_main_save_size(void) +{ + TRACE_CALL(__func__); + if ((gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(remminamain->window))) & GDK_WINDOW_STATE_MAXIMIZED) == 0) { + gtk_window_get_size(remminamain->window, &remmina_pref.main_width, &remmina_pref.main_height); + remmina_pref.main_maximize = FALSE; + }else { + remmina_pref.main_maximize = TRUE; + } +} + +static void remmina_main_save_expanded_group_func(GtkTreeView *tree_view, GtkTreePath *path, gpointer user_data) +{ + TRACE_CALL(__func__); + GtkTreeIter iter; + gchar *group; + + gtk_tree_model_get_iter(remminamain->priv->file_model_sort, &iter, path); + gtk_tree_model_get(remminamain->priv->file_model_sort, &iter, GROUP_COLUMN, &group, -1); + if (group) { + remmina_string_array_add(remminamain->priv->expanded_group, group); + g_free(group); + } +} + +static void remmina_main_save_expanded_group(void) +{ + TRACE_CALL(__func__); + if (GTK_IS_TREE_STORE(remminamain->priv->file_model)) { + if (remminamain->priv->expanded_group) { + remmina_string_array_free(remminamain->priv->expanded_group); + } + remminamain->priv->expanded_group = remmina_string_array_new(); + gtk_tree_view_map_expanded_rows(remminamain->tree_files_list, + (GtkTreeViewMappingFunc)remmina_main_save_expanded_group_func, NULL); + } +} + +void remmina_main_save_before_destroy() +{ + if (!remminamain || !remminamain->window) + return; + remmina_main_save_size(); + remmina_main_save_expanded_group(); + remmina_pref_save(); +} + +static gboolean remmina_main_dexit(gpointer data) +{ + /* Try to exit remmina after a delete window event */ + TRACE_CALL(__func__); + remmina_application_condexit(REMMINA_CONDEXIT_ONMAINWINDELETE); + return FALSE; +} + +gboolean remmina_main_on_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) +{ + TRACE_CALL(__func__); + remmina_main_save_before_destroy(); + + // Forget the main window: it has been deleted + remminamain->window = NULL; + g_idle_add(remmina_main_dexit, NULL); + + return FALSE; +} + +void remmina_main_destroy() +{ + TRACE_CALL(__func__); + + /* Called when main window is destroyed via a call of gtk_widget_destroy() */ + if (remminamain) { + if (remminamain->window) + remmina_main_save_before_destroy(); + g_free(remmina_pref.expanded_group); + remmina_pref.expanded_group = remmina_string_array_to_string(remminamain->priv->expanded_group); + remmina_string_array_free(remminamain->priv->expanded_group); + remminamain->priv->expanded_group = NULL; + + if (remminamain->priv->file_model) + g_object_unref(G_OBJECT(remminamain->priv->file_model)); + g_object_unref(G_OBJECT(remminamain->priv->file_model_filter)); + g_object_unref(remminamain->builder); + g_free(remminamain->priv->selected_filename); + g_free(remminamain->priv->selected_name); + g_free(remminamain->priv); + g_free(remminamain); + + remminamain = NULL; + } +} + +static void remmina_main_clear_selection_data(void) +{ + TRACE_CALL(__func__); + g_free(remminamain->priv->selected_filename); + g_free(remminamain->priv->selected_name); + remminamain->priv->selected_filename = NULL; + remminamain->priv->selected_name = NULL; + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + gtk_action_group_set_sensitive(remminamain->actiongroup_connection, FALSE); + G_GNUC_END_IGNORE_DEPRECATIONS +} + +#ifdef SNAP_BUILD + +static void remmina_main_show_snap_welcome() +{ + GtkBuilder *dlgbuilder = NULL; + GtkWidget *dlg; + GtkWindow *parent; + int result; + static gboolean shown_once = FALSE; + gboolean need_snap_interface_connections = FALSE; + GtkWidget* dsa; + RemminaSecretPlugin *remmina_secret_plugin; + + if (shown_once) + return; + else + shown_once = TRUE; + + g_print("Remmina is compiled as a SNAP package.\n"); + remmina_secret_plugin = remmina_plugin_manager_get_secret_plugin(); + if (remmina_secret_plugin == NULL) { + g_print(" but we can't find the secret plugin inside the SNAP.\n"); + need_snap_interface_connections = TRUE; + } else { + if (!remmina_secret_plugin->is_service_available()) { + g_print(" but we can't access a secret service. Secret service or SNAP interface connection is missing.\n"); + need_snap_interface_connections = TRUE; + } + } + + if (need_snap_interface_connections && !remmina_pref.prevent_snap_welcome_message) { + dlgbuilder = remmina_public_gtk_builder_new_from_file("remmina_snap_info_dialog.glade"); + dsa = GTK_WIDGET(gtk_builder_get_object(dlgbuilder, "dontshowagain")); + if(dlgbuilder) { + parent = remmina_main_get_window(); + dlg = GTK_WIDGET(gtk_builder_get_object(dlgbuilder, "snapwarndlg")); + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(dlg), parent); + gtk_builder_connect_signals(dlgbuilder,NULL); + result = gtk_dialog_run(GTK_DIALOG(dlg)); + if (result == 1) { + remmina_pref.prevent_snap_welcome_message = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dsa)); + remmina_pref_save(); + } + gtk_widget_destroy(dlg); + g_object_unref(dlgbuilder); + } + } + +} +#endif + + +static gboolean remmina_main_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, + gboolean path_currently_selected, gpointer user_data) +{ + TRACE_CALL(__func__); + guint context_id; + GtkTreeIter iter; + gchar buf[1000]; + + if (path_currently_selected) + return TRUE; + + if (!gtk_tree_model_get_iter(model, &iter, path)) + return TRUE; + + remmina_main_clear_selection_data(); + + gtk_tree_model_get(model, &iter, NAME_COLUMN, &remminamain->priv->selected_name, FILENAME_COLUMN, + &remminamain->priv->selected_filename, -1); + + context_id = gtk_statusbar_get_context_id(remminamain->statusbar_main, "status"); + gtk_statusbar_pop(remminamain->statusbar_main, context_id); + if (remminamain->priv->selected_filename) { + g_snprintf(buf, sizeof(buf), "%s (%s)", remminamain->priv->selected_name, remminamain->priv->selected_filename); + gtk_statusbar_push(remminamain->statusbar_main, context_id, buf); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + gtk_action_group_set_sensitive(remminamain->actiongroup_connection, TRUE); + G_GNUC_END_IGNORE_DEPRECATIONS + }else { + gtk_statusbar_push(remminamain->statusbar_main, context_id, remminamain->priv->selected_name); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + gtk_action_group_set_sensitive(remminamain->actiongroup_connection, FALSE); + G_GNUC_END_IGNORE_DEPRECATIONS + } + return TRUE; +} + +static void remmina_main_load_file_list_callback(RemminaFile *remminafile, gpointer user_data) +{ + TRACE_CALL(__func__); + GtkTreeIter iter; + GtkListStore *store; + store = GTK_LIST_STORE(user_data); + gchar* datetime; + + datetime = remmina_file_get_datetime(remminafile); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + PROTOCOL_COLUMN, remmina_file_get_icon_name(remminafile), + NAME_COLUMN, remmina_file_get_string(remminafile, "name"), + GROUP_COLUMN, remmina_file_get_string(remminafile, "group"), + SERVER_COLUMN, remmina_file_get_string(remminafile, "server"), + DATE_COLUMN, datetime, + FILENAME_COLUMN, remmina_file_get_filename(remminafile), + -1); + g_free(datetime); +} + +static gboolean remmina_main_load_file_tree_traverse(GNode *node, GtkTreeStore *store, GtkTreeIter *parent) +{ + TRACE_CALL(__func__); + GtkTreeIter *iter; + RemminaGroupData *data; + GNode *child; + + iter = NULL; + if (node->data) { + data = (RemminaGroupData*)node->data; + iter = g_new0(GtkTreeIter, 1); + gtk_tree_store_append(store, iter, parent); + gtk_tree_store_set(store, iter, + PROTOCOL_COLUMN, "folder", + NAME_COLUMN, data->name, + GROUP_COLUMN, data->group, + DATE_COLUMN, data->datetime, + FILENAME_COLUMN, NULL, + -1); + } + for (child = g_node_first_child(node); child; child = g_node_next_sibling(child)) { + remmina_main_load_file_tree_traverse(child, store, iter); + } + g_free(iter); + return FALSE; +} + +static void remmina_main_load_file_tree_group(GtkTreeStore *store) +{ + TRACE_CALL(__func__); + GNode *root; + + root = remmina_file_manager_get_group_tree(); + remmina_main_load_file_tree_traverse(root, store, NULL); + remmina_file_manager_free_group_tree(root); +} + +static void remmina_main_expand_group_traverse(GtkTreeIter *iter) +{ + TRACE_CALL(__func__); + GtkTreeModel *tree; + gboolean ret; + gchar *group, *filename; + GtkTreeIter child; + GtkTreePath *path; + + tree = remminamain->priv->file_model_sort; + ret = TRUE; + while (ret) { + gtk_tree_model_get(tree, iter, GROUP_COLUMN, &group, FILENAME_COLUMN, &filename, -1); + if (filename == NULL) { + if (remmina_string_array_find(remminamain->priv->expanded_group, group) >= 0) { + path = gtk_tree_model_get_path(tree, iter); + gtk_tree_view_expand_row(remminamain->tree_files_list, path, FALSE); + gtk_tree_path_free(path); + } + if (gtk_tree_model_iter_children(tree, &child, iter)) { + remmina_main_expand_group_traverse(&child); + } + } + g_free(group); + g_free(filename); + + ret = gtk_tree_model_iter_next(tree, iter); + } +} + +static void remmina_main_expand_group(void) +{ + TRACE_CALL(__func__); + GtkTreeIter iter; + + if (gtk_tree_model_get_iter_first(remminamain->priv->file_model_sort, &iter)) { + remmina_main_expand_group_traverse(&iter); + } +} + +static gboolean remmina_main_load_file_tree_find(GtkTreeModel *tree, GtkTreeIter *iter, const gchar *match_group) +{ + TRACE_CALL(__func__); + gboolean ret, match; + gchar *group, *filename; + GtkTreeIter child; + + match = FALSE; + ret = TRUE; + while (ret) { + gtk_tree_model_get(tree, iter, GROUP_COLUMN, &group, FILENAME_COLUMN, &filename, -1); + match = (filename == NULL && g_strcmp0(group, match_group) == 0); + g_free(group); + g_free(filename); + if (match) + break; + if (gtk_tree_model_iter_children(tree, &child, iter)) { + match = remmina_main_load_file_tree_find(tree, &child, match_group); + if (match) { + memcpy(iter, &child, sizeof(GtkTreeIter)); + break; + } + } + ret = gtk_tree_model_iter_next(tree, iter); + } + return match; +} + +static void remmina_main_load_file_tree_callback(RemminaFile *remminafile, gpointer user_data) +{ + TRACE_CALL(__func__); + GtkTreeIter iter, child; + GtkTreeStore *store; + gboolean found; + gchar* datetime; + + store = GTK_TREE_STORE(user_data); + + found = FALSE; + if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) { + found = remmina_main_load_file_tree_find(GTK_TREE_MODEL(store), &iter, + remmina_file_get_string(remminafile, "group")); + } + + datetime = remmina_file_get_datetime(remminafile); + gtk_tree_store_append(store, &child, (found ? &iter : NULL)); + gtk_tree_store_set(store, &child, + PROTOCOL_COLUMN, remmina_file_get_icon_name(remminafile), + NAME_COLUMN, remmina_file_get_string(remminafile, "name"), + GROUP_COLUMN, remmina_file_get_string(remminafile, "group"), + SERVER_COLUMN, remmina_file_get_string(remminafile, "server"), + DATE_COLUMN, datetime, + FILENAME_COLUMN, remmina_file_get_filename(remminafile), + -1); + g_free(datetime); +} + +static void remmina_main_file_model_on_sort(GtkTreeSortable *sortable, gpointer user_data) +{ + TRACE_CALL(__func__); + gint columnid; + GtkSortType order; + + gtk_tree_sortable_get_sort_column_id(sortable, &columnid, &order); + remmina_pref.main_sort_column_id = columnid; + remmina_pref.main_sort_order = order; + remmina_pref_save(); +} + +static gboolean remmina_main_filter_visible_func(GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) +{ + TRACE_CALL(__func__); + gchar *text; + gchar *protocol, *name, *group, *server, *date, *s; + gboolean result = TRUE; + + text = g_ascii_strdown(gtk_entry_get_text(remminamain->entry_quick_connect_server), -1); + if (text && text[0]) { + gtk_tree_model_get(model, iter, + PROTOCOL_COLUMN, &protocol, + NAME_COLUMN, &name, + GROUP_COLUMN, &group, + SERVER_COLUMN, &server, + DATE_COLUMN, &date, + -1); + if (g_strcmp0(protocol, "folder") != 0) { + s = g_ascii_strdown(name ? name : "", -1); + g_free(name); + name = s; + s = g_ascii_strdown(group ? group : "", -1); + g_free(group); + group = s; + s = g_ascii_strdown(server ? server : "", -1); + g_free(server); + server = s; + s = g_ascii_strdown(date ? date : "", -1); + g_free(date); + date = s; + result = (strstr(name, text) || strstr(server, text) || strstr(group, text) || strstr(date, text)); + } + g_free(protocol); + g_free(name); + g_free(group); + g_free(server); + g_free(date); + } + g_free(text); + return result; +} + +static void remmina_main_select_file(const gchar *filename) +{ + TRACE_CALL(__func__); + GtkTreeIter iter; + GtkTreePath *path; + gchar *item_filename; + gboolean cmp; + + if (!gtk_tree_model_get_iter_first(remminamain->priv->file_model_sort, &iter)) + return; + + while (TRUE) { + gtk_tree_model_get(remminamain->priv->file_model_sort, &iter, FILENAME_COLUMN, &item_filename, -1); + cmp = g_strcmp0(item_filename, filename); + g_free(item_filename); + if (cmp == 0) { + gtk_tree_selection_select_iter(gtk_tree_view_get_selection(remminamain->tree_files_list), + &iter); + path = gtk_tree_model_get_path(remminamain->priv->file_model_sort, &iter); + gtk_tree_view_scroll_to_cell(remminamain->tree_files_list, path, NULL, TRUE, 0.5, 0.0); + gtk_tree_path_free(path); + return; + } + if (!gtk_tree_model_iter_next(remminamain->priv->file_model_sort, &iter)) + return; + } +} + +static void remmina_main_load_files() +{ + TRACE_CALL(__func__); + gint items_count; + gchar buf[200]; + guint context_id; + gint view_file_mode; + char *save_selected_filename; + GtkTreeModel *newmodel; + + save_selected_filename = g_strdup(remminamain->priv->selected_filename); + remmina_main_save_expanded_group(); + + view_file_mode = remmina_pref.view_file_mode; + if (remminamain->priv->override_view_file_mode_to_list) + view_file_mode = REMMINA_VIEW_FILE_LIST; + + switch (remmina_pref.view_file_mode) { + case REMMINA_VIEW_FILE_TREE: + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(remminamain->menuitem_view_mode_tree), TRUE); + break; + case REMMINA_VIEW_FILE_LIST: + default: + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(remminamain->menuitem_view_mode_list), TRUE); + break; + } + + switch (view_file_mode) { + case REMMINA_VIEW_FILE_TREE: + /* Create new GtkTreeStore model */ + newmodel = GTK_TREE_MODEL(gtk_tree_store_new(6, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING)); + /* Hide the Group column in the tree view mode */ + gtk_tree_view_column_set_visible(remminamain->column_files_list_group, FALSE); + /* Load groups first */ + remmina_main_load_file_tree_group(GTK_TREE_STORE(newmodel)); + /* Load files list */ + items_count = remmina_file_manager_iterate((GFunc)remmina_main_load_file_tree_callback, (gpointer)newmodel); + break; + + case REMMINA_VIEW_FILE_LIST: + default: + /* Create new GtkListStore model */ + newmodel = GTK_TREE_MODEL(gtk_list_store_new(6, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING)); + /* Show the Group column in the list view mode */ + gtk_tree_view_column_set_visible(remminamain->column_files_list_group, TRUE); + /* Load files list */ + items_count = remmina_file_manager_iterate((GFunc)remmina_main_load_file_list_callback, (gpointer)newmodel); + break; + } + + /* Unset old model */ + gtk_tree_view_set_model(remminamain->tree_files_list, NULL); + + /* Destroy the old model and save the new one */ + remminamain->priv->file_model = newmodel; + + /* Create a sorted filtered model based on newmodel and apply it to the TreeView */ + remminamain->priv->file_model_filter = gtk_tree_model_filter_new(remminamain->priv->file_model, NULL); + gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(remminamain->priv->file_model_filter), + (GtkTreeModelFilterVisibleFunc)remmina_main_filter_visible_func, NULL, NULL); + remminamain->priv->file_model_sort = gtk_tree_model_sort_new_with_model(remminamain->priv->file_model_filter); + gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(remminamain->priv->file_model_sort), + remmina_pref.main_sort_column_id, + remmina_pref.main_sort_order); + gtk_tree_view_set_model(remminamain->tree_files_list, remminamain->priv->file_model_sort); + g_signal_connect(G_OBJECT(remminamain->priv->file_model_sort), "sort-column-changed", + G_CALLBACK(remmina_main_file_model_on_sort), NULL); + remmina_main_expand_group(); + /* Select the file previously selected */ + if (save_selected_filename) { + remmina_main_select_file(save_selected_filename); + g_free(save_selected_filename); + } + /* Show in the status bar the total number of connections found */ + g_snprintf(buf, sizeof(buf), ngettext("Total %i item.", "Total %i items.", items_count), items_count); + context_id = gtk_statusbar_get_context_id(remminamain->statusbar_main, "status"); + gtk_statusbar_pop(remminamain->statusbar_main, context_id); + gtk_statusbar_push(remminamain->statusbar_main, context_id, buf); +} + +void remmina_main_load_files_cb() +{ + TRACE_CALL(__func__); + remmina_main_load_files(); +} + +void remmina_main_on_action_connection_connect(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + + RemminaFile *remminafile; + + if (!remminamain->priv->selected_filename) + return; + + remminafile = remmina_file_load(remminamain->priv->selected_filename); + + if (remminafile == NULL) + return; + + remmina_file_touch(remminafile); + remmina_connection_window_open_from_filename(remminamain->priv->selected_filename); + + remmina_file_free(remminafile); +} + +void remmina_main_on_action_connection_external_tools(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + if (!remminamain->priv->selected_filename) + return; + + remmina_external_tools_from_filename(remminamain, remminamain->priv->selected_filename); +} + +static void remmina_main_file_editor_destroy(GtkWidget *widget, gpointer user_data) +{ + TRACE_CALL(__func__); + remmina_main_load_files(); +} + +void remmina_main_on_action_application_mpchange(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + RemminaFile *remminafile; + + const gchar *username; + const gchar *domain; + const gchar *group; + + username = domain = group = ""; + + remminafile = NULL; + if (remminamain->priv->selected_filename) { + remminafile = remmina_file_load(remminamain->priv->selected_filename); + if (remminafile != NULL) { + username = remmina_file_get_string(remminafile, "username"); + domain = remmina_file_get_string(remminafile, "domain"); + group = remmina_file_get_string(remminafile, "group"); + } + } + + remmina_mpchange_schedule(TRUE, group, domain, username, ""); + + if (remminafile != NULL) + remmina_file_free(remminafile); + +} + +void remmina_main_on_action_connections_new(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + GtkWidget *widget; + + widget = remmina_file_editor_new(); + g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(remmina_main_file_editor_destroy), remminamain); + gtk_window_set_transient_for(GTK_WINDOW(widget), remminamain->window); + gtk_widget_show(widget); + remmina_main_load_files(); +} + +void remmina_main_on_action_connection_copy(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + GtkWidget *widget; + + if (!remminamain->priv->selected_filename) + return; + + widget = remmina_file_editor_new_copy(remminamain->priv->selected_filename); + if (widget) { + g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(remmina_main_file_editor_destroy), remminamain); + gtk_window_set_transient_for(GTK_WINDOW(widget), remminamain->window); + gtk_widget_show(widget); + } + /* Select the file previously selected */ + if (remminamain->priv->selected_filename) { + remmina_main_select_file(remminamain->priv->selected_filename); + } +} + +void remmina_main_on_action_connection_edit(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + GtkWidget *widget; + + if (!remminamain->priv->selected_filename) + return; + + widget = remmina_file_editor_new_from_filename(remminamain->priv->selected_filename); + if (widget) { + gtk_window_set_transient_for(GTK_WINDOW(widget), remminamain->window); + gtk_widget_show(widget); + } + /* Select the file previously selected */ + if (remminamain->priv->selected_filename) { + remmina_main_select_file(remminamain->priv->selected_filename); + } +} + +void remmina_main_on_action_connection_delete(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + GtkWidget *dialog; + gchar *delfilename; + + if (!remminamain->priv->selected_filename) + return; + + dialog = gtk_message_dialog_new(remminamain->window, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, + _("Are you sure to delete '%s'"), remminamain->priv->selected_name); + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES) { + delfilename = g_strdup(remminamain->priv->selected_filename); + remmina_file_delete(delfilename); + g_free(delfilename); + remmina_icon_populate_menu(); + remmina_main_load_files(); + } + gtk_widget_destroy(dialog); + remmina_main_clear_selection_data(); +} + +void remmina_main_on_action_application_preferences(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + GtkDialog *dialog = remmina_pref_dialog_new(0, remminamain->window); + gtk_dialog_run(dialog); + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + +void remmina_main_on_action_application_quit(GtkAction *action, gpointer user_data) +{ + // Called by quit signal in remmina_main.glade + TRACE_CALL(__func__); + remmina_application_condexit(REMMINA_CONDEXIT_ONQUIT); +} + +void remmina_main_on_action_view_statusbar(GtkToggleAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + gboolean toggled; + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + toggled = gtk_toggle_action_get_active(action); + G_GNUC_END_IGNORE_DEPRECATIONS + if (toggled) { + gtk_widget_show(GTK_WIDGET(remminamain->statusbar_main)); + }else { + gtk_widget_hide(GTK_WIDGET(remminamain->statusbar_main)); + } + if (remminamain->priv->initialized) { + remmina_pref.hide_statusbar = !toggled; + remmina_pref_save(); + } +} + +void remmina_main_on_action_view_file_mode(GtkRadioAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + gint v; + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + v = gtk_radio_action_get_current_value(action); + G_GNUC_END_IGNORE_DEPRECATIONS + + if (v == REMMINA_VIEW_FILE_TREE) { + gtk_entry_set_text(remminamain->entry_quick_connect_server, ""); + } + + if (remmina_pref.view_file_mode != v) { + remmina_pref.view_file_mode = v; + gtk_entry_set_text(remminamain->entry_quick_connect_server, ""); + remmina_pref_save(); + remmina_main_load_files(); + } + +} + +void remmina_main_on_date_column_sort_clicked() +{ + if (remmina_pref.view_file_mode != REMMINA_VIEW_FILE_LIST) { + remmina_pref.view_file_mode = REMMINA_VIEW_FILE_LIST; + gtk_entry_set_text(remminamain->entry_quick_connect_server, ""); + remmina_pref_save(); + remmina_main_load_files(); + } +} + +static void remmina_main_import_file_list(GSList *files) +{ + TRACE_CALL(__func__); + GtkWidget *dlg; + GSList *element; + gchar *path; + RemminaFilePlugin *plugin; + GString *err; + RemminaFile *remminafile = NULL; + gboolean imported; + + err = g_string_new(NULL); + imported = FALSE; + for (element = files; element; element = element->next) { + path = (gchar*)element->data; + plugin = remmina_plugin_manager_get_import_file_handler(path); + if (plugin && (remminafile = plugin->import_func(path)) != NULL && remmina_file_get_string(remminafile, "name")) { + remmina_file_generate_filename(remminafile); + remmina_file_save(remminafile); + imported = TRUE; + }else { + g_string_append(err, path); + g_string_append_c(err, '\n'); + } + if (remminafile) { + remmina_file_free(remminafile); + remminafile = NULL; + } + g_free(path); + } + g_slist_free(files); + if (err->len > 0) { + dlg = gtk_message_dialog_new(remminamain->window, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + _("Unable to import:\n%s"), err->str); + g_signal_connect(G_OBJECT(dlg), "response", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_widget_show(dlg); + } + g_string_free(err, TRUE); + if (imported) { + remmina_main_load_files(); + } +} + +static void remmina_main_action_tools_import_on_response(GtkDialog *dialog, gint response_id, gpointer user_data) +{ + TRACE_CALL(__func__); + GSList *files; + + if (response_id == GTK_RESPONSE_ACCEPT) { + files = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); + remmina_main_import_file_list(files); + } + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + +void remmina_main_on_action_tools_import(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + GtkWidget *dialog; + + 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); +} + +void remmina_main_on_action_tools_export(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + RemminaFilePlugin *plugin; + RemminaFile *remminafile; + GtkWidget *dialog; + + if (!remminamain->priv->selected_filename) + return; + + remminafile = remmina_file_load(remminamain->priv->selected_filename); + if (remminafile == NULL) + 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(remminafile, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog))); + } + gtk_widget_destroy(dialog); + }else { + 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); + } + remmina_file_free(remminafile); +} + +void remmina_main_on_action_application_plugins(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + remmina_plugin_manager_show(remminamain->window); +} + +void remmina_main_on_action_help_homepage(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + g_app_info_launch_default_for_uri("http://www.remmina.org", NULL, NULL); +} + +void remmina_main_on_action_help_wiki(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + g_app_info_launch_default_for_uri("https://github.com/FreeRDP/Remmina/wiki", NULL, NULL); +} + +void remmina_main_on_action_help_gplus(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + g_app_info_launch_default_for_uri("https://plus.google.com/communities/106276095923371962010", NULL, NULL); +} + +void remmina_main_on_action_help_donations(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + g_app_info_launch_default_for_uri("http://www.remmina.org/wp/donations", NULL, NULL); +} + +void remmina_main_on_action_help_debug(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + remmina_log_start(); +} + +void remmina_main_on_action_application_about(GtkAction *action, gpointer user_data) +{ + TRACE_CALL(__func__); + remmina_about_open(remminamain->window); +}; + +static gboolean remmina_main_quickconnect(void) +{ + TRACE_CALL(__func__); + RemminaFile* remminafile; + gchar* server; + + remminafile = remmina_file_new(); + server = strdup(gtk_entry_get_text(remminamain->entry_quick_connect_server)); + + remmina_file_set_string(remminafile, "sound", "off"); + remmina_file_set_string(remminafile, "server", server); + remmina_file_set_string(remminafile, "name", server); + remmina_file_set_string(remminafile, "protocol", + gtk_combo_box_text_get_active_text(remminamain->combo_quick_connect_protocol)); + g_free(server); + + remmina_connection_window_open_from_file(remminafile); + + return FALSE; +} + +gboolean remmina_main_quickconnect_on_click(GtkWidget *widget, gpointer user_data) +{ + TRACE_CALL(__func__); + return remmina_main_quickconnect(); +} + +/* Select all the text inside the quick search box if there is anything */ +void remmina_main_quick_search_enter(GtkWidget *widget, gpointer user_data) +{ + if (gtk_entry_get_text(remminamain->entry_quick_connect_server)) + gtk_editable_select_region(GTK_EDITABLE(remminamain->entry_quick_connect_server), 0, -1); +} + +/* Handle double click on a row in the connections list */ +void remmina_main_file_list_on_row_activated(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data) +{ + TRACE_CALL(__func__); + /* If a connection was selected then execute the default action */ + if (remminamain->priv->selected_filename) { + switch (remmina_pref.default_action) { + case REMMINA_ACTION_EDIT: + remmina_main_on_action_connection_edit(NULL, NULL); + break; + case REMMINA_ACTION_CONNECT: + default: + remmina_main_on_action_connection_connect(NULL, NULL); + break; + } + } +} + +/* Show the popup menu by the right button mouse click */ +gboolean remmina_main_file_list_on_button_press(GtkWidget *widget, GdkEventButton *event, gpointer user_data) +{ + TRACE_CALL(__func__); + if (event->button == MOUSE_BUTTON_RIGHT) { +#if GTK_CHECK_VERSION(3, 22, 0) + gtk_menu_popup_at_pointer(GTK_MENU(remminamain->menu_popup), (GdkEvent*)event); +#else + gtk_menu_popup(remminamain->menu_popup, NULL, NULL, NULL, NULL, event->button, event->time); +#endif + + + } + return FALSE; +} + +/* Show the popup menu by the menu key */ +gboolean remmina_main_file_list_on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) +{ + TRACE_CALL(__func__); + if (event->keyval == GDK_KEY_Menu) { +#if GTK_CHECK_VERSION(3, 22, 0) + gtk_menu_popup_at_widget(GTK_MENU(remminamain->menu_popup), widget, + GDK_GRAVITY_CENTER, GDK_GRAVITY_CENTER, + (GdkEvent*)event); +#else + gtk_menu_popup(remminamain->menu_popup, NULL, NULL, NULL, NULL, 0, event->time); +#endif + } + return FALSE; +} + +void remmina_main_quick_search_on_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event, gpointer user_data) +{ + TRACE_CALL(__func__); + if (icon_pos == GTK_ENTRY_ICON_SECONDARY) { + gtk_entry_set_text(entry, ""); + } +} + +void remmina_main_quick_search_on_changed(GtkEditable *editable, gpointer user_data) +{ + TRACE_CALL(__func__); + /* If a search text was input then temporary set the file mode to list */ + if (gtk_entry_get_text_length(remminamain->entry_quick_connect_server)) { + if (GTK_IS_TREE_STORE(remminamain->priv->file_model)) { + /* File view mode changed, put it to override and reload list */ + remminamain->priv->override_view_file_mode_to_list = TRUE; + remmina_main_load_files(); + } + } else { + if (remminamain->priv->override_view_file_mode_to_list) { + /* File view mode changed, put it to default (disable override) and reload list */ + remminamain->priv->override_view_file_mode_to_list = FALSE; + remmina_main_load_files(); + } + } + gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(remminamain->priv->file_model_filter)); +} + +void remmina_main_on_drag_data_received(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, + GtkSelectionData *data, guint info, guint time, gpointer user_data) +{ + TRACE_CALL(__func__); + gchar **uris; + GSList *files = NULL; + gint i; + + uris = g_uri_list_extract_uris((const gchar*)gtk_selection_data_get_data(data)); + for (i = 0; uris[i]; i++) { + if (strncmp(uris[i], "file://", 7) != 0) + continue; + files = g_slist_append(files, g_strdup(uris[i] + 7)); + } + g_strfreev(uris); + remmina_main_import_file_list(files); +} + +/* Add a new menuitem to the Tools menu */ +static gboolean remmina_main_add_tool_plugin(gchar *name, RemminaPlugin *plugin, gpointer user_data) +{ + TRACE_CALL(__func__); + RemminaToolPlugin *tool_plugin = (RemminaToolPlugin*)plugin; + GtkWidget *menuitem = gtk_menu_item_new_with_label(plugin->description); + + gtk_widget_show(menuitem); + gtk_menu_shell_append(GTK_MENU_SHELL(remminamain->menu_popup_full), menuitem); + g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(tool_plugin->exec_func), NULL); + return FALSE; +} + +gboolean remmina_main_on_window_state_event(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data) +{ + TRACE_CALL(__func__); + return FALSE; +} + +/* Remmina main window initialization */ +static void remmina_main_init(void) +{ + TRACE_CALL(__func__); + int i; + char *name; + + remminamain->priv->expanded_group = remmina_string_array_new_from_string(remmina_pref.expanded_group); + gtk_window_set_title(remminamain->window, _("Remmina Remote Desktop Client")); + gtk_window_set_default_size(remminamain->window, remmina_pref.main_width, remmina_pref.main_height); + if (remmina_pref.main_maximize) { + gtk_window_maximize(remminamain->window); + } + + /* Add a GtkMenuItem to the Tools menu for each plugin of type REMMINA_PLUGIN_TYPE_TOOL */ + remmina_plugin_manager_for_each_plugin(REMMINA_PLUGIN_TYPE_TOOL, remmina_main_add_tool_plugin, remminamain); + + /* Add available quick connect protocols to remminamain->combo_quick_connect_protocol */ + for (i = 0; i < sizeof(quick_connect_plugin_list) / sizeof(quick_connect_plugin_list[0]); i++) { + name = quick_connect_plugin_list[i]; + if (remmina_plugin_manager_get_plugin(REMMINA_PLUGIN_TYPE_PROTOCOL, name)) + gtk_combo_box_text_append(remminamain->combo_quick_connect_protocol, name, name); + } + gtk_combo_box_set_active(GTK_COMBO_BOX(remminamain->combo_quick_connect_protocol), 0); + + /* Connect the group accelerators to the GtkWindow */ + gtk_window_add_accel_group(remminamain->window, remminamain->accelgroup_shortcuts); + /* Set the Quick Connection */ + gtk_entry_set_activates_default(remminamain->entry_quick_connect_server, TRUE); + /* Set the TreeView for the files list */ + gtk_tree_selection_set_select_function( + gtk_tree_view_get_selection(remminamain->tree_files_list), + remmina_main_selection_func, NULL, NULL); + /** @todo Set entry_quick_connect_server as default search entry. Weirdly. This does not work yet. */ + gtk_tree_view_set_search_entry(remminamain->tree_files_list, GTK_ENTRY(remminamain->entry_quick_connect_server)); + /* Load the files list */ + remmina_main_load_files(); + /* Load the preferences */ + if (remmina_pref.hide_statusbar) { + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + gtk_toggle_action_set_active(remminamain->action_view_statusbar, FALSE); + G_GNUC_END_IGNORE_DEPRECATIONS + } + if (remmina_pref.view_file_mode) { + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + gtk_toggle_action_set_active(remminamain->action_view_mode_tree, TRUE); + G_GNUC_END_IGNORE_DEPRECATIONS + } + + /* Drag-n-drop support */ + gtk_drag_dest_set(GTK_WIDGET(remminamain->window), GTK_DEST_DEFAULT_ALL, remmina_drop_types, 1, GDK_ACTION_COPY); + + /* Finish initialization */ + remminamain->priv->initialized = TRUE; + + /* Register the window in remmina_widget_pool with GType=GTK_WINDOW and TAG=remmina-main-window */ + g_object_set_data(G_OBJECT(remminamain->window), "tag", "remmina-main-window"); + remmina_widget_pool_register(GTK_WIDGET(remminamain->window)); +} + +/* Signal handler for "show" on remminamain->window */ +void remmina_main_on_show(GtkWidget *w, gpointer user_data) +{ + TRACE_CALL(__func__); + if (!remmina_pref.periodic_usage_stats_permission_asked) { + gtk_widget_set_visible(GTK_WIDGET(remminamain->box_ustat), TRUE); + } + +#ifdef SNAP_BUILD + remmina_main_show_snap_welcome(); +#endif + +} + +void remmina_main_on_click_ustat_yes(GtkWidget *w, gpointer user_data) +{ + remmina_pref.periodic_usage_stats_permission_asked = TRUE; + remmina_pref.periodic_usage_stats_permitted = TRUE; + remmina_pref_save(); + gtk_widget_set_visible(GTK_WIDGET(remminamain->box_ustat), FALSE); + remmina_stats_sender_schedule(); +} + +void remmina_main_on_click_ustat_no(GtkWidget *w, gpointer user_data) +{ + remmina_pref.periodic_usage_stats_permission_asked = TRUE; + remmina_pref.periodic_usage_stats_permitted = FALSE; + remmina_pref_save(); + gtk_widget_set_visible(GTK_WIDGET(remminamain->box_ustat), FALSE); +} + + +/* RemminaMain instance */ +GtkWidget* remmina_main_new(void) +{ + TRACE_CALL(__func__); + remminamain = g_new0(RemminaMain, 1); + remminamain->priv = g_new0(RemminaMainPriv, 1); + /* Assign UI widgets to the private members */ + remminamain->builder = remmina_public_gtk_builder_new_from_file("remmina_main.glade"); + remminamain->window = GTK_WINDOW(gtk_builder_get_object(remminamain->builder, "RemminaMain")); + /* Menu widgets */ + remminamain->menu_popup = GTK_MENU(GET_OBJECT("menu_popup")); + remminamain->menu_popup_full = GTK_MENU(GET_OBJECT("menu_popup_full")); + /* View mode radios */ + remminamain->menuitem_view_mode_list = GTK_RADIO_MENU_ITEM(GET_OBJECT("menuitem_view_mode_list")); + remminamain->menuitem_view_mode_tree = GTK_RADIO_MENU_ITEM(GET_OBJECT("menuitem_view_mode_tree")); + /* Quick connect objects */ + remminamain->box_quick_connect = GTK_BOX(GET_OBJECT("box_quick_connect")); + remminamain->combo_quick_connect_protocol = GTK_COMBO_BOX_TEXT(GET_OBJECT("combo_quick_connect_protocol")); + remminamain->entry_quick_connect_server = GTK_ENTRY(GET_OBJECT("entry_quick_connect_server")); + /* Other widgets */ + remminamain->tree_files_list = GTK_TREE_VIEW(GET_OBJECT("tree_files_list")); + remminamain->column_files_list_group = GTK_TREE_VIEW_COLUMN(GET_OBJECT("column_files_list_group")); + remminamain->statusbar_main = GTK_STATUSBAR(GET_OBJECT("statusbar_main")); + remminamain->box_ustat = GTK_BOX(GET_OBJECT("box_ustat")); + /* Non widget objects */ + remminamain->accelgroup_shortcuts = GTK_ACCEL_GROUP(GET_OBJECT("accelgroup_shortcuts")); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + remminamain->actiongroup_connection = GTK_ACTION_GROUP(GET_OBJECT("actiongroup_connection")); + /* Actions from the application ActionGroup */ + remminamain->action_application_about = GTK_ACTION(GET_OBJECT("action_application_about")); + remminamain->action_application_plugins = GTK_ACTION(GET_OBJECT("action_application_plugins")); + remminamain->action_application_preferences = GTK_ACTION(GET_OBJECT("action_application_preferences")); + remminamain->action_application_quit = GTK_ACTION(GET_OBJECT("action_application_quit")); + /* Actions from the connections ActionGroup */ + remminamain->action_connections_new = GTK_ACTION(GET_OBJECT("action_connections_new")); + /* Actions from the connection ActionGroup */ + remminamain->action_connection_connect = GTK_ACTION(GET_OBJECT("action_connection_connect")); + remminamain->action_connection_edit = GTK_ACTION(GET_OBJECT("action_connection_edit")); + remminamain->action_connection_copy = GTK_ACTION(GET_OBJECT("action_connection_copy")); + remminamain->action_connection_delete = GTK_ACTION(GET_OBJECT("action_connection_delete")); + remminamain->action_connection_external_tools = GTK_ACTION(GET_OBJECT("action_connection_external_tools")); + /* Actions from the view ActionGroup */ + remminamain->action_view_statusbar = GTK_TOGGLE_ACTION(GET_OBJECT("action_view_statusbar")); + remminamain->action_view_mode_list = GTK_TOGGLE_ACTION(GET_OBJECT("action_view_mode_list")); + remminamain->action_view_mode_tree = GTK_TOGGLE_ACTION(GET_OBJECT("action_view_mode_tree")); + /* Actions from the tools ActionGroup */ + remminamain->action_tools_import = GTK_ACTION(GET_OBJECT("action_tools_import")); + remminamain->action_tools_export = GTK_ACTION(GET_OBJECT("action_tools_export")); + /* Actions from the help ActionGroup */ + remminamain->action_help_homepage = GTK_ACTION(GET_OBJECT("action_help_homepage")); + remminamain->action_help_wiki = GTK_ACTION(GET_OBJECT("action_help_wiki")); + remminamain->action_help_debug = GTK_ACTION(GET_OBJECT("action_help_debug")); + G_GNUC_END_IGNORE_DEPRECATIONS + + /* Connect signals */ + gtk_builder_connect_signals(remminamain->builder, NULL); + /* Initialize the window and load the preferences */ + remmina_main_init(); + return GTK_WIDGET(remminamain->window); +} + +GtkWindow* remmina_main_get_window() +{ + if (!remminamain) + return NULL; + if (!remminamain->priv) + return NULL; + if (!remminamain->priv->initialized) + return NULL; + return remminamain->window; +} + +void remmina_main_update_file_datetime(RemminaFile *file) +{ + if (!remminamain) + return; + remmina_main_load_files(); +} + +void remmina_main_show_warning_dialog(const gchar* message) +{ + GtkWidget* dialog; + + if (remminamain->window) { + dialog = gtk_message_dialog_new(remminamain->window, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, + message, g_get_application_name()); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + } +} |