2
* Remmina - The GTK+ Remote Desktop Client
3
* Copyright (C) 2009-2010 Vic Lee
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330,
18
* Boston, MA 02111-1307, USA.
23
#include <glib/gstdio.h>
24
#include <glib/gi18n.h>
25
#include "remminastringarray.h"
26
#include "remminapublic.h"
27
#include "remminafile.h"
28
#include "remminafilemanager.h"
29
#include "remminafileeditor.h"
30
#include "remminaconnectionwindow.h"
31
#include "remminaabout.h"
32
#include "remminapref.h"
33
#include "remminaprefdialog.h"
34
#include "remminawidgetpool.h"
35
#include "remminapluginmanager.h"
36
#include "remminalog.h"
37
#include "remminamain.h"
39
G_DEFINE_TYPE (RemminaMain, remmina_main, GTK_TYPE_WINDOW)
41
struct _RemminaMainPriv
44
GtkTreeModel *file_model;
45
GtkTreeModel *file_model_filter;
46
GtkTreeModel *file_model_sort;
47
GtkUIManager *uimanager;
51
GtkToolItem *quick_search_separator;
52
GtkToolItem *quick_search_item;
53
GtkWidget *quick_search_entry;
55
GtkTreeViewColumn *group_column;
57
GtkActionGroup *main_group;
58
GtkActionGroup *file_sensitive_group;
62
gchar *selected_filename;
64
RemminaStringArray *expanded_group;
68
remmina_main_class_init (RemminaMainClass *klass)
82
static GtkTargetEntry remmina_drop_types[] =
84
{ "text/uri-list", 0, 1 }
88
remmina_main_save_size (RemminaMain *remminamain)
90
if ((gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (remminamain))) & GDK_WINDOW_STATE_MAXIMIZED) == 0)
92
gtk_window_get_size (GTK_WINDOW (remminamain), &remmina_pref.main_width, &remmina_pref.main_height);
93
remmina_pref.main_maximize = FALSE;
97
remmina_pref.main_maximize = TRUE;
102
remmina_main_save_expanded_group_func (GtkTreeView *tree_view, GtkTreePath *path, RemminaMain *remminamain)
107
gtk_tree_model_get_iter (remminamain->priv->file_model_sort, &iter, path);
108
gtk_tree_model_get (remminamain->priv->file_model_sort, &iter, GROUP_COLUMN, &group, -1);
111
remmina_string_array_add (remminamain->priv->expanded_group, group);
117
remmina_main_save_expanded_group (RemminaMain *remminamain)
119
if (GTK_IS_TREE_STORE (remminamain->priv->file_model))
121
if (remminamain->priv->expanded_group)
123
remmina_string_array_free (remminamain->priv->expanded_group);
125
remminamain->priv->expanded_group = remmina_string_array_new ();
126
gtk_tree_view_map_expanded_rows (GTK_TREE_VIEW (remminamain->priv->file_list),
127
(GtkTreeViewMappingFunc) remmina_main_save_expanded_group_func, remminamain);
132
remmina_main_on_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
134
RemminaMain *remminamain;
136
remminamain = REMMINA_MAIN (widget);
138
remmina_main_save_size (remminamain);
140
remmina_main_save_expanded_group (remminamain);
141
g_free (remmina_pref.expanded_group);
142
remmina_pref.expanded_group = remmina_string_array_to_string (remminamain->priv->expanded_group);
143
remmina_string_array_free (remminamain->priv->expanded_group);
144
remminamain->priv->expanded_group = NULL;
146
remmina_pref_save ();
151
remmina_main_destroy (GtkWidget *widget, gpointer data)
153
g_free (REMMINA_MAIN (widget)->priv->selected_filename);
154
g_free (REMMINA_MAIN (widget)->priv->selected_name);
155
g_free (REMMINA_MAIN (widget)->priv);
159
remmina_main_clear_selection_data (RemminaMain *remminamain)
161
g_free (remminamain->priv->selected_filename);
162
g_free (remminamain->priv->selected_name);
163
remminamain->priv->selected_filename = NULL;
164
remminamain->priv->selected_name = NULL;
166
gtk_action_group_set_sensitive (remminamain->priv->file_sensitive_group, FALSE);
170
remmina_main_selection_func (
171
GtkTreeSelection *selection,
174
gboolean path_currently_selected,
177
RemminaMain *remminamain;
182
remminamain = (RemminaMain*) user_data;
183
if (path_currently_selected) return TRUE;
185
if (!gtk_tree_model_get_iter (model, &iter, path)) return TRUE;
187
remmina_main_clear_selection_data (remminamain);
189
gtk_tree_model_get (model, &iter,
190
NAME_COLUMN, &remminamain->priv->selected_name,
191
FILENAME_COLUMN, &remminamain->priv->selected_filename,
194
context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (remminamain->priv->statusbar), "status");
195
gtk_statusbar_pop (GTK_STATUSBAR (remminamain->priv->statusbar), context_id);
196
if (remminamain->priv->selected_filename)
198
gtk_action_group_set_sensitive (remminamain->priv->file_sensitive_group, TRUE);
199
g_snprintf (buf, sizeof (buf), "%s (%s)", remminamain->priv->selected_name, remminamain->priv->selected_filename);
200
gtk_statusbar_push (GTK_STATUSBAR (remminamain->priv->statusbar), context_id, buf);
204
gtk_statusbar_push (GTK_STATUSBAR (remminamain->priv->statusbar), context_id, remminamain->priv->selected_name);
210
remmina_main_load_file_list_callback (gpointer data, gpointer user_data)
212
RemminaMain *remminamain;
215
RemminaFile *remminafile;
217
remminafile = (RemminaFile*) data;
218
remminamain = (RemminaMain*) user_data;
219
store = GTK_LIST_STORE (remminamain->priv->file_model);
221
gtk_list_store_append (store, &iter);
222
gtk_list_store_set (store, &iter,
223
PROTOCOL_COLUMN, remmina_file_get_icon_name (remminafile),
224
NAME_COLUMN, remmina_file_get_string (remminafile, "name"),
225
GROUP_COLUMN, remmina_file_get_string (remminafile, "group"),
226
SERVER_COLUMN, remmina_file_get_string (remminafile, "server"),
227
FILENAME_COLUMN, remmina_file_get_filename (remminafile),
232
remmina_main_load_file_tree_traverse (GNode *node, GtkTreeStore *store, GtkTreeIter *parent)
235
RemminaGroupData *data;
241
data = (RemminaGroupData*)node->data;
242
iter = g_new0 (GtkTreeIter, 1);
243
gtk_tree_store_append (store, iter, parent);
244
gtk_tree_store_set (store, iter,
245
PROTOCOL_COLUMN, GTK_STOCK_DIRECTORY,
246
NAME_COLUMN, data->name,
247
GROUP_COLUMN, data->group,
248
FILENAME_COLUMN, NULL,
251
for (child = g_node_first_child (node); child; child = g_node_next_sibling (child))
253
remmina_main_load_file_tree_traverse (child, store, iter);
260
remmina_main_load_file_tree_group (GtkTreeStore *store)
264
root = remmina_file_manager_get_group_tree ();
265
remmina_main_load_file_tree_traverse (root, store, NULL);
266
remmina_file_manager_free_group_tree (root);
270
remmina_main_expand_group_traverse (RemminaMain *remminamain, GtkTreeIter *iter)
274
gchar *group, *filename;
278
tree = remminamain->priv->file_model_sort;
282
gtk_tree_model_get (tree, iter, GROUP_COLUMN, &group, FILENAME_COLUMN, &filename, -1);
283
if (filename == NULL)
285
if (remmina_string_array_find (remminamain->priv->expanded_group, group) >= 0)
287
path = gtk_tree_model_get_path (tree, iter);
288
gtk_tree_view_expand_row (GTK_TREE_VIEW (remminamain->priv->file_list), path, FALSE);
289
gtk_tree_path_free (path);
291
if (gtk_tree_model_iter_children (tree, &child, iter))
293
remmina_main_expand_group_traverse (remminamain, &child);
299
ret = gtk_tree_model_iter_next (tree, iter);
304
remmina_main_expand_group (RemminaMain *remminamain)
308
if (gtk_tree_model_get_iter_first (remminamain->priv->file_model_sort, &iter))
310
remmina_main_expand_group_traverse (remminamain, &iter);
315
remmina_main_load_file_tree_find (GtkTreeModel *tree, GtkTreeIter *iter, const gchar *match_group)
318
gchar *group, *filename;
325
gtk_tree_model_get (tree, iter, GROUP_COLUMN, &group, FILENAME_COLUMN, &filename, -1);
326
match = (filename == NULL && g_strcmp0 (group, match_group) == 0);
330
if (gtk_tree_model_iter_children (tree, &child, iter))
332
match = remmina_main_load_file_tree_find (tree, &child, match_group);
335
memcpy (iter, &child, sizeof (GtkTreeIter));
339
ret = gtk_tree_model_iter_next (tree, iter);
345
remmina_main_load_file_tree_callback (gpointer data, gpointer user_data)
347
RemminaMain *remminamain;
348
GtkTreeIter iter, child;
350
RemminaFile *remminafile;
353
remminafile = (RemminaFile*) data;
354
remminamain = (RemminaMain*) user_data;
355
store = GTK_TREE_STORE (remminamain->priv->file_model);
358
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
360
found = remmina_main_load_file_tree_find (GTK_TREE_MODEL (store), &iter,
361
remmina_file_get_string (remminafile, "group"));
364
gtk_tree_store_append (store, &child, (found ? &iter : NULL));
365
gtk_tree_store_set (store, &child,
366
PROTOCOL_COLUMN, remmina_file_get_icon_name (remminafile),
367
NAME_COLUMN, remmina_file_get_string (remminafile, "name"),
368
GROUP_COLUMN, remmina_file_get_string (remminafile, "group"),
369
SERVER_COLUMN, remmina_file_get_string (remminafile, "server"),
370
FILENAME_COLUMN, remmina_file_get_filename (remminafile),
375
remmina_main_file_model_on_sort (GtkTreeSortable *sortable, RemminaMain *remminamain)
380
gtk_tree_sortable_get_sort_column_id (sortable, &columnid, &order);
381
remmina_pref.main_sort_column_id = columnid;
382
remmina_pref.main_sort_order = order;
383
remmina_pref_save ();
387
remmina_main_filter_visible_func (GtkTreeModel *model, GtkTreeIter *iter, RemminaMain *remminamain)
390
gchar *protocol, *name, *group, *server, *s;
391
gboolean result = TRUE;
393
if (!remmina_pref.show_quick_search) return TRUE;
395
text = g_ascii_strdown (gtk_entry_get_text (GTK_ENTRY (remminamain->priv->quick_search_entry)), -1);
398
gtk_tree_model_get (model, iter,
399
PROTOCOL_COLUMN, &protocol,
401
GROUP_COLUMN, &group,
402
SERVER_COLUMN, &server,
404
if (g_strcmp0 (protocol, GTK_STOCK_DIRECTORY) != 0)
406
s = g_ascii_strdown (name ? name : "", -1); g_free (name); name = s;
407
s = g_ascii_strdown (group ? group : "", -1); g_free (group); group = s;
408
s = g_ascii_strdown (server ? server : "", -1); g_free (server); server = s;
409
result = (strstr (name, text) || strstr (server, text) || strstr (group, text));
421
remmina_main_select_file (RemminaMain *remminamain, const gchar *filename)
425
gchar *item_filename;
428
if (!gtk_tree_model_get_iter_first (remminamain->priv->file_model_sort, &iter)) return;
432
gtk_tree_model_get (remminamain->priv->file_model_sort, &iter, FILENAME_COLUMN, &item_filename, -1);
433
cmp = g_strcmp0 (item_filename, filename);
434
g_free (item_filename);
437
gtk_tree_selection_select_iter (
438
gtk_tree_view_get_selection (GTK_TREE_VIEW (remminamain->priv->file_list)),
440
path = gtk_tree_model_get_path (remminamain->priv->file_model_sort, &iter);
441
gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (remminamain->priv->file_list),
442
path, NULL, TRUE, 0.5, 0.0);
443
gtk_tree_path_free (path);
446
if (!gtk_tree_model_iter_next (remminamain->priv->file_model_sort, &iter)) return;
451
remmina_main_load_files (RemminaMain *remminamain, gboolean refresh)
453
GtkTreeModel *filter;
461
remmina_main_save_expanded_group (remminamain);
464
switch (remmina_pref.view_file_mode)
467
case REMMINA_VIEW_FILE_TREE:
468
gtk_tree_view_column_set_visible (remminamain->priv->group_column, FALSE);
469
remminamain->priv->file_model = GTK_TREE_MODEL (gtk_tree_store_new (N_COLUMNS,
470
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING));
471
remmina_main_load_file_tree_group (GTK_TREE_STORE (remminamain->priv->file_model));
472
n = remmina_file_manager_iterate (remmina_main_load_file_tree_callback, remminamain);
475
case REMMINA_VIEW_FILE_LIST:
477
gtk_tree_view_column_set_visible (remminamain->priv->group_column, TRUE);
478
remminamain->priv->file_model = GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS,
479
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING));
480
n = remmina_file_manager_iterate (remmina_main_load_file_list_callback, remminamain);
484
filter = gtk_tree_model_filter_new (remminamain->priv->file_model, NULL);
485
gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
486
(GtkTreeModelFilterVisibleFunc) remmina_main_filter_visible_func, remminamain, NULL);
487
remminamain->priv->file_model_filter = filter;
489
sort = gtk_tree_model_sort_new_with_model (filter);
490
remminamain->priv->file_model_sort = sort;
492
gtk_tree_view_set_model (GTK_TREE_VIEW (remminamain->priv->file_list), sort);
493
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort),
494
remmina_pref.main_sort_column_id, remmina_pref.main_sort_order);
495
g_signal_connect (G_OBJECT (sort), "sort-column-changed",
496
G_CALLBACK (remmina_main_file_model_on_sort), remminamain);
497
remmina_main_expand_group (remminamain);
499
if (remminamain->priv->selected_filename)
501
remmina_main_select_file (remminamain, remminamain->priv->selected_filename);
504
g_snprintf (buf, 200, ngettext("Total %i item.", "Total %i items.", n), n);
505
context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (remminamain->priv->statusbar), "status");
506
gtk_statusbar_pop (GTK_STATUSBAR (remminamain->priv->statusbar), context_id);
507
gtk_statusbar_push (GTK_STATUSBAR (remminamain->priv->statusbar), context_id, buf);
511
remmina_main_action_connection_connect (GtkAction *action, RemminaMain *remminamain)
513
remmina_connection_window_open_from_filename (remminamain->priv->selected_filename);
517
remmina_main_file_editor_destroy (GtkWidget *widget, RemminaMain *remminamain)
519
if (GTK_IS_WIDGET (remminamain))
521
remmina_main_load_files (remminamain, TRUE);
526
remmina_main_action_connection_new (GtkAction *action, RemminaMain *remminamain)
530
widget = remmina_file_editor_new ();
531
g_signal_connect (G_OBJECT (widget), "destroy", G_CALLBACK (remmina_main_file_editor_destroy), remminamain);
532
gtk_widget_show (widget);
536
remmina_main_action_connection_copy (GtkAction *action, RemminaMain *remminamain)
540
if (remminamain->priv->selected_filename == NULL) return;
542
widget = remmina_file_editor_new_copy (remminamain->priv->selected_filename);
545
g_signal_connect (G_OBJECT (widget), "destroy", G_CALLBACK (remmina_main_file_editor_destroy), remminamain);
546
gtk_widget_show (widget);
551
remmina_main_action_connection_edit (GtkAction *action, RemminaMain *remminamain)
555
if (remminamain->priv->selected_filename == NULL) return;
557
widget = remmina_file_editor_new_from_filename (remminamain->priv->selected_filename);
560
g_signal_connect (G_OBJECT (widget), "destroy", G_CALLBACK (remmina_main_file_editor_destroy), remminamain);
561
gtk_widget_show (widget);
566
remmina_main_action_connection_delete (GtkAction *action, RemminaMain *remminamain)
570
if (remminamain->priv->selected_filename == NULL) return;
572
dialog = gtk_message_dialog_new (GTK_WINDOW (remminamain),
573
GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
574
_("Are you sure to delete '%s'"), remminamain->priv->selected_name);
575
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_YES)
577
g_unlink (remminamain->priv->selected_filename);
578
remmina_main_load_files (remminamain, TRUE);
580
gtk_widget_destroy (dialog);
581
remmina_main_clear_selection_data (remminamain);
585
remmina_main_action_edit_preferences (GtkAction *action, RemminaMain *remminamain)
589
widget = remmina_pref_dialog_new (0);
590
gtk_widget_show (widget);
594
remmina_main_action_connection_close (GtkAction *action, RemminaMain *remminamain)
596
gtk_widget_destroy (GTK_WIDGET (remminamain));
600
remmina_main_action_view_toolbar (GtkToggleAction *action, RemminaMain *remminamain)
604
toggled = gtk_toggle_action_get_active (action);
607
gtk_widget_show (remminamain->priv->toolbar);
611
gtk_widget_hide (remminamain->priv->toolbar);
613
if (remminamain->priv->initialized)
615
remmina_pref.hide_toolbar = !toggled;
616
remmina_pref_save ();
621
remmina_main_action_view_quick_search (GtkToggleAction *action, RemminaMain *remminamain)
625
toggled = gtk_toggle_action_get_active (action);
628
gtk_entry_set_text (GTK_ENTRY (remminamain->priv->quick_search_entry), "");
629
gtk_widget_show (GTK_WIDGET (remminamain->priv->quick_search_separator));
630
gtk_widget_show (GTK_WIDGET (remminamain->priv->quick_search_item));
631
gtk_widget_grab_focus (remminamain->priv->quick_search_entry);
635
gtk_widget_hide (GTK_WIDGET (remminamain->priv->quick_search_separator));
636
gtk_widget_hide (GTK_WIDGET (remminamain->priv->quick_search_item));
638
if (remminamain->priv->initialized)
640
remmina_pref.show_quick_search = toggled;
641
remmina_pref_save ();
645
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (remminamain->priv->file_model_filter));
646
gtk_tree_view_expand_all (GTK_TREE_VIEW (remminamain->priv->file_list));
652
remmina_main_action_view_statusbar (GtkToggleAction *action, RemminaMain *remminamain)
656
toggled = gtk_toggle_action_get_active (action);
659
gtk_widget_show (remminamain->priv->statusbar);
663
gtk_widget_hide (remminamain->priv->statusbar);
665
if (remminamain->priv->initialized)
667
remmina_pref.hide_statusbar = !toggled;
668
remmina_pref_save ();
673
remmina_main_action_view_small_toolbutton (GtkToggleAction *action, RemminaMain *remminamain)
677
toggled = gtk_toggle_action_get_active (action);
680
gtk_toolbar_set_icon_size (GTK_TOOLBAR (remminamain->priv->toolbar), GTK_ICON_SIZE_MENU);
684
gtk_toolbar_unset_icon_size (GTK_TOOLBAR (remminamain->priv->toolbar));
686
if (remminamain->priv->initialized)
688
remmina_pref.small_toolbutton = toggled;
689
remmina_pref_save ();
694
remmina_main_action_view_file_mode (GtkRadioAction *action, GtkRadioAction *current, RemminaMain *remminamain)
696
remmina_pref.view_file_mode = gtk_radio_action_get_current_value (action);
697
remmina_pref_save ();
698
remmina_main_load_files (remminamain, TRUE);
702
remmina_main_import_file_list (RemminaMain *remminamain, GSList *files)
707
RemminaFilePlugin *plugin;
709
RemminaFile *remminafile = NULL;
712
err = g_string_new (NULL);
714
for (element = files; element; element = element->next)
716
path = (gchar*) element->data;
717
plugin = remmina_plugin_manager_get_import_file_handler (path);
718
if (plugin && (remminafile = plugin->import_func (path)) != NULL &&
719
remmina_file_get_string (remminafile, "name"))
721
remmina_file_generate_filename (remminafile);
722
remmina_file_save_all (remminafile);
727
g_string_append (err, path);
728
g_string_append_c (err, '\n');
732
remmina_file_free (remminafile);
737
g_slist_free (files);
740
dlg = gtk_message_dialog_new (GTK_WINDOW (remminamain),
741
GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
742
_("Unable to import:\n%s"), err->str);
743
g_signal_connect (G_OBJECT (dlg), "response", G_CALLBACK (gtk_widget_destroy), NULL);
744
gtk_widget_show (dlg);
746
g_string_free (err, TRUE);
749
remmina_main_load_files (remminamain, TRUE);
754
remmina_main_action_tools_import_on_response (GtkDialog *dialog, gint response_id, RemminaMain *remminamain)
758
if (response_id == GTK_RESPONSE_ACCEPT)
760
files = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (dialog));
761
remmina_main_import_file_list (remminamain, files);
763
gtk_widget_destroy (GTK_WIDGET (dialog));
767
remmina_main_action_tools_import (GtkAction *action, RemminaMain *remminamain)
771
dialog = gtk_file_chooser_dialog_new (_("Import"), GTK_WINDOW (remminamain),
772
GTK_FILE_CHOOSER_ACTION_OPEN,
773
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
775
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
776
g_signal_connect (G_OBJECT (dialog), "response",
777
G_CALLBACK (remmina_main_action_tools_import_on_response), remminamain);
778
gtk_widget_show (dialog);
782
remmina_main_action_tools_export (GtkAction *action, RemminaMain *remminamain)
784
RemminaFilePlugin *plugin;
785
RemminaFile *remminafile;
788
if (remminamain->priv->selected_filename == NULL) return;
790
remminafile = remmina_file_load (remminamain->priv->selected_filename);
791
if (remminafile == NULL) return;
792
plugin = remmina_plugin_manager_get_export_file_handler (remminafile);
795
dialog = gtk_file_chooser_dialog_new (plugin->export_hints, GTK_WINDOW (remminamain),
796
GTK_FILE_CHOOSER_ACTION_SAVE,
797
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
799
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
801
plugin->export_func (remminafile, gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)));
803
gtk_widget_destroy (dialog);
807
dialog = gtk_message_dialog_new (GTK_WINDOW (remminamain),
808
GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
809
_("This protocol does not support exporting."));
810
g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), NULL);
811
gtk_widget_show (dialog);
813
remmina_file_free (remminafile);
817
remmina_main_action_tools_plugins (GtkAction *action, RemminaMain *remminamain)
819
remmina_plugin_manager_show (GTK_WINDOW (remminamain));
823
remmina_main_action_tools_addition (GtkAction *action, RemminaMain *remminamain)
825
RemminaToolPlugin *plugin;
827
plugin = (RemminaToolPlugin *) remmina_plugin_manager_get_plugin (REMMINA_PLUGIN_TYPE_TOOL, gtk_action_get_name (action));
835
remmina_main_action_help_homepage (GtkAction *action, RemminaMain *remminamain)
837
g_app_info_launch_default_for_uri ("http://remmina.sourceforge.net", NULL, NULL);
841
remmina_main_action_help_wiki (GtkAction *action, RemminaMain *remminamain)
843
g_app_info_launch_default_for_uri ("http://sourceforge.net/apps/mediawiki/remmina/", NULL, NULL);
847
remmina_main_action_help_debug (GtkAction *action, RemminaMain *remminamain)
849
remmina_log_start ();
853
remmina_main_action_help_about (GtkAction *action, RemminaMain *remminamain)
855
remmina_about_open (GTK_WINDOW (remminamain));
858
static const gchar *remmina_main_ui_xml =
860
" <menubar name='MenuBar'>"
861
" <menu name='ConnectionMenu' action='Connection'>"
862
" <menuitem name='ConnectionConnectMenu' action='ConnectionConnect'/>"
864
" <menuitem name='ConnectionNewMenu' action='ConnectionNew'/>"
865
" <menuitem name='ConnectionCopyMenu' action='ConnectionCopy'/>"
866
" <menuitem name='ConnectionEditMenu' action='ConnectionEdit'/>"
867
" <menuitem name='ConnectionDeleteMenu' action='ConnectionDelete'/>"
869
" <menuitem name='ConnectionCloseMenu' action='ConnectionClose'/>"
871
" <menu name='EditMenu' action='Edit'>"
872
" <menuitem name='EditPreferencesMenu' action='EditPreferences'/>"
874
" <menu name='ViewMenu' action='View'>"
875
" <menuitem name='ViewToolbarMenu' action='ViewToolbar'/>"
876
" <menuitem name='ViewStatusbarMenu' action='ViewStatusbar'/>"
877
" <menuitem name='ViewQuickSearchMenu' action='ViewQuickSearch'/>"
879
" <menuitem name='ViewSmallToolbuttonMenu' action='ViewSmallToolbutton'/>"
881
" <menuitem name='ViewFileListMenu' action='ViewFileList'/>"
882
" <menuitem name='ViewFileTreeMenu' action='ViewFileTree'/>"
884
" <menu name='ToolsMenu' action='Tools'>"
885
" <menuitem name='ToolsImportMenu' action='ToolsImport'/>"
886
" <menuitem name='ToolsExportMenu' action='ToolsExport'/>"
887
" <placeholder name='ToolsAdditions'/>"
889
" <menuitem name='ToolsPluginsMenu' action='ToolsPlugins'/>"
891
" <menu name='HelpMenu' action='Help'>"
892
" <menuitem name='HelpHomepageMenu' action='HelpHomepage'/>"
893
" <menuitem name='HelpWikiMenu' action='HelpWiki'/>"
894
" <menuitem name='HelpDebugMenu' action='HelpDebug'/>"
896
" <menuitem name='HelpAboutMenu' action='HelpAbout'/>"
899
" <toolbar name='ToolBar'>"
900
" <toolitem action='ConnectionConnect'/>"
902
" <toolitem action='ConnectionNew'/>"
903
" <toolitem action='ConnectionCopy'/>"
904
" <toolitem action='ConnectionEdit'/>"
905
" <toolitem action='ConnectionDelete'/>"
907
" <toolitem action='EditPreferences'/>"
909
" <popup name='PopupMenu'>"
910
" <menuitem action='ConnectionConnect'/>"
912
" <menuitem action='ConnectionCopy'/>"
913
" <menuitem action='ConnectionEdit'/>"
914
" <menuitem action='ConnectionDelete'/>"
918
static const GtkActionEntry remmina_main_ui_menu_entries[] =
920
{ "Connection", NULL, N_("_Connection") },
921
{ "Edit", NULL, N_("_Edit") },
922
{ "View", NULL, N_("_View") },
923
{ "Tools", NULL, N_("_Tools") },
924
{ "Help", NULL, N_("_Help") },
926
{ "ConnectionNew", GTK_STOCK_NEW, NULL, "<control>N",
927
N_("Create a new remote desktop file"),
928
G_CALLBACK (remmina_main_action_connection_new) },
930
{ "EditPreferences", GTK_STOCK_PREFERENCES, NULL, "<control>P",
931
N_("Open the preferences dialog"),
932
G_CALLBACK (remmina_main_action_edit_preferences) },
934
{ "ConnectionClose", GTK_STOCK_CLOSE, NULL, "<control>X",
936
G_CALLBACK (remmina_main_action_connection_close) },
938
{ "ToolsImport", NULL, N_("Import"), NULL,
940
G_CALLBACK (remmina_main_action_tools_import) },
942
{ "ToolsPlugins", NULL, N_("Plugins"), NULL,
944
G_CALLBACK (remmina_main_action_tools_plugins) },
946
{ "HelpHomepage", NULL, N_("Homepage"), NULL,
948
G_CALLBACK (remmina_main_action_help_homepage) },
950
{ "HelpWiki", NULL, N_("Online Wiki"), NULL,
952
G_CALLBACK (remmina_main_action_help_wiki) },
954
{ "HelpDebug", NULL, N_("Debug Window"), NULL,
956
G_CALLBACK (remmina_main_action_help_debug) },
958
{ "HelpAbout", GTK_STOCK_ABOUT, NULL, NULL,
960
G_CALLBACK (remmina_main_action_help_about) }
963
static const GtkActionEntry remmina_main_ui_file_sensitive_menu_entries[] =
965
{ "ConnectionConnect", GTK_STOCK_CONNECT, NULL, "<control>O",
966
N_("Open the connection to the selected remote desktop file"),
967
G_CALLBACK (remmina_main_action_connection_connect) },
969
{ "ConnectionCopy", GTK_STOCK_COPY, NULL, "<control>C",
970
N_("Create a copy of the selected remote desktop file"),
971
G_CALLBACK (remmina_main_action_connection_copy) },
973
{ "ConnectionEdit", GTK_STOCK_EDIT, NULL, "<control>E",
974
N_("Edit the selected remote desktop file"),
975
G_CALLBACK (remmina_main_action_connection_edit) },
977
{ "ConnectionDelete", GTK_STOCK_DELETE, NULL, "<control>D",
978
N_("Delete the selected remote desktop file"),
979
G_CALLBACK (remmina_main_action_connection_delete) },
981
{ "ToolsExport", NULL, N_("Export"), NULL,
983
G_CALLBACK (remmina_main_action_tools_export) }
986
static const GtkToggleActionEntry remmina_main_ui_toggle_menu_entries[] =
988
{ "ViewToolbar", NULL, N_("Toolbar"), NULL, NULL,
989
G_CALLBACK (remmina_main_action_view_toolbar), TRUE },
991
{ "ViewStatusbar", NULL, N_("Statusbar"), NULL, NULL,
992
G_CALLBACK (remmina_main_action_view_statusbar), TRUE },
994
{ "ViewQuickSearch", NULL, N_("Quick Search"), NULL, NULL,
995
G_CALLBACK (remmina_main_action_view_quick_search), FALSE },
997
{ "ViewSmallToolbutton", NULL, N_("Small Toolbar Buttons"), NULL, NULL,
998
G_CALLBACK (remmina_main_action_view_small_toolbutton), FALSE }
1001
static const GtkRadioActionEntry remmina_main_ui_view_file_mode_entries[] =
1003
{ "ViewFileList", NULL, N_("List View"), NULL, NULL, REMMINA_VIEW_FILE_LIST },
1004
{ "ViewFileTree", NULL, N_("Tree View"), NULL, NULL, REMMINA_VIEW_FILE_TREE }
1008
remmina_main_file_list_on_button_press (GtkWidget *widget, GdkEventButton *event, RemminaMain *remminamain)
1012
if (event->button == 3)
1014
popup = gtk_ui_manager_get_widget (remminamain->priv->uimanager, "/PopupMenu");
1017
gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL, event->button, event->time);
1020
else if (event->type == GDK_2BUTTON_PRESS && remminamain->priv->selected_filename)
1022
switch (remmina_pref.default_action)
1024
case REMMINA_ACTION_EDIT:
1025
remmina_main_action_connection_edit (NULL, remminamain);
1027
case REMMINA_ACTION_CONNECT:
1029
remmina_main_action_connection_connect (NULL, remminamain);
1037
remmina_main_quick_search_on_icon_press (GtkEntry *entry,
1038
GtkEntryIconPosition icon_pos,
1040
RemminaMain *remminamain)
1042
if (icon_pos == GTK_ENTRY_ICON_SECONDARY)
1044
gtk_entry_set_text (entry, "");
1049
remmina_main_quick_search_on_changed (GtkEditable *editable, RemminaMain *remminamain)
1051
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (remminamain->priv->file_model_filter));
1052
gtk_tree_view_expand_all (GTK_TREE_VIEW (remminamain->priv->file_list));
1056
remmina_main_create_quick_search (RemminaMain *remminamain)
1061
remminamain->priv->quick_search_separator = gtk_separator_tool_item_new ();
1062
gtk_toolbar_insert (GTK_TOOLBAR (remminamain->priv->toolbar), remminamain->priv->quick_search_separator, -1);
1064
remminamain->priv->quick_search_item = gtk_tool_item_new ();
1065
gtk_toolbar_insert (GTK_TOOLBAR (remminamain->priv->toolbar), remminamain->priv->quick_search_item, -1);
1067
widget = gtk_entry_new ();
1068
gtk_widget_show (widget);
1069
gtk_entry_set_icon_from_stock (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_FIND);
1070
gtk_entry_set_icon_from_stock (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1071
gtk_entry_set_width_chars (GTK_ENTRY (widget), 25);
1072
gtk_container_add (GTK_CONTAINER (remminamain->priv->quick_search_item), widget);
1074
g_value_init (&val, G_TYPE_BOOLEAN);
1075
g_value_set_boolean (&val, FALSE);
1076
g_object_set_property (G_OBJECT (widget), "primary-icon-activatable", &val);
1077
g_value_unset (&val);
1079
g_signal_connect (G_OBJECT (widget), "icon-press", G_CALLBACK (remmina_main_quick_search_on_icon_press), remminamain);
1080
g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (remmina_main_quick_search_on_changed), remminamain);
1082
remminamain->priv->quick_search_entry = widget;
1086
remmina_main_on_drag_data_received (RemminaMain *remminamain, GdkDragContext *drag_context, gint x, gint y,
1087
GtkSelectionData *data, guint info, guint time, gpointer user_data)
1090
GSList *files = NULL;
1093
uris = g_uri_list_extract_uris ((gchar *) data->data);
1094
for (i = 0; uris[i]; i++)
1096
if (strncmp (uris[i], "file://", 7) != 0) continue;
1097
files = g_slist_append (files, g_strdup (uris[i] + 7));
1100
remmina_main_import_file_list (remminamain, files);
1104
remmina_main_add_tool_plugin (gchar *name, RemminaPlugin *plugin, gpointer data)
1106
RemminaMain *remminamain = REMMINA_MAIN (data);
1110
merge_id = gtk_ui_manager_new_merge_id (remminamain->priv->uimanager);
1111
action = gtk_action_new (name, plugin->description, NULL, NULL);
1112
gtk_action_group_add_action (remminamain->priv->main_group, action);
1113
g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (remmina_main_action_tools_addition), remminamain);
1114
g_object_unref (action);
1116
gtk_ui_manager_add_ui (remminamain->priv->uimanager, merge_id, "/MenuBar/ToolsMenu/ToolsAdditions",
1117
name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
1123
remmina_main_on_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
1127
screen = gdk_screen_get_default ();
1128
if (remmina_pref.minimize_to_tray &&
1129
(event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) != 0 &&
1130
(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) != 0 &&
1131
remmina_public_get_current_workspace (screen) ==
1132
remmina_public_get_window_workspace (GTK_WINDOW (widget)) &&
1133
gdk_screen_get_number (screen) ==
1134
gdk_screen_get_number (gtk_widget_get_screen (widget))
1137
gtk_widget_hide (widget);
1144
remmina_main_init (RemminaMain *remminamain)
1146
RemminaMainPriv *priv;
1149
GtkUIManager *uimanager;
1150
GtkActionGroup *action_group;
1151
GtkWidget *scrolledwindow;
1153
GtkCellRenderer *renderer;
1154
GtkTreeViewColumn *column;
1157
priv = g_new0 (RemminaMainPriv, 1);
1158
remminamain->priv = priv;
1160
remminamain->priv->expanded_group = remmina_string_array_new_from_string (remmina_pref.expanded_group);
1162
/* Create main window */
1163
g_signal_connect (G_OBJECT (remminamain), "delete-event", G_CALLBACK (remmina_main_on_delete_event), NULL);
1164
g_signal_connect (G_OBJECT (remminamain), "destroy", G_CALLBACK (remmina_main_destroy), NULL);
1165
g_signal_connect (G_OBJECT (remminamain), "window-state-event", G_CALLBACK (remmina_main_on_window_state_event), NULL);
1166
gtk_container_set_border_width (GTK_CONTAINER (remminamain), 0);
1167
gtk_window_set_title (GTK_WINDOW (remminamain), _("Remmina Remote Desktop Client"));
1168
gtk_window_set_default_size (GTK_WINDOW (remminamain), remmina_pref.main_width, remmina_pref.main_height);
1169
gtk_window_set_position (GTK_WINDOW (remminamain), GTK_WIN_POS_CENTER);
1170
if (remmina_pref.main_maximize)
1172
gtk_window_maximize (GTK_WINDOW (remminamain));
1175
/* Create the main container */
1176
vbox = gtk_vbox_new (FALSE, 0);
1177
gtk_container_add (GTK_CONTAINER (remminamain), vbox);
1178
gtk_widget_show (vbox);
1180
/* Create the menubar and toolbar */
1181
uimanager = gtk_ui_manager_new ();
1182
priv->uimanager = uimanager;
1184
action_group = gtk_action_group_new ("RemminaMainActions");
1185
gtk_action_group_set_translation_domain (action_group, NULL);
1186
gtk_action_group_add_actions (action_group, remmina_main_ui_menu_entries,
1187
G_N_ELEMENTS (remmina_main_ui_menu_entries), remminamain);
1188
gtk_action_group_add_toggle_actions (action_group, remmina_main_ui_toggle_menu_entries,
1189
G_N_ELEMENTS (remmina_main_ui_toggle_menu_entries), remminamain);
1190
gtk_action_group_add_radio_actions (action_group, remmina_main_ui_view_file_mode_entries,
1191
G_N_ELEMENTS (remmina_main_ui_view_file_mode_entries),
1192
remmina_pref.view_file_mode, G_CALLBACK (remmina_main_action_view_file_mode), remminamain);
1194
gtk_ui_manager_insert_action_group (uimanager, action_group, 0);
1195
g_object_unref (action_group);
1196
priv->main_group = action_group;
1198
action_group = gtk_action_group_new ("RemminaMainFileSensitiveActions");
1199
gtk_action_group_set_translation_domain (action_group, NULL);
1200
gtk_action_group_add_actions (action_group, remmina_main_ui_file_sensitive_menu_entries,
1201
G_N_ELEMENTS (remmina_main_ui_file_sensitive_menu_entries), remminamain);
1203
gtk_ui_manager_insert_action_group (uimanager, action_group, 0);
1204
g_object_unref (action_group);
1205
priv->file_sensitive_group = action_group;
1208
gtk_ui_manager_add_ui_from_string (uimanager, remmina_main_ui_xml, -1, &error);
1211
g_message ("building menus failed: %s", error->message);
1212
g_error_free (error);
1215
remmina_plugin_manager_for_each_plugin (REMMINA_PLUGIN_TYPE_TOOL, remmina_main_add_tool_plugin, remminamain);
1217
menubar = gtk_ui_manager_get_widget (uimanager, "/MenuBar");
1218
gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0);
1220
priv->toolbar = gtk_ui_manager_get_widget (uimanager, "/ToolBar");
1221
gtk_box_pack_start (GTK_BOX (vbox), priv->toolbar, FALSE, FALSE, 0);
1223
remmina_main_create_quick_search (remminamain);
1225
gtk_window_add_accel_group (GTK_WINDOW (remminamain), gtk_ui_manager_get_accel_group (uimanager));
1227
gtk_action_group_set_sensitive (priv->file_sensitive_group, FALSE);
1229
/* Create the scrolled window for the file list */
1230
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
1231
gtk_widget_show (scrolledwindow);
1232
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
1233
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1234
gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0);
1236
/* Create the remmina file list */
1237
tree = gtk_tree_view_new ();
1239
column = gtk_tree_view_column_new ();
1240
gtk_tree_view_column_set_title (column, _("Name"));
1241
gtk_tree_view_column_set_resizable (column, TRUE);
1242
gtk_tree_view_column_set_sort_column_id (column, NAME_COLUMN);
1243
renderer = gtk_cell_renderer_pixbuf_new ();
1244
gtk_tree_view_column_pack_start (column, renderer, FALSE);
1245
gtk_tree_view_column_add_attribute (column, renderer, "icon-name", PROTOCOL_COLUMN);
1246
g_object_set (G_OBJECT (renderer), "stock-size", GTK_ICON_SIZE_LARGE_TOOLBAR, NULL);
1247
renderer = gtk_cell_renderer_text_new ();
1248
gtk_tree_view_column_pack_start (column, renderer, FALSE);
1249
gtk_tree_view_column_add_attribute (column, renderer, "text", NAME_COLUMN);
1250
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
1252
renderer = gtk_cell_renderer_text_new ();
1253
column = gtk_tree_view_column_new_with_attributes (_("Group"),
1254
renderer, "text", GROUP_COLUMN, NULL);
1255
gtk_tree_view_column_set_resizable (column, TRUE);
1256
gtk_tree_view_column_set_sort_column_id (column, GROUP_COLUMN);
1257
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
1258
priv->group_column = column;
1260
renderer = gtk_cell_renderer_text_new ();
1261
column = gtk_tree_view_column_new_with_attributes (_("Server"),
1262
renderer, "text", SERVER_COLUMN, NULL);
1263
gtk_tree_view_column_set_resizable (column, TRUE);
1264
gtk_tree_view_column_set_sort_column_id (column, SERVER_COLUMN);
1265
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
1267
gtk_container_add (GTK_CONTAINER (scrolledwindow), tree);
1268
gtk_widget_show (tree);
1270
gtk_tree_selection_set_select_function (
1271
gtk_tree_view_get_selection (GTK_TREE_VIEW (tree)),
1272
remmina_main_selection_func, remminamain, NULL);
1273
g_signal_connect (G_OBJECT (tree), "button-press-event",
1274
G_CALLBACK (remmina_main_file_list_on_button_press), remminamain);
1276
priv->file_list = tree;
1278
/* Create statusbar */
1279
priv->statusbar = gtk_statusbar_new ();
1280
gtk_box_pack_start (GTK_BOX (vbox), priv->statusbar, FALSE, FALSE, 0);
1281
gtk_widget_show (priv->statusbar);
1283
/* Prepare the data */
1284
remmina_main_load_files (remminamain, FALSE);
1286
/* Load the preferences */
1287
if (remmina_pref.hide_toolbar)
1289
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (
1290
gtk_action_group_get_action (priv->main_group, "ViewToolbar")), FALSE);
1292
if (remmina_pref.hide_statusbar)
1294
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (
1295
gtk_action_group_get_action (priv->main_group, "ViewStatusbar")), FALSE);
1297
if (remmina_pref.show_quick_search)
1299
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (
1300
gtk_action_group_get_action (priv->main_group, "ViewQuickSearch")), TRUE);
1302
if (remmina_pref.small_toolbutton)
1304
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (
1305
gtk_action_group_get_action (priv->main_group, "ViewSmallToolbutton")), TRUE);
1308
/* Drag-n-drop support */
1309
gtk_drag_dest_set (GTK_WIDGET (remminamain), GTK_DEST_DEFAULT_ALL, remmina_drop_types, 1, GDK_ACTION_COPY);
1310
g_signal_connect (G_OBJECT (remminamain), "drag-data-received",
1311
G_CALLBACK (remmina_main_on_drag_data_received), NULL);
1313
priv->initialized = TRUE;
1315
remmina_widget_pool_register (GTK_WIDGET (remminamain));
1319
remmina_main_new (void)
1321
RemminaMain *window;
1323
window = REMMINA_MAIN (g_object_new (REMMINA_TYPE_MAIN, NULL));
1324
return GTK_WIDGET (window);