Remmina - The GTK+ Remote Desktop Client  v1.4.33
Remmina is a remote desktop client written in GTK+, aiming to be useful for system administrators and travellers, who need to work with lots of remote computers in front of either large monitors or tiny netbooks. Remmina supports multiple network protocols in an integrated and consistent user interface. Currently RDP, VNC, NX, XDMCP and SSH are supported.
remmina_applet_menu_item.c
Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2009-2010 Vic Lee
4  * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5  * Copyright (C) 2016-2022 Antenore Gatta, Giovanni Panozzo
6  * Copyright (C) 2022-2023 Antenore Gatta, Giovanni Panozzo, Hiroyuki Tanaka
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  * In addition, as a special exception, the copyright holders give
24  * permission to link the code of portions of this program with the
25  * OpenSSL library under certain conditions as described in each
26  * individual source file, and distribute linked combinations
27  * including the two.
28  * You must obey the GNU General Public License in all respects
29  * for all of the code used other than OpenSSL. * If you modify
30  * file(s) with this exception, you may extend this exception to your
31  * version of the file(s), but you are not obligated to do so. * If you
32  * do not wish to do so, delete this exception statement from your
33  * version. * If you delete this exception statement from all source
34  * files in the program, then also delete it here.
35  *
36  */
37 
38 #include <glib/gi18n.h>
39 #include <glib/gprintf.h>
40 #include <string.h>
41 #include <stdarg.h>
42 #include "config.h"
43 #include "remmina_plugin_manager.h"
46 
47 G_DEFINE_TYPE( RemminaAppletMenuItem, remmina_applet_menu_item, GTK_TYPE_MENU_ITEM)
48 
49 #define IS_EMPTY(s) ((!s) || (s[0] == 0))
50 
51 static void remmina_applet_menu_item_destroy(RemminaAppletMenuItem* item, gpointer data)
52 {
53  TRACE_CALL(__func__);
54  g_free(item->filename);
55  g_free(item->name);
56  g_free(item->group);
57  g_free(item->protocol);
58  g_free(item->server);
59 }
60 
62 {
63  TRACE_CALL(__func__);
64 }
65 
67 {
68  TRACE_CALL(__func__);
69  item->filename = NULL;
70  item->name = NULL;
71  item->group = NULL;
72  item->protocol = NULL;
73  item->server = NULL;
74  item->ssh_tunnel_enabled = FALSE;
75  g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remmina_applet_menu_item_destroy), NULL);
76 }
77 
79 {
80  TRACE_CALL(__func__);
81  va_list ap;
83  GKeyFile* gkeyfile;
84  GtkWidget* widget;
85  GtkWidget* box;
86  GtkWidget* icon;
87 
88  va_start(ap, item_type);
89 
90  item = REMMINA_APPLET_MENU_ITEM(g_object_new(REMMINA_TYPE_APPLET_MENU_ITEM, NULL));
91 
92  item->item_type = item_type;
93 
94  switch (item_type) {
96  item->filename = g_strdup(va_arg(ap, const gchar*));
97 
98  /* Load the file */
99  gkeyfile = g_key_file_new();
100 
101  if (!g_key_file_load_from_file(gkeyfile, item->filename, G_KEY_FILE_NONE, NULL)) {
102  g_key_file_free(gkeyfile);
103  va_end(ap);
104  return NULL;
105  }
106 
107  item->name = g_key_file_get_string(gkeyfile, "remmina", "name", NULL);
108  item->group = g_key_file_get_string(gkeyfile, "remmina", "group", NULL);
109  item->protocol = g_key_file_get_string(gkeyfile, "remmina", "protocol", NULL);
110  item->server = g_key_file_get_string(gkeyfile, "remmina", "server", NULL);
111  item->ssh_tunnel_enabled = g_key_file_get_boolean(gkeyfile, "remmina", "ssh_tunnel_enabled", NULL);
112 
113  g_key_file_free(gkeyfile);
114 
115  if (item->name == NULL) {
116  g_printf("WARNING: missing name= line in file %s. Skipping.\n", item->filename);
117  va_end(ap);
118  return NULL;
119  }
120 
121  break;
122 
124  item->name = g_strdup(va_arg(ap, const gchar *));
125  item->group = g_strdup(_("Discovered"));
126  item->protocol = g_strdup("VNC");
127  break;
128 
130  item->name = g_strdup(_("New Connection"));
131  break;
132  }
133 
134  va_end(ap);
135 
136 
137  /* Get the icon based on the protocol */
138  const gchar* icon_name;
139  RemminaProtocolPlugin *plugin;
141  item->protocol);
142  if (!plugin) {
143  icon_name = g_strconcat(REMMINA_APP_ID, "-symbolic", NULL);
144  } else {
145  icon_name = item->ssh_tunnel_enabled ? plugin->icon_name_ssh : plugin->icon_name;
146  }
147  icon = gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_MENU);
148 
149  /* Create the label */
150  widget = gtk_label_new(item->name);
151  box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
152  gtk_widget_show(widget);
153  gtk_widget_show(icon);
154  gtk_widget_show(box);
155  gtk_widget_set_valign(widget, GTK_ALIGN_START);
156  gtk_widget_set_halign(widget, GTK_ALIGN_START);
157  gtk_container_add(GTK_CONTAINER(box), icon);
158  gtk_container_add(GTK_CONTAINER(box), widget);
159  gtk_container_add(GTK_CONTAINER(item), box);
160 
161  if (item->server) {
162  gtk_widget_set_tooltip_text(GTK_WIDGET(item), item->server);
163  }
164 
165  return GTK_WIDGET(item);
166 }
167 
168 gint remmina_applet_menu_item_compare(gconstpointer a, gconstpointer b, gpointer user_data)
169 {
170  TRACE_CALL(__func__);
171  gint cmp;
172  RemminaAppletMenuItem* itema;
173  RemminaAppletMenuItem* itemb;
174 
175  /* Passed in parameters are pointers to pointers */
176  itema = REMMINA_APPLET_MENU_ITEM(*((void**)a));
177  itemb = REMMINA_APPLET_MENU_ITEM(*((void**)b));
178 
179  /* Put ungrouped items to the last */
180  if (IS_EMPTY(itema->group) && !IS_EMPTY(itemb->group))
181  return 1;
182  if (!IS_EMPTY(itema->group) && IS_EMPTY(itemb->group))
183  return -1;
184 
185  /* Put discovered items the last group */
187  return 1;
189  return -1;
190 
191  if (itema->item_type != REMMINA_APPLET_MENU_ITEM_DISCOVERED && !IS_EMPTY(itema->group)) {
192  cmp = g_strcmp0(itema->group, itemb->group);
193 
194  if (cmp != 0)
195  return cmp;
196  }
197 
198  return g_strcmp0(itema->name, itemb->name);
199 }
G_DEFINE_TYPE(RemminaAppletMenuItem, remmina_applet_menu_item, GTK_TYPE_MENU_ITEM)
RemminaAppletMenuItemType item_type
const gchar * icon_name_ssh
Definition: plugin.h:73
RemminaAppletMenuItemType
static void remmina_applet_menu_item_class_init(RemminaAppletMenuItemClass *klass)
gint remmina_applet_menu_item_compare(gconstpointer a, gconstpointer b, gpointer user_data)
RemminaPlugin * remmina_plugin_manager_get_plugin(RemminaPluginType type, const gchar *name)
GtkWidget * remmina_applet_menu_item_new(RemminaAppletMenuItemType item_type,...)
const gchar * icon_name
Definition: plugin.h:72
static void remmina_applet_menu_item_init(RemminaAppletMenuItem *item)