diff options
author | Antenore Gatta <antenore@simbiosi.org> | 2018-07-15 02:07:16 +0300 |
---|---|---|
committer | Antenore Gatta <antenore@simbiosi.org> | 2018-07-15 02:07:16 +0300 |
commit | 960d9c4912aa8e19af86d439e0a2489be4bf6551 (patch) | |
tree | 5e0baa593aa443adfc2b4ce536fc39060d4c5bbc | |
parent | 5502acc90e372ffef54c52d7cdeff400950357ff (diff) | |
parent | 2f6979263eead2d554ca80d1c589b9cfdad2910d (diff) |
Kiosk mode, initial implementation
This si an initial implementation of the kiosk mode, that can be used, for example, for thin clients.
-rw-r--r-- | data/desktop/CMakeLists.txt | 33 | ||||
-rwxr-xr-x | data/desktop/gnome-session-remmina | 2 | ||||
-rw-r--r-- | data/desktop/org.remmina.Remmina.desktop.in | 9 | ||||
-rwxr-xr-x | data/desktop/remmina-gnome | 12 | ||||
-rw-r--r-- | data/desktop/remmina-gnome-xsession.desktop | 9 | ||||
-rw-r--r-- | data/desktop/remmina-gnome.desktop | 10 | ||||
-rw-r--r-- | data/desktop/remmina-gnome.session | 5 | ||||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/remmina.1 | 3 | ||||
-rw-r--r-- | src/remmina.c | 12 | ||||
-rw-r--r-- | src/remmina.h | 39 | ||||
-rw-r--r-- | src/remmina_connection_window.c | 21 | ||||
-rw-r--r-- | src/remmina_exec.c | 4 | ||||
-rw-r--r-- | src/remmina_main.c | 1539 | ||||
-rw-r--r-- | src/remmina_main.h | 3 |
15 files changed, 943 insertions, 759 deletions
diff --git a/data/desktop/CMakeLists.txt b/data/desktop/CMakeLists.txt index 469177555..b9c577f7a 100644 --- a/data/desktop/CMakeLists.txt +++ b/data/desktop/CMakeLists.txt @@ -96,6 +96,39 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/remmina-file.desktop DESTINATION "${REMMINA_DATADIR}/applications") install(FILES ${REMMINA_APP_ID}.appdata.xml DESTINATION "${REMMINA_DATADIR}/metainfo") +# Kiosk Session Files +install( + FILES remmina-gnome-xsession.desktop + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/xsessions + RENAME remmina-gnome.desktop + PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ + ) +install( + FILES remmina-gnome.desktop + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications + RENAME remmina-gnome.desktop + PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ + ) +install( + FILES remmina-gnome.session + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/gnome-session/sessions + RENAME remmina-gnome.session + PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ + ) +install( + FILES remmina-gnome + DESTINATION ${CMAKE_INSTALL_PREFIX}/bin + RENAME remmina-gnome + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ + WORLD_EXECUTE WORLD_READ + ) +install( + FILES gnome-session-remmina + DESTINATION ${CMAKE_INSTALL_PREFIX}/bin + RENAME gnome-session-remmina + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ + WORLD_EXECUTE WORLD_READ + ) # XML mime types set( SHARED_MIME_INFO_MINIMUM_VERSION "0.30" ) set( XDG_MIME_INSTALL_DIR "${REMMINA_DATADIR}/mime/packages" ) diff --git a/data/desktop/gnome-session-remmina b/data/desktop/gnome-session-remmina new file mode 100755 index 000000000..89bb068f3 --- /dev/null +++ b/data/desktop/gnome-session-remmina @@ -0,0 +1,2 @@ +#! /bin/sh +env GNOME_SHELL_SESSION_MODE=classic gnome-session --session remmina-gnome "$@" diff --git a/data/desktop/org.remmina.Remmina.desktop.in b/data/desktop/org.remmina.Remmina.desktop.in index 10ec94ac8..69b016830 100644 --- a/data/desktop/org.remmina.Remmina.desktop.in +++ b/data/desktop/org.remmina.Remmina.desktop.in @@ -71,7 +71,7 @@ Icon=@REMMINA_ICON@ Terminal=false Type=Application Categories=GTK;GNOME;X-GNOME-NetworkSettings;Network; -Actions=Profile;Tray;Quit; +Actions=Kiosk;Profile;Tray;Quit; Keywords=remote desktop;rdp;vnc;nx;ssh;spice;xdmcp; StartupWMClass=remmina @@ -98,6 +98,13 @@ Name[uk]=Створити новий профіль з’єднання Name[zh_CN]=新建连接配置 Exec=@REMMINA_BINARY_PATH@ --new +[Desktop Action Kiosk] +# Start Remmina with a minimal interface for kiosk/thin client mode +Name=Start Remmina in Kiosk mode +Name[fr]=Démarrer Remmina en mode Kiosque +Name[it]=Avvia Remmina in modo Chiosco +Exec=@REMMINA_BINARY_PATH@ --kiosk + [Desktop Action Tray] Name=Start Remmina Minimized Name[ca]=Inicia el Remmina minimitzat diff --git a/data/desktop/remmina-gnome b/data/desktop/remmina-gnome new file mode 100755 index 000000000..1301c7958 --- /dev/null +++ b/data/desktop/remmina-gnome @@ -0,0 +1,12 @@ +#!/bin/sh + +# Register with gnome-session so that it does not kill the whole session thinking it is dead. +test -n "$DESKTOP_AUTOSTART_ID" && { + dbus-send --print-reply --session --dest=org.gnome.SessionManager "/org/gnome/SessionManager" org.gnome.SessionManager.RegisterClient "string:remmina-gnome" "string:$DESKTOP_AUTOSTART_ID" +} + +remmina --kiosk + +test -n "$DESKTOP_AUTOSTART_ID" && { +dbus-send --print-reply --session --dest=org.gnome.SessionManager "/org/gnome/SessionManager" org.gnome.SessionManager.Logout "uint32:1" +} diff --git a/data/desktop/remmina-gnome-xsession.desktop b/data/desktop/remmina-gnome-xsession.desktop new file mode 100644 index 000000000..c967402ac --- /dev/null +++ b/data/desktop/remmina-gnome-xsession.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=GNOME + Remmina Kiosk +Comment=This session logs you into GNOME with remmina as the window manager +Exec=gnome-session-remmina +TryExec=remmina-gnome +Icon= +Type=Application +DesktopNames=GNOME +X-Ubuntu-Gettext-Domain=gnome-session-3.0 diff --git a/data/desktop/remmina-gnome.desktop b/data/desktop/remmina-gnome.desktop new file mode 100644 index 000000000..887e8db5a --- /dev/null +++ b/data/desktop/remmina-gnome.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Type=Application +Name=remmina-gnome +NoDisplay=true +Comment=Remina Kiosk +Exec=remmina-gnome +X-GNOME-WMName=remmina-gnome +X-GNOME-Autostart-Phase=WindowManager +X-GNOME-Provides=windowmanager +X-GNOME-Autostart-Notify=false diff --git a/data/desktop/remmina-gnome.session b/data/desktop/remmina-gnome.session new file mode 100644 index 000000000..5bb868e0f --- /dev/null +++ b/data/desktop/remmina-gnome.session @@ -0,0 +1,5 @@ +# -*- mode: conf -*- + +[GNOME Session] +Name=remmina-gnome +RequiredComponents=org.gnome.SettingsDaemon.A11ySettings;org.gnome.SettingsDaemon.Clipboard;org.gnome.SettingsDaemon.Color;org.gnome.SettingsDaemon.Datetime;org.gnome.SettingsDaemon.Housekeeping;org.gnome.SettingsDaemon.Keyboard;org.gnome.SettingsDaemon.MediaKeys;org.gnome.SettingsDaemon.Mouse;org.gnome.SettingsDaemon.Power;org.gnome.SettingsDaemon.PrintNotifications;org.gnome.SettingsDaemon.Rfkill;org.gnome.SettingsDaemon.ScreensaverProxy;org.gnome.SettingsDaemon.Sharing;org.gnome.SettingsDaemon.Smartcard;org.gnome.SettingsDaemon.Sound;org.gnome.SettingsDaemon.Wacom;org.gnome.SettingsDaemon.XSettings;remmina-gnome diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index baf631645..a49afe461 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,6 +45,7 @@ list(APPEND REMMINA_SRCS "remmina_avahi.c" "remmina_avahi.h" "remmina.c" + "remmina.h" "remmina_chat_window.c" "remmina_chat_window.h" "remmina_crypt.c" diff --git a/src/remmina.1 b/src/remmina.1 index 803a9e34a..8e5f9d205 100644 --- a/src/remmina.1 +++ b/src/remmina.1 @@ -53,6 +53,9 @@ Connect to a .remmina file .It Fl e, -edit\fR=\fIFILE\fR Edit a .remmina file .Tp +.It Fl k, -kiosk\fR +Start Remmina in kiosk mode (thin client) +.Tp .It Fl n, -new\fR Create a new connection profile .Tp diff --git a/src/remmina.c b/src/remmina.c index d32f15429..61610058c 100644 --- a/src/remmina.c +++ b/src/remmina.c @@ -41,6 +41,7 @@ #include <stdlib.h> #include "config.h" +#include "remmina.h" #include "remmina_exec.h" #include "remmina_file_manager.h" #include "remmina_icon.h" @@ -73,6 +74,8 @@ static int gcrypt_thread_initialized = 0; #endif /* !GCRYPT_VERSION_NUMBER */ #endif /* HAVE_LIBGCRYPT */ +gboolean kioskmode; + static GOptionEntry remmina_options[] = { { "about", 'a', 0, G_OPTION_ARG_NONE, NULL, N_("Show about dialog"), NULL }, @@ -80,6 +83,7 @@ static GOptionEntry remmina_options[] = { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, NULL, N_("Connect to a .remmina file"), "FILE" }, { "edit", 'e', 0, G_OPTION_ARG_FILENAME, NULL, N_("Edit a .remmina file"), "FILE" }, { "help", '?', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, NULL, NULL, NULL }, + { "kiosk", 'k', 0, G_OPTION_ARG_NONE, NULL, N_("Start Remmina in Kiosk mode"), NULL }, { "new", 'n', 0, G_OPTION_ARG_NONE, NULL, N_("Create a new connection profile"), NULL }, { "pref", 'p', 0, G_OPTION_ARG_STRING, NULL, N_("Show preferences dialog page"), "PAGENR" }, { "plugin", 'x', 0, G_OPTION_ARG_STRING, NULL, N_("Execute the plugin"), "PLUGIN" }, @@ -131,7 +135,7 @@ static gint remmina_on_command_line(GApplication *app, GApplicationCommandLine * /** @todo This should be a G_OPTION_ARG_FILENAME_ARRAY (^aay) so that * we can implement multi profile connection: - * https://github.com/FreeRDP/Remmina/issues/915 + * https://gitlab.com/Remmina/Remmina/issues/915 */ if (g_variant_dict_lookup(opts, "connect", "^ay", &str)) { remmina_exec_command(REMMINA_COMMAND_CONNECT, g_strdup(str)); @@ -151,6 +155,12 @@ static gint remmina_on_command_line(GApplication *app, GApplicationCommandLine * executed = TRUE; } + if (g_variant_dict_lookup_value(opts, "kiosk", NULL)) { + kioskmode = TRUE; + remmina_exec_command(REMMINA_COMMAND_MAIN, NULL); + executed = TRUE; + } + if (g_variant_dict_lookup_value(opts, "new", NULL)) { if (!g_variant_dict_lookup(opts, "protocol", "&s", &protocol)) protocol = NULL; diff --git a/src/remmina.h b/src/remmina.h new file mode 100644 index 000000000..9cd985182 --- /dev/null +++ b/src/remmina.h @@ -0,0 +1,39 @@ +/* + * Remmina - The GTK+ Remote Desktop Client + * Copyright (C) 2014-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. + * + */ + +#pragma once + +G_BEGIN_DECLS +extern gboolean kioskmode; +G_END_DECLS diff --git a/src/remmina_connection_window.c b/src/remmina_connection_window.c index 36b373fc1..4bfb83b82 100644 --- a/src/remmina_connection_window.c +++ b/src/remmina_connection_window.c @@ -43,6 +43,7 @@ #include <gtk/gtk.h> #include <stdlib.h> +#include "remmina.h" #include "remmina_connection_window.h" #include "remmina_file.h" #include "remmina_file_manager.h" @@ -1887,6 +1888,7 @@ remmina_connection_holder_create_toolbar(RemminaConnectionHolder* cnnhld, gint m gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1); gtk_widget_show(GTK_WIDGET(toolitem)); + /* Fullscreen toggle */ toolitem = gtk_toggle_tool_button_new(); gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem), "remmina-fullscreen-symbolic"); @@ -1895,8 +1897,12 @@ remmina_connection_holder_create_toolbar(RemminaConnectionHolder* cnnhld, gint m gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1); gtk_widget_show(GTK_WIDGET(toolitem)); priv->toolitem_fullscreen = toolitem; - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem), mode != SCROLLED_WINDOW_MODE); - g_signal_connect(G_OBJECT(toolitem), "clicked", G_CALLBACK(remmina_connection_holder_toolbar_fullscreen), cnnhld); + if (kioskmode && kioskmode == TRUE) { + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem), FALSE); + } else { + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem), mode != SCROLLED_WINDOW_MODE); + g_signal_connect(G_OBJECT(toolitem), "clicked", G_CALLBACK(remmina_connection_holder_toolbar_fullscreen), cnnhld); + } /* Fullscreen drop-down options */ toolitem = gtk_tool_item_new(); @@ -1942,6 +1948,9 @@ remmina_connection_holder_create_toolbar(RemminaConnectionHolder* cnnhld, gint m toolitem = gtk_separator_tool_item_new(); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1); gtk_widget_show(GTK_WIDGET(toolitem)); + if (!kioskmode && kioskmode == FALSE) { + gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE); + } /* Dynamic Resolution Update */ toolitem = gtk_toggle_tool_button_new(); @@ -2033,6 +2042,9 @@ remmina_connection_holder_create_toolbar(RemminaConnectionHolder* cnnhld, gint m gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1); gtk_widget_show(GTK_WIDGET(toolitem)); g_signal_connect(G_OBJECT(toolitem), "clicked", G_CALLBACK(remmina_connection_holder_toolbar_minimize), cnnhld); + if (!kioskmode && kioskmode == FALSE) { + gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE); + } toolitem = gtk_tool_button_new(NULL, "_Disconnect"); gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem), "remmina-disconnect-symbolic"); @@ -2584,6 +2596,9 @@ static void remmina_connection_window_init(RemminaConnectionWindow* cnnwin) cnnwin->priv = priv; priv->view_mode = AUTO_MODE; + if (kioskmode && kioskmode == TRUE) + priv->view_mode = VIEWPORT_FULLSCREEN_MODE; + priv->floating_toolbar_opacity = 1.0; priv->kbcaptured = FALSE; priv->mouse_pointer_entered = FALSE; @@ -3616,6 +3631,8 @@ static void remmina_connection_object_on_connect(RemminaProtocolWidget* gp, Remm if (!cnnhld->cnnwin) { i = remmina_file_get_int(cnnobj->remmina_file, "viewmode", 0); + if (kioskmode && kioskmode == TRUE) + i = VIEWPORT_FULLSCREEN_MODE; switch (i) { case SCROLLED_FULLSCREEN_MODE: case VIEWPORT_FULLSCREEN_MODE: diff --git a/src/remmina_exec.c b/src/remmina_exec.c index 59c3be8a2..7195826b4 100644 --- a/src/remmina_exec.c +++ b/src/remmina_exec.c @@ -38,6 +38,7 @@ #include <gtk/gtk.h> #include <glib/gi18n.h> #include <stdlib.h> +#include "remmina.h" #include "remmina_main.h" #include "remmina_widget_pool.h" #include "remmina_pref_dialog.h" @@ -112,6 +113,9 @@ void remmina_application_condexit(RemminaCondExitType why) remmina_exec_exitremmina(); break; case REMMINA_CONDEXIT_ONMAINWINDELETE: + /* If we are in Kiosk mode, we just exit */ + if (kioskmode && kioskmode == TRUE) + remmina_exec_exitremmina(); // Main window has been deleted if (remmina_widget_pool_count() < 1 && !remmina_icon_is_available()) remmina_exec_exitremmina(); diff --git a/src/remmina_main.c b/src/remmina_main.c index a1f0b4e5c..099a32fab 100644 --- a/src/remmina_main.c +++ b/src/remmina_main.c @@ -19,25 +19,27 @@ * 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. -* -*/ + * 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.h" #include "remmina_string_array.h" #include "remmina_public.h" #include "remmina_file.h" @@ -63,1093 +65,1103 @@ 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, -PLUGIN_COLUMN, -DATE_COLUMN, -FILENAME_COLUMN, -N_COLUMNS + PROTOCOL_COLUMN, + NAME_COLUMN, + GROUP_COLUMN, + SERVER_COLUMN, + PLUGIN_COLUMN, + DATE_COLUMN, + FILENAME_COLUMN, + N_COLUMNS }; static GtkTargetEntry remmina_drop_types[] = { -{ "text/uri-list", 0, 1 } + { "text/uri-list", 0, 1 } }; static char *quick_connect_plugin_list[] = { -"RDP", "VNC", "SSH", "NX", "SPICE" + "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; -} + 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; + 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); -} + 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); + 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); } - 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(); + 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; + /* 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(); + 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); + remminamain->window = NULL; + g_idle_add(remmina_main_dexit, NULL); -return FALSE; + return FALSE; } void remmina_main_destroy() { -TRACE_CALL(__func__); + 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; -} + 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 + 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"); + 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(); + 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); } - 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) + gboolean path_currently_selected, gpointer user_data) { -TRACE_CALL(__func__); -guint context_id; -GtkTreeIter iter; -gchar buf[1000]; + TRACE_CALL(__func__); + guint context_id; + GtkTreeIter iter; + gchar buf[1000]; -if (path_currently_selected) - return TRUE; + if (path_currently_selected) + return TRUE; -if (!gtk_tree_model_get_iter(model, &iter, path)) - return TRUE; + if (!gtk_tree_model_get_iter(model, &iter, path)) + return TRUE; -remmina_main_clear_selection_data(); + remmina_main_clear_selection_data(); -gtk_tree_model_get(model, &iter, NAME_COLUMN, &remminamain->priv->selected_name, FILENAME_COLUMN, - &remminamain->priv->selected_filename, -1); + 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; + 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"), - PLUGIN_COLUMN, remmina_file_get_string(remminafile, "protocol"), - DATE_COLUMN, datetime, - FILENAME_COLUMN, remmina_file_get_filename(remminafile), - -1); -g_free(datetime); + 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"), + PLUGIN_COLUMN, remmina_file_get_string(remminafile, "protocol"), + 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, "remmina-folder-symbolic", - 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; + 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, "remmina-folder-symbolic", + 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; + 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); + 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); + 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); + g_free(group); + g_free(filename); - ret = gtk_tree_model_iter_next(tree, iter); -} + ret = gtk_tree_model_iter_next(tree, iter); + } } static void remmina_main_expand_group(void) { -TRACE_CALL(__func__); -GtkTreeIter iter; + TRACE_CALL(__func__); + GtkTreeIter iter; -if (gtk_tree_model_get_iter_first(remminamain->priv->file_model_sort, &iter)) { - remmina_main_expand_group_traverse(&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)); + 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); } - ret = gtk_tree_model_iter_next(tree, iter); -} -return match; + 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; + TRACE_CALL(__func__); + GtkTreeIter iter, child; + GtkTreeStore *store; + gboolean found; + gchar* datetime; -store = GTK_TREE_STORE(user_data); + 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")); -} + 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"), - PLUGIN_COLUMN, remmina_file_get_string(remminafile, "protocol"), - DATE_COLUMN, datetime, - FILENAME_COLUMN, remmina_file_get_filename(remminafile), - -1); -g_free(datetime); + 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"), + PLUGIN_COLUMN, remmina_file_get_string(remminafile, "protocol"), + 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; + 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(); + 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, *plugin, *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, - PLUGIN_COLUMN, &plugin, - DATE_COLUMN, &date, - -1); - if (g_strcmp0(protocol, "remmina-folder-symbolic") != 0) { - s = g_ascii_strdown(name ? name : "", -1); + TRACE_CALL(__func__); + gchar *text; + gchar *protocol, *name, *group, *server, *plugin, *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, + PLUGIN_COLUMN, &plugin, + DATE_COLUMN, &date, + -1); + if (g_strcmp0(protocol, "remmina-folder-symbolic") != 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(plugin ? plugin : "", -1); + g_free(plugin); + plugin = s; + s = g_ascii_strdown(date ? date : "", -1); + g_free(date); + date = s; + result = (strstr(name, text) || strstr(group, text) || strstr(server, text) || strstr(plugin, text) || strstr(date, text)); + } + g_free(protocol); 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(plugin ? plugin : "", -1); g_free(plugin); - plugin = s; - s = g_ascii_strdown(date ? date : "", -1); g_free(date); - date = s; - result = (strstr(name, text) || strstr(group, text) || strstr(server, text) || strstr(plugin, text) || strstr(date, text)); } - g_free(protocol); - g_free(name); - g_free(group); - g_free(server); - g_free(plugin); - g_free(date); -} -g_free(text); -return result; + 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); + 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; } - 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(7, G_TYPE_STRING, 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(7, G_TYPE_STRING, 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; -} + 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(7, G_TYPE_STRING, 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(7, G_TYPE_STRING, 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); + gtk_tree_view_set_model(remminamain->tree_files_list, NULL); /* Destroy the old model and save the new one */ -remminamain->priv->file_model = newmodel; + 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(); + 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); -} + 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); + 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(); + TRACE_CALL(__func__); + remmina_main_load_files(); } void remmina_main_on_action_connection_connect(GtkAction *action, gpointer user_data) { -TRACE_CALL(__func__); + TRACE_CALL(__func__); -RemminaFile *remminafile; + RemminaFile *remminafile; -if (!remminamain->priv->selected_filename) - return; + if (!remminamain->priv->selected_filename) + return; -remminafile = remmina_file_load(remminamain->priv->selected_filename); + remminafile = remmina_file_load(remminamain->priv->selected_filename); -if (remminafile == NULL) - return; + if (remminafile == NULL) + return; -remmina_file_touch(remminafile); -remmina_connection_window_open_from_filename(remminamain->priv->selected_filename); + remmina_file_touch(remminafile); + remmina_connection_window_open_from_filename(remminamain->priv->selected_filename); -remmina_file_free(remminafile); + 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; + TRACE_CALL(__func__); + if (!remminamain->priv->selected_filename) + return; -remmina_external_tools_from_filename(remminamain, remminamain->priv->selected_filename); + 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(); + TRACE_CALL(__func__); + remmina_main_load_files(); } void remmina_main_on_action_application_mpchange(GtkAction *action, gpointer user_data) { -TRACE_CALL(__func__); -RemminaFile *remminafile; + TRACE_CALL(__func__); + RemminaFile *remminafile; -const gchar *username; -const gchar *domain; -const gchar *group; + const gchar *username; + const gchar *domain; + const gchar *group; -username = domain = 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"); + 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, ""); + remmina_mpchange_schedule(TRUE, group, domain, username, ""); -if (remminafile != NULL) - remmina_file_free(remminafile); + if (remminafile != NULL) + remmina_file_free(remminafile); } void remmina_main_on_action_connections_new(GtkAction *action, gpointer user_data) { -TRACE_CALL(__func__); -GtkWidget *widget; + 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(); + 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_search_toggle() { - if (gtk_toggle_button_get_active (remminamain->search_toggle)) { - gtk_search_bar_set_search_mode (remminamain->search_bar, TRUE); +void remmina_main_on_search_toggle() +{ + if (gtk_toggle_button_get_active(remminamain->search_toggle)) { + gtk_search_bar_set_search_mode(remminamain->search_bar, TRUE); } else { - gtk_search_bar_set_search_mode (remminamain->search_bar, FALSE); + gtk_search_bar_set_search_mode(remminamain->search_bar, FALSE); } } void remmina_main_on_action_connection_copy(GtkAction *action, gpointer user_data) { -TRACE_CALL(__func__); -GtkWidget *widget; + TRACE_CALL(__func__); + GtkWidget *widget; -if (!remminamain->priv->selected_filename) - return; + 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); -} + 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); -} + 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; + TRACE_CALL(__func__); + GtkWidget *widget; -if (!remminamain->priv->selected_filename) - return; + 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); -} + 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); -} + 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; + TRACE_CALL(__func__); + GtkWidget *dialog; + gchar *delfilename; -if (!remminamain->priv->selected_filename) - return; + 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(); + 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)); + 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); + // 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; + 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(); -} + 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; + TRACE_CALL(__func__); + gint v; -G_GNUC_BEGIN_IGNORE_DEPRECATIONS - v = gtk_radio_action_get_current_value(action); -G_GNUC_END_IGNORE_DEPRECATIONS + 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 (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(); -} + 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(); -} + 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'); + 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); } - if (remminafile) { - remmina_file_free(remminafile); - remminafile = NULL; + 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(); } - 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; + 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)); + 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; + 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); + 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))); + 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); } - 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); + 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); + 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); + 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); + 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); + 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); + 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(); + 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); + TRACE_CALL(__func__); + remmina_about_open(remminamain->window); }; static gboolean remmina_main_quickconnect(void) { -TRACE_CALL(__func__); -RemminaFile* remminafile; -gchar* server; + TRACE_CALL(__func__); + RemminaFile* remminafile; + gchar* server; -remminafile = remmina_file_new(); -server = strdup(gtk_entry_get_text(remminamain->entry_quick_connect_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_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); + remmina_connection_window_open_from_file(remminafile); -return FALSE; + return FALSE; } gboolean remmina_main_quickconnect_on_click(GtkWidget *widget, gpointer user_data) { -TRACE_CALL(__func__); -return remmina_main_quickconnect(); + TRACE_CALL(__func__); + if (!kioskmode && kioskmode == FALSE) + return remmina_main_quickconnect(); + return FALSE; } /* 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); + 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__); + 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; + 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) { + TRACE_CALL(__func__); + if (event->button == MOUSE_BUTTON_RIGHT) { + if (!kioskmode && kioskmode == FALSE) #if GTK_CHECK_VERSION(3, 22, 0) - gtk_menu_popup_at_pointer(GTK_MENU(remminamain->menu_popup), (GdkEvent*)event); + 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); + gtk_menu_popup(remminamain->menu_popup, NULL, NULL, NULL, NULL, event->button, event->time); #endif -} -return FALSE; + } + 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) { + 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); + 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); + gtk_menu_popup(remminamain->menu_popup, NULL, NULL, NULL, NULL, 0, event->time); #endif -} -return FALSE; + } + 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, ""); -} + 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__); + 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(); + 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)); + 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) + 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); + 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); + 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; + 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; + 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); + TRACE_CALL(__func__); + int i; + char *name; + + remminamain->priv->expanded_group = remmina_string_array_new_from_string(remmina_pref.expanded_group); + if (!kioskmode && kioskmode == FALSE) { + gtk_window_set_title(remminamain->window, _("Remmina Remote Desktop Client")); + }else { + gtk_window_set_title(remminamain->window, _("Remmina Kiosk")); + } + if (!kioskmode && kioskmode == FALSE) + gtk_window_set_default_size(remminamain->window, remmina_pref.main_width, remmina_pref.main_height); + if (!kioskmode && kioskmode == FALSE) + 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 } @@ -1205,24 +1217,41 @@ GtkWidget* remmina_main_new(void) /* Assign UI widgets to the private members */ remminamain->builder = remmina_public_gtk_builder_new_from_file("remmina_main.glade"); remminamain->window = GTK_WINDOW(GET_OBJECT("RemminaMain")); + if (kioskmode && kioskmode == TRUE) { + gtk_window_set_position(remminamain->window, GTK_WIN_POS_CENTER_ALWAYS); + gtk_window_set_default_size(remminamain->window, 800, 400); + gtk_window_set_resizable(remminamain->window, FALSE); + } + /* New Button */ + remminamain->button_new = GTK_BUTTON(GET_OBJECT("button_new")); + if (kioskmode && kioskmode == TRUE) + gtk_widget_set_sensitive(GTK_WIDGET(remminamain->button_new), FALSE); /* Search bar */ - remminamain->search_toggle = GTK_TOGGLE_BUTTON (GET_OBJECT("search_toggle")); - remminamain->search_bar = GTK_SEARCH_BAR (GET_OBJECT("search_bar")); + remminamain->search_toggle = GTK_TOGGLE_BUTTON(GET_OBJECT("search_toggle")); + remminamain->search_bar = GTK_SEARCH_BAR(GET_OBJECT("search_bar")); /* Menu widgets */ remminamain->menu_popup = GTK_MENU(GET_OBJECT("menu_popup")); + remminamain->menu_header_button = GTK_MENU_BUTTON(GET_OBJECT("menu_header_button")); remminamain->menu_popup_full = GTK_MENU(GET_OBJECT("menu_popup_full")); + if (kioskmode && kioskmode == TRUE) { + gtk_widget_set_sensitive(GTK_WIDGET(remminamain->menu_popup_full), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(remminamain->menu_header_button), FALSE); + } /* 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")); + if (kioskmode && kioskmode == TRUE) + gtk_widget_set_sensitive(GTK_WIDGET(remminamain->combo_quick_connect_protocol), FALSE); 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")); + if (!kioskmode && kioskmode == FALSE) + 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 diff --git a/src/remmina_main.h b/src/remmina_main.h index bd45c28ad..14bc504fc 100644 --- a/src/remmina_main.h +++ b/src/remmina_main.h @@ -47,9 +47,12 @@ typedef struct _RemminaMain { GtkWindow *window; /* Menu widgets */ GtkMenu *menu_popup; + GtkMenuButton *menu_header_button; GtkMenu *menu_popup_full; GtkRadioMenuItem *menuitem_view_mode_list; GtkRadioMenuItem *menuitem_view_mode_tree; + /* Button new */ + GtkButton *button_new; /* Search bar objects */ GtkToggleButton *search_toggle; GtkSearchBar *search_bar; |