4
* Copyright (C) 2008 Stefan Walter
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU Lesser General Public License as
8
* published by the Free Software Foundation; either version 2.1 of
9
* the License, or (at your option) any later version.
11
* This program is distributed in the hope that it will be useful, but
12
* WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26
public abstract class Viewer : Widget, View {
28
private UIManager _ui_manager;
29
private ActionGroup _object_actions;
30
private HashTable<Quark, Commands> _commands;
31
private static bool _about_initialized;
33
private static const ActionEntry[] UI_ENTRIES = {
36
{ "key-menu", null, N_("_Key") },
37
{ "edit-menu", null, N_("_Edit") },
38
{ "view-menu", null, N_("_View") },
39
{ "help-menu", null, N_("_Help") },
41
{ "app-preferences", Gtk.STOCK_PREFERENCES, N_("Prefere_nces"), null,
42
N_("Change preferences for this program"), null },
43
{ "app-about", "gnome-stock-about", N_("_About"), null,
44
N_("About this program"), null },
45
{ "help-show", Gtk.STOCK_HELP, N_("_Contents"), "F1",
46
N_("Show Seahorse help"), null }
49
private static const ActionEntry[] KEY_ENTRIES = {
50
{ "key-properties", Gtk.STOCK_PROPERTIES, N_("P_roperties"), null,
51
N_("Show key properties"), null },
52
{ "key-export-file", Gtk.STOCK_SAVE_AS, N_("E_xport Public Key..."), null,
53
N_("Export public part of key to a file"), null },
54
{ "key-export-clipboard", Gtk.STOCK_COPY, N_("_Copy Public Key"), "<control>C",
55
N_("Copy public part of selected keys to the clipboard"), null },
56
{ "key-delete", Gtk.STOCK_DELETE, N_("_Delete Key"), null,
57
N_("Delete selected keys"), null }
61
_ui_manager = new Gtk.UIManager ();
63
/* The widgts get added in an idle loop later */
64
_ui_manager.add_widget += on_ui_add_widget;
67
string path = "%sseahorse-%s.ui".printf (Config.SEAHORSE_GLADEDIR, name);
68
_ui_manager.add_ui_from_file (path);
70
warning ("couldn't load ui description for '%s': %s", name, ex.message);
73
var win = get_toplevel ();
74
if (win.get_type() == typeof (Gtk.Window))
75
((Gtk.Window)win).add_accel_group (_ui_manager.get_accel_group ());
77
include_basic_actions ();
78
this.selection_changed += on_selection_changed;
80
/* Setup the commands */
81
_commands = new HashTable<Quark, Commands> (GLib.direct_hash, GLib.direct_equal);
82
var types = Registry.get().find_types ("commands", null);
83
foreach (GLib.Type typ in types) {
85
/* Add each commands to our hash table */
86
Commands commands = (Commands)GLib.Object.new(typ, "view", this, null);
87
_commands.insert (commands.ktype, commands);
89
/* Add the UI for each commands */
90
var actions = commands.command_actions;
92
include_actions (actions);
93
var uidef = commands.ui_definition;
94
if (uidef != null && uidef.len() > 0)
95
_ui_manager.add_ui_from_string (uidef, -1);
100
private void include_basic_actions () {
103
* We hook callbacks up here for now because of a compiler warning. See:
104
* http://bugzilla.gnome.org/show_bug.cgi?id=539483
107
var actions = new Gtk.ActionGroup ("main");
108
actions.set_translation_domain (Config.GETTEXT_PACKAGE);
109
actions.add_actions (UI_ENTRIES, this);
110
actions.get_action("app-preferences").activate += on_app_preferences;
111
actions.get_action("app-about").activate += on_app_about;
112
actions.get_action("help-show").activate += on_help_show;
113
include_actions (actions);
115
_object_actions = new Gtk.ActionGroup ("key");
116
_object_actions.set_translation_domain (Config.GETTEXT_PACKAGE);
117
_object_actions.add_actions (KEY_ENTRIES, this);
118
_object_actions.get_action("key-properties").activate += on_key_properties;
119
_object_actions.get_action("key-export-file").activate += on_key_export_file;
120
_object_actions.get_action("key-export-clipboard").activate += on_key_export_clipboard;
121
_object_actions.get_action("key-delete").activate += on_key_delete;
123
/* Mark the properties toolbar button as important */
124
_object_actions.get_action("key-properties").is_important = true;
126
include_actions (_object_actions);
129
protected void ensure_updated () {
130
_ui_manager.ensure_update ();
133
protected void include_actions (Gtk.ActionGroup actions) {
134
_ui_manager.insert_action_group (actions, -1);
137
public virtual List<weak Object> get_selected_objects () {
138
return new List<weak Object>();
141
public virtual void set_selected_objects (List<Object> objects) {
142
/* Must be overridden */
145
public virtual weak Object? selected {
147
/* Must be overridden */
151
List<weak Object> objects = new List<weak Object>();
152
objects.prepend(value);
153
set_selected_objects (objects);
157
public virtual weak Set? current_set {
159
/* Must be overridden */
164
public virtual weak Object? get_selected_object_and_uid (out uint uid) {
165
/* Must be overridden */
169
public Gtk.Window window {
170
get { return (Gtk.Window)get_toplevel(); }
173
private void on_ui_add_widget (Gtk.UIManager ui, Gtk.Widget widget) {
176
if (widget.get_type () == typeof (Gtk.MenuBar))
177
name = "menu-placeholder";
178
else if (widget.get_type () == typeof (Gtk.Toolbar))
179
name = "toolbar-placeholder";
183
Gtk.Widget holder = get_widget (name);
185
((Gtk.Container)holder).add (widget);
187
warning ("no place holder found for: %s", name);
190
private void on_app_preferences (Action action) {
191
Preferences.show (window, null);
194
private void on_app_about (Action action) {
197
"Jacob Perkins <jap1@users.sourceforge.net>",
198
"Jose Carlos Garcia Sogo <jsogo@users.sourceforge.net>",
199
"Jean Schurger <yshark@schurger.org>",
200
"Stef Walter <stef@memberwebs.com>",
201
"Adam Schreiber <sadam@clemson.edu>",
204
"Albrecht DreĆ <albrecht.dress@arcor.de>",
205
"Jim Pharis <binbrain@gmail.com>"
208
string[] documenters = {
209
"Jacob Perkins <jap1@users.sourceforge.net>",
210
"Adam Schreiber <sadam@clemson.edu>",
211
"Milo Casagrande <milo_casagrande@yahoo.it>"
215
"Jacob Perkins <jap1@users.sourceforge.net>",
216
"Stef Walter <stef@memberwebs.com>"
219
if (!_about_initialized) {
220
_about_initialized = true;
221
Gtk.AboutDialog.set_url_hook (on_about_link_clicked, null);
224
Gtk.AboutDialog about = new Gtk.AboutDialog();
225
about.artists = artists;
226
about.authors = authors;
227
about.documenters = documenters;
228
about.version = Config.VERSION;
229
about.comments = _("Encryption Key Manager");
230
about.copyright = "Copyright \xc2\xa9 2002 - 2008 Seahorse Project";
231
about.translator_credits = _("translator-credits");
232
about.logo_icon_name = "seahorse";
233
about.website = "http://www.gnome.org/projects/seahorse";
234
about.website_label = _("Seahorse Project Homepage");
239
private static void on_about_link_clicked (Gtk.AboutDialog about, string url) {
241
GLib.AppInfo.launch_default_for_uri (url, new GLib.AppLaunchContext ());
242
} catch (GLib.Error ex){
243
warning ("couldn't launch url: %s: %s", url, ex.message);
247
private void on_help_show (Action action) {
251
protected void show_context_menu (uint button, uint time) {
252
Gtk.Menu menu = (Gtk.Menu)_ui_manager.get_widget ("/KeyPopup");
253
return_if_fail (menu != null && menu.get_type() == typeof (Gtk.Menu));
255
menu.popup (null, null, null, button, time);
259
protected void show_properties (Object obj) {
260
var commands = _commands.lookup(obj.tag);
261
if (commands != null)
262
commands.show_properties (obj);
265
private void on_key_properties (Action action) {
266
if (this.selected != null)
267
show_properties (this.selected);
270
private int compare_by_tag (Object one, Object two) {
271
Quark kone = one.tag;
272
Quark ktwo = two.tag;
280
private void delete_object_batch (List<Object> objects) {
281
assert (objects != null);
282
var commands = _commands.lookup(objects.data.tag);
285
if (commands != null)
286
commands.delete_objects (objects);
287
} catch (GLib.Error ex) {
288
Util.handle_error (ex, _("Couldn't delete."), window);
292
private void on_key_delete (Action action) {
293
List<weak Object> objects, batch;
295
/* Get the selected objects and sort them by ktype */
296
objects = get_selected_objects ();
297
objects.sort ((GLib.CompareFunc)compare_by_tag);
299
uint num = objects.length();
303
/* Check for private objects */
304
foreach (var object in objects) {
305
if (object.usage == Usage.PRIVATE_KEY) {
308
prompt = _("%s is a private key. Are you sure you want to proceed?").printf(objects.data.display_name);
310
prompt = _("One or more of the deleted keys are private keys. Are you sure you want to proceed?");
311
if (!Util.prompt_delete (prompt))
317
batch = new List<weak Object>();
318
foreach (Object object in objects) {
320
/* Process that batch */
321
if (ktype != object.tag && batch != null) {
322
delete_object_batch (batch);
323
batch = new List<weak Object>();
326
/* Add to the batch */
327
batch.prepend (object);
330
/* Process last batch */
332
delete_object_batch (batch);
335
private void on_copy_complete (Operation op) {
337
if (!op.is_successful ()) {
338
op.display_error (_("Couldn't retrieve data from key server"), window);
342
GLib.Object result = (GLib.Object)op.get_result ();
343
return_if_fail (result != null && result.get_type () != typeof (MemoryOutputStream));
344
MemoryOutputStream output = (MemoryOutputStream)result;
346
weak string text = (string)output.get_data ();
347
return_if_fail (text != null);
349
uint size = Util.memory_output_length (output);
350
return_if_fail (size >= 0);
352
Gdk.Atom atom = Gdk.Atom.intern ("CLIPBOARD", false);
353
Gtk.Clipboard board = Gtk.Clipboard.get (atom);
354
board.set_text (text, (int)size);
356
set_status (_("Copied keys"));
359
private void on_key_export_clipboard (Action action) {
361
var objects = get_selected_objects ();
365
OutputStream output = new MemoryOutputStream (null, 0, realloc, free);
366
Operation op = Source.export_objects (objects, output);
368
Progress.show (op, _("Retrieving keys"), true);
369
op.watch (on_copy_complete, null);
372
private void on_export_done (Operation op) {
373
if (!op.is_successful ())
374
op.display_error (_("Couldn't export keys"), window);
377
private void on_key_export_file (Action action) {
379
var objects = get_selected_objects ();
383
Gtk.Dialog dialog = Util.chooser_save_new (_("Export public key"), window);
384
Util.chooser_show_key_files (dialog);
385
Util.chooser_set_filename (dialog, objects);
387
string uri = Util.chooser_save_prompt (dialog);
391
var file = File.new_for_uri (uri);
392
OutputStream output = file.replace (null, false, 0, null);
394
Operation op = Source.export_objects (objects, output);
395
Progress.show (op, _("Exporting keys"), true);
396
op.watch (on_export_done, null);
399
Util.handle_error (ex, _("Couldn't export key to \"%s\""),
400
Util.uri_get_last (uri));
407
private void on_selection_changed (View view) {
408
_object_actions.set_sensitive (view.selected != null);
411
protected void set_status (string text) {
412
Gtk.Widget widget = get_widget ("status");
413
return_if_fail (widget != null || widget.get_type() != typeof (Gtk.Statusbar));
415
Gtk.Statusbar status = (Gtk.Statusbar)widget;
416
uint id = status.get_context_id ("key-manager");
418
status.push (id, text);
421
protected void set_numbered_status (string text, int num) {
422
string message = text.printf (num);
423
set_status (message);