Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/Remmina/Remmina.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntenore Gatta <antenore@simbiosi.org>2018-05-03 15:38:44 +0300
committerAntenore Gatta <antenore@simbiosi.org>2018-05-03 15:38:44 +0300
commitd77997ca5c06c1dd971cf85383e81bd6584be746 (patch)
tree78a08a34126a30a25655ca748b9e2197e918102b /src/remmina_main.c
parentbcf9990358f0ac9423734421be45c38fdccdf1f0 (diff)
Renamed remmina in src and moved source files
Diffstat (limited to 'src/remmina_main.c')
-rw-r--r--src/remmina_main.c1272
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);
+ }
+}