diff --git a/src/clipboard.c b/src/clipboard.c index 176811f..12959b9 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -1,1568 +1,1568 @@ /* clipboard.c - The GNU Privacy Assistant Copyright (C) 2000, 2001 G-N-U GmbH. Copyright (C) 2007, 2008 g10 Code GmbH This file is part of GPA. GPA 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 3 of the License, or (at your option) any later version. GPA 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, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include "gpa.h" #include "gtktools.h" #include "gpgmetools.h" #include "gpawidgets.h" #include "siglist.h" #include "helpmenu.h" #include "icons.h" #include "clipboard.h" #include "gpafiledecryptop.h" #include "gpafileencryptop.h" #include "gpafilesignop.h" #include "gpafileverifyop.h" #include "icons.h" #include "helpmenu.h" /* Support for Gtk 2.8. */ #if ! GTK_CHECK_VERSION (2, 10, 0) #define gtk_text_buffer_get_has_selection(textbuf) \ gtk_text_buffer_get_selection_bounds (textbuf, NULL, NULL); #define gdk_atom_intern_static_string(str) gdk_atom_intern (str, FALSE) #define GTK_STOCK_SELECT_ALL "gtk-select-all" #define MY_GTK_TEXT_BUFFER_NO_HAS_SELECTION #endif /* FIXME: Move to a global file. */ #ifndef DIM #define DIM(array) (sizeof (array) / sizeof (*array)) #endif /* Object and class definition. */ struct _GpaClipboard { GtkWindow parent; GtkWidget *text_view; GtkTextBuffer *text_buffer; /* List of sensitive widgets. See below */ GList *selection_sensitive_actions; GList *paste_sensitive_actions; gboolean paste_p; }; struct _GpaClipboardClass { GtkWindowClass parent_class; }; /* There is only one instance of the clipboard class. Use a global variable to keep track of it. */ static GpaClipboard *instance; /* We also need to save the parent class. */ static GObjectClass *parent_class; /* Local prototypes */ static GObject *gpa_clipboard_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties); /* GtkWidget boilerplate. */ static void gpa_clipboard_finalize (GObject *object) { G_OBJECT_CLASS (parent_class)->finalize (object); } static void gpa_clipboard_init (GpaClipboard *clipboard) { clipboard->selection_sensitive_actions = NULL; clipboard->paste_sensitive_actions = NULL; } static void gpa_clipboard_class_init (GpaClipboardClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->constructor = gpa_clipboard_constructor; object_class->finalize = gpa_clipboard_finalize; } GType gpa_clipboard_get_type (void) { static GType clipboard_type = 0; if (!clipboard_type) { static const GTypeInfo clipboard_info = { sizeof (GpaClipboardClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gpa_clipboard_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GpaClipboard), 0, /* n_preallocs */ (GInstanceInitFunc) gpa_clipboard_init, }; clipboard_type = g_type_register_static (GTK_TYPE_WINDOW, "GpaClipboard", &clipboard_info, 0); } return clipboard_type; } /* Definition of the sensitivity function type. */ typedef gboolean (*sensitivity_func_t)(gpointer); /* Add widget to the list of sensitive widgets of editor. */ static void add_selection_sensitive_action (GpaClipboard *clipboard, GSimpleAction *action) { clipboard->selection_sensitive_actions = g_list_append (clipboard->selection_sensitive_actions, action); } /* Return true if a selection is active. */ static gboolean has_selection (gpointer param) { GpaClipboard *clipboard = param; return gtk_text_buffer_get_has_selection (clipboard->text_buffer); } /* Update the sensitivity of the widget DATA and pass PARAM through to the sensitivity callback. Usable as an iterator function in g_list_foreach. */ static void update_selection_sensitive_action (gpointer data, gpointer param) { // gtk_action_set_sensitive (GTK_ACTION (data), has_selection (param)); g_simple_action_set_enabled (G_SIMPLE_ACTION (data), has_selection (param)); } /* Call update_selection_sensitive_widget for all widgets in the list of sensitive widgets and pass CLIPBOARD through as the user data parameter. */ static void update_selection_sensitive_actions (GpaClipboard *clipboard) { g_list_foreach (clipboard->selection_sensitive_actions, update_selection_sensitive_action, (gpointer) clipboard); } /* Add ACTION to the list of sensitive actions of CLIPBOARD. */ static void add_paste_sensitive_action (GpaClipboard *clipboard, GSimpleAction *action) { clipboard->paste_sensitive_actions = g_list_append (clipboard->paste_sensitive_actions, action); } static void update_paste_sensitive_action (gpointer data, gpointer param) { GpaClipboard *clipboard = param; // gtk_action_set_sensitive (GTK_ACTION (data), clipboard->paste_p); g_simple_action_set_enabled (G_SIMPLE_ACTION (data), clipboard->paste_p); } static void update_paste_sensitive_actions (GtkClipboard *clip, GtkSelectionData *selection_data, GpaClipboard *clipboard) { clipboard->paste_p = gtk_selection_data_targets_include_text (selection_data); g_list_foreach (clipboard->paste_sensitive_actions, update_paste_sensitive_action, (gpointer) clipboard); } static void set_paste_sensitivity (GpaClipboard *clipboard, GtkClipboard *clip) { GdkDisplay *display; display = gtk_clipboard_get_display (clip); if (gdk_display_supports_selection_notification (display)) gtk_clipboard_request_contents (clip, gdk_atom_intern_static_string ("TARGETS"), (GtkClipboardReceivedFunc) update_paste_sensitive_actions, clipboard); } static void clipboard_owner_change_cb (GtkClipboard *clip, GdkEventOwnerChange *event, GpaClipboard *clipboard) { set_paste_sensitivity (clipboard, clip); } /* Add a file created by an operation to the list */ static void file_created_cb (GpaFileOperation *op, gpa_file_item_t item, gpointer data) { GpaClipboard *clipboard = data; gboolean suc; const gchar *end; suc = g_utf8_validate (item->direct_out, item->direct_out_len, &end); if (! suc) { gchar *str; gsize len; str = g_strdup_printf ("No valid UTF-8 encoding at position %i.\n" "Assuming Latin-1 encoding instead.", ((int) (end - item->direct_out))); gpa_window_message (str, GTK_WIDGET (clipboard)); g_free (str); str = g_convert (item->direct_out, item->direct_out_len, "UTF-8", "ISO-8859-1", NULL, &len, NULL); if (str) { gtk_text_buffer_set_text (clipboard->text_buffer, str, len); g_free (str); return; } gpa_window_error ("Error converting Latin-1 to UTF-8", GTK_WIDGET (clipboard)); /* Enough warnings: Try to show even with invalid encoding. */ } gtk_text_buffer_set_text (clipboard->text_buffer, item->direct_out, item->direct_out_len); } /* Do whatever is required with a file operation, to ensure proper clean up */ static void register_operation (GpaClipboard *clipboard, GpaFileOperation *op) { g_signal_connect (G_OBJECT (op), "created_file", G_CALLBACK (file_created_cb), clipboard); g_signal_connect (G_OBJECT (op), "completed", G_CALLBACK (g_object_unref), NULL); } /* Actions as called by the menu items. */ /* Handle menu item "File/Clear". */ static void file_clear (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = param; gtk_text_buffer_set_text (clipboard->text_buffer, "", -1); } /* The directory last visited by load or save operations. */ static gchar *last_directory; static gchar * get_load_file_name (GtkWidget *parent, const gchar *title) { static GtkWidget *dialog; GtkResponseType response; gchar *filename = NULL; if (! dialog) { dialog = gtk_file_chooser_dialog_new (title, GTK_WINDOW (parent), GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Open"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); } if (last_directory) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), last_directory); gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (dialog)); /* Run the dialog until there is a valid response. */ response = gtk_dialog_run (GTK_DIALOG (dialog)); if (response == GTK_RESPONSE_OK) { filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); if (filename) filename = g_strdup (filename); } if (last_directory) g_free (last_directory); last_directory = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); if (last_directory) last_directory = g_strdup (last_directory); gtk_widget_hide (dialog); return filename; } /* Handle menu item "File/Open". */ static void file_open (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = param; gchar *filename; struct stat buf; int res; gboolean suc; gchar *contents; gsize length; GError *err = NULL; const gchar *end; filename = get_load_file_name (GTK_WIDGET (clipboard), _("Open File")); if (! filename) return; res = g_stat (filename, &buf); if (res < 0) { gchar *str; str = g_strdup_printf ("Error determining size of file %s:\n%s", filename, strerror (errno)); gpa_window_error (str, GTK_WIDGET (clipboard)); g_free (str); g_free (filename); return; } #define MAX_CLIPBOARD_SIZE (2*1024*1024) if (buf.st_size > MAX_CLIPBOARD_SIZE) { GtkWidget *window; GtkWidget *hbox; GtkWidget *labelMessage; GtkWidget *pixmap; gint result; gchar *str; window = gtk_dialog_new_with_buttons (_("GPA Message"), GTK_WINDOW (clipboard), GTK_DIALOG_MODAL, _("_Open"), GTK_RESPONSE_OK, _("_Cancel"), GTK_RESPONSE_CANCEL, NULL); gtk_container_set_border_width (GTK_CONTAINER (window), 5); gtk_dialog_set_default_response (GTK_DIALOG (window), GTK_RESPONSE_CANCEL); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); //gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (window)->vbox), hbox); GtkWidget *box = gtk_dialog_get_content_area (GTK_DIALOG (window)); gtk_box_pack_start( GTK_BOX (box), hbox, TRUE, TRUE, 0); pixmap = gtk_image_new_from_icon_name ("dialog-information", GTK_ICON_SIZE_DIALOG); gtk_box_pack_start (GTK_BOX (hbox), pixmap, TRUE, FALSE, 10); /* TRANSLATORS: The arguments are the filename, the integer size and the unit (such as KB or MB). */ str = g_strdup_printf (_("The file %s is %llu%s large. Do you really " " want to open it?"), filename, (unsigned long long)buf.st_size / 1024 / 1024, "MB"); labelMessage = gtk_label_new (str); g_free (str); gtk_label_set_line_wrap (GTK_LABEL (labelMessage), TRUE); gtk_box_pack_start (GTK_BOX (hbox), labelMessage, TRUE, FALSE, 10); gtk_widget_show_all (window); result = gtk_dialog_run (GTK_DIALOG (window)); gtk_widget_destroy (window); if (result != GTK_RESPONSE_OK) { g_free (filename); return; } } suc = g_file_get_contents (filename, &contents, &length, &err); if (! suc) { gchar *str; str = g_strdup_printf ("Error loading content of file %s:\n%s", filename, err->message); gpa_window_error (str, GTK_WIDGET (clipboard)); g_free (str); g_error_free (err); g_free (filename); return; } suc = g_utf8_validate (contents, length, &end); if (! suc) { gchar *str; str = g_strdup_printf ("Error opening file %s:\n" "No valid UTF-8 at position %i.", filename, ((int) (end - contents))); gpa_window_error (str, GTK_WIDGET (clipboard)); g_free (str); g_free (contents); g_free (filename); return; } gtk_text_buffer_set_text (clipboard->text_buffer, contents, length); g_free (contents); } /* Run the modal file selection dialog and return a new copy of the filename if the user pressed OK and NULL otherwise. */ static gchar * get_save_file_name (GtkWidget *parent, const gchar *title) { static GtkWidget *dialog; GtkResponseType response; gchar *filename = NULL; if (! dialog) { dialog = gtk_file_chooser_dialog_new (title, GTK_WINDOW (parent), GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL); + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Save"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); } if (last_directory) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), last_directory); gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (dialog)); /* Run the dialog until there is a valid response. */ response = gtk_dialog_run (GTK_DIALOG (dialog)); if (response == GTK_RESPONSE_OK) { filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); if (filename) filename = g_strdup (filename); } if (last_directory) g_free (last_directory); last_directory = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); if (last_directory) last_directory = g_strdup (last_directory); if (last_directory) g_free (last_directory); last_directory = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); if (last_directory) last_directory = g_strdup (last_directory); gtk_widget_hide (dialog); return filename; } /* Handle menu item "File/Save As...". */ static void file_save_as (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = param; gchar *filename; GError *err = NULL; gchar *contents; gssize length; gboolean suc; GtkTextIter begin; GtkTextIter end; filename = get_save_file_name (GTK_WIDGET (clipboard), _("Save As...")); if (! filename) return; gtk_text_buffer_get_bounds (clipboard->text_buffer, &begin, &end); contents = gtk_text_buffer_get_text (clipboard->text_buffer, &begin, &end, FALSE); length = strlen (contents); suc = g_file_set_contents (filename, contents, length, &err); g_free (contents); if (! suc) { gchar *str; str = g_strdup_printf ("Error saving content to file %s:\n%s", filename, err->message); gpa_window_error (str, GTK_WIDGET (clipboard)); g_free (str); g_error_free (err); g_free (filename); return; } g_free (filename); } /* Handle menu item "File/Verify". */ static void file_verify (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = (GpaClipboard *) param; GpaFileVerifyOperation *op; GList *files = NULL; gpa_file_item_t file_item; GtkTextIter begin; GtkTextIter end; gtk_text_buffer_get_bounds (clipboard->text_buffer, &begin, &end); file_item = g_malloc0 (sizeof (*file_item)); file_item->direct_name = g_strdup (_("Clipboard")); file_item->direct_in = gtk_text_buffer_get_slice (clipboard->text_buffer, &begin, &end, TRUE); /* FIXME: One would think there exists a function to get the number of bytes between two GtkTextIter, but no, that's too obvious. */ file_item->direct_in_len = strlen (file_item->direct_in); files = g_list_append (files, file_item); /* Start the operation. */ op = gpa_file_verify_operation_new (GTK_WIDGET (clipboard), files); register_operation (clipboard, GPA_FILE_OPERATION (op)); } /* Handle menu item "File/Sign". */ static void file_sign (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = (GpaClipboard *) param; GpaFileSignOperation *op; GList *files = NULL; gpa_file_item_t file_item; GtkTextIter begin; GtkTextIter end; gtk_text_buffer_get_bounds (clipboard->text_buffer, &begin, &end); file_item = g_malloc0 (sizeof (*file_item)); file_item->direct_name = g_strdup (_("Clipboard")); file_item->direct_in = gtk_text_buffer_get_text (clipboard->text_buffer, &begin, &end, FALSE); /* FIXME: One would think there exists a function to get the number of bytes between two GtkTextIter, but no, that's too obvious. */ file_item->direct_in_len = strlen (file_item->direct_in); files = g_list_append (files, file_item); /* Start the operation. */ op = gpa_file_sign_operation_new (GTK_WIDGET (clipboard), files, TRUE); register_operation (clipboard, GPA_FILE_OPERATION (op)); } /* Handle menu item "File/Encrypt". */ static void file_encrypt (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = (GpaClipboard *) param; GpaFileEncryptOperation *op; GList *files = NULL; gpa_file_item_t file_item; GtkTextIter begin; GtkTextIter end; gtk_text_buffer_get_bounds (clipboard->text_buffer, &begin, &end); file_item = g_malloc0 (sizeof (*file_item)); file_item->direct_name = g_strdup (_("Clipboard")); file_item->direct_in = gtk_text_buffer_get_text (clipboard->text_buffer, &begin, &end, FALSE); /* FIXME: One would think there exists a function to get the number of bytes between two GtkTextIter, but no, that's too obvious. */ file_item->direct_in_len = strlen (file_item->direct_in); files = g_list_append (files, file_item); /* Start the operation. */ op = gpa_file_encrypt_operation_new (GTK_WIDGET (clipboard), files, TRUE); register_operation (clipboard, GPA_FILE_OPERATION (op)); } /* Handle menu item "File/Decrypt". */ static void file_decrypt (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = (GpaClipboard *) param; GpaFileDecryptOperation *op; GList *files = NULL; gpa_file_item_t file_item; GtkTextIter begin; GtkTextIter end; gtk_text_buffer_get_bounds (clipboard->text_buffer, &begin, &end); file_item = g_malloc0 (sizeof (*file_item)); file_item->direct_name = g_strdup (_("Clipboard")); file_item->direct_in = gtk_text_buffer_get_text (clipboard->text_buffer, &begin, &end, FALSE); /* FIXME: One would think there exists a function to get the number of bytes between two GtkTextIter, but no, that's too obvious. */ file_item->direct_in_len = strlen (file_item->direct_in); files = g_list_append (files, file_item); /* Start the operation. */ op = gpa_file_decrypt_operation_new (GTK_WIDGET (clipboard), files); register_operation (clipboard, GPA_FILE_OPERATION (op)); } /* Handle menu item "File/Close". */ static void file_close (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = param; gtk_widget_destroy (GTK_WIDGET (clipboard)); } /* Handle menu item "File/Quit". */ static void file_quit (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = param; gtk_widget_destroy (GTK_WIDGET (clipboard)); } static void edit_cut (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = param; g_signal_emit_by_name (GTK_TEXT_VIEW (clipboard->text_view), "cut-clipboard"); } static void edit_copy (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = param; g_signal_emit_by_name (GTK_TEXT_VIEW (clipboard->text_view), "copy-clipboard"); } static void edit_paste (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = param; g_signal_emit_by_name (GTK_TEXT_VIEW (clipboard->text_view), "paste-clipboard"); } static void edit_delete (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = param; g_signal_emit_by_name (GTK_TEXT_VIEW (clipboard->text_view), "backspace"); } /* Handle menu item "Edit/Select All". */ static void edit_select_all (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaClipboard *clipboard = param; g_signal_emit_by_name (GTK_TEXT_VIEW (clipboard->text_view), "select-all"); } /* Construct the file manager menu window and return that object. */ static void clipboard_action_new (GpaClipboard *clipboard, GtkWidget **menu, GtkWidget **toolbar) { static const GActionEntry g_entries[] = { { "File", NULL }, { "Edit", NULL }, { "file_clear", file_clear }, { "file_open", file_open }, { "file_save_as", file_save_as }, { "file_sign", file_sign }, { "file_verify", file_verify }, { "file_encrypt", file_encrypt }, { "file_decrypt", file_decrypt }, { "file_close", file_close }, { "file_quit", file_quit }, #if g { "edit_undo", edit_undo }, { "edit_redo", edit_redo }, #endif { "edit_cut", edit_cut }, { "edit_copy", edit_copy }, { "edit_paste", edit_paste }, { "edit_delete", edit_delete }, { "edit_select_all", edit_select_all }, }; /* static const GtkActionEntry entries[] = { // Toplevel { "File", NULL, N_("_File"), NULL }, { "Edit", NULL, N_("_Edit"), NULL }, // File menu. { "FileClear", GTK_STOCK_CLEAR, NULL, NULL, N_("Clear buffer"), G_CALLBACK (file_clear) }, - { "FileOpen", GTK_STOCK_OPEN, NULL, NULL, + { "FileOpen", _("_Open"), NULL, NULL, N_("Open a file"), G_CALLBACK (file_open) }, - { "FileSaveAs", GTK_STOCK_SAVE_AS, NULL, NULL, + { "FileSaveAs", _("_Save")_AS, NULL, NULL, N_("Save to a file"), G_CALLBACK (file_save_as) }, { "FileSign", GPA_STOCK_SIGN, NULL, NULL, N_("Sign buffer text"), G_CALLBACK (file_sign) }, { "FileVerify", GPA_STOCK_VERIFY, NULL, NULL, N_("Check signatures of buffer text"), G_CALLBACK (file_verify) }, { "FileEncrypt", GPA_STOCK_ENCRYPT, NULL, NULL, N_("Encrypt the buffer text"), G_CALLBACK (file_encrypt) }, { "FileDecrypt", GPA_STOCK_DECRYPT, NULL, NULL, N_("Decrypt the buffer text"), G_CALLBACK (file_decrypt) }, - { "FileClose", GTK_STOCK_CLOSE, NULL, NULL, + { "FileClose", _("_Close"), NULL, NULL, N_("Close the buffer"), G_CALLBACK (file_close) }, { "FileQuit", GTK_STOCK_QUIT, NULL, NULL, N_("Quit the program"), G_CALLBACK (g_application_quit) }, // Edit menu. #if 0 // FIXME: Not implemented yet. { "EditUndo", GTK_STOCK_UNDO, NULL, NULL, N_("Undo the last action"), G_CALLBACK (edit_undo) }, { "EditRedo", GTK_STOCK_REDO, NULL, NULL, N_("Redo the last undone action"), G_CALLBACK (edit_redo) }, #endif { "EditCut", GTK_STOCK_CUT, NULL, NULL, N_("Cut the selection"), G_CALLBACK (edit_cut) }, { "EditCopy", GTK_STOCK_COPY, NULL, NULL, N_("Copy the selection"), G_CALLBACK (edit_copy) }, { "EditPaste", GTK_STOCK_PASTE, NULL, NULL, N_("Paste the clipboard"), G_CALLBACK (edit_paste) }, { "EditDelete", GTK_STOCK_DELETE, NULL, NULL, N_("Delete the selected text"), G_CALLBACK (edit_delete) }, { "EditSelectAll", GTK_STOCK_SELECT_ALL, NULL, "A", N_("Select the entire document"), G_CALLBACK (edit_select_all) } }; */ static const char *ui_string = "" "" "" "_File" "" "Clear" "app.file_cleear" "" "" "Open" "app.file_open" "" "
" "" "Sign" "app.file_sign" "" "" "Verify" "app.file_verify" "" "" "Encrypt" "app.file_encrypt" "" "" "Decrypt" "app.file_decrypt" "" "
" "
" "" "Close" "app.file_close" "" "" "Quit" "app.file_quit" "" "
" "
" "" "Edit" "" "Cut" "app.edit_cut" "" "" "Copy" "app.edit_copy" "" "" "Copy" "app.edit_paste" "" "" "Delete" "app.edit_delete" "" "
" "" "Select All" "app.edit_select_all" "" "
" "
" "" "Preferences" "app.edit_preferences" "" "" "Backend Preferences" "app.edit_backend_preferences" "" "
" "
" "" "Windows" "" "Keyring Manager" "app.windows_keyring_editor" "" "" "File Manager" "app.windows_file_manager" "" "" "Clipboard" "app.windows_clipboard" "" "" "Card Manager" "app.windows_card_manager" "" "" "" "Help" "" "About" "app.help_about" "" "" "
" "" "True" "False" "False" "" "" "True" "False" "True" "app.file_clear" "edit-clear" "true" "Clear buffer" "" "" "False" "True" "" "" "" "" "" "" "" "" "True" "False" "True" "app.edit_cut" "edit-cut" "true" "Cut the selection" "" "" "False" "True" "" "" "" "" "True" "False" "True" "app.edit_copy" "edit-copy" "true" "Copy the selection" "" "" "False" "True" "" "" "" "" "True" "False" "True" "app.edit_paste" "edit-paste" "true" "Paste the clipboard" "" "" "False" "True" "" "" "" "" "" "" "" "" "True" "False" "True" "app.file_sign" "sign" "true" "Sign buffer text" "" "" "False" "True" "" "" "" "" "True" "False" "verify" "True" "app.file_verify" "true" "Check signatures of buffer text" "" "" "False" "True" "" "" "" "" "True" "False" "True" "encrypt" "app.file_encrypt" "true" "Encrypt the buffer text" "" "" "False" "True" "" "" "" "" "True" "False" "True" "decrypt" "app.file_decrypt" "true" "Decrypt the buffer text" "" "" "False" "True" "" "" "" "" "" "" "" "" "True" "False" "True" "preferences-desktop" "app.edit_preferences" "true" "Configure the application" "" "" "False" "True" "" "" "" "" "" "" "" "" "True" "False" "True" "keyring" "app.windows_keyring_editor" "true" "Open the keyring editor" "" "" "False" "True" "" "" "" "" "True" "False" "__glade_unnamed_10" "True" "folder" "app.windows_file_manager" "true" "Open the file manager" "" "" "False" "True" "" "" #ifdef ENABLE_CARD_MANAGER "" "" "True" "False" "__glade_unnamed_10" "True" "smartcard" "app.windows_card_manager" "true" "Open the card manager" "" "" "False" "True" "" "" #endif "" "
"; /* static const char *ui_description = "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " #if 0 // Not implemented yet. " " " " " " #endif " " " " " " " " " " " " " " " " " " " " " " " " " " " " #ifdef ENABLE_CARD_MANAGER " " #endif " " " " #if 0 " " #endif " " " " " " " " " " #if 0 // Disabled because the toolbar arrow mode doesn't work, and the // toolbar takes up too much space otherwise. " " " " #endif " " " " " " " " " " " " " " " " " " " " " " " " " " " " #ifdef ENABLE_CARD_MANAGER " " #endif #if 0 " " #endif " " ""; */ #ifdef OLD_MENU GtkAccelGroup *accel_group; GtkActionGroup *action_group; GtkAction *action; GtkUIManager *ui_manager; GError *error; action_group = gtk_action_group_new ("MenuActions"); gtk_action_group_set_translation_domain (action_group, PACKAGE); gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), clipboard); gtk_action_group_add_actions (action_group, gpa_help_menu_action_entries, G_N_ELEMENTS (gpa_help_menu_action_entries), clipboard); gtk_action_group_add_actions (action_group, gpa_windows_menu_action_entries, G_N_ELEMENTS (gpa_windows_menu_action_entries), clipboard); gtk_action_group_add_actions (action_group, gpa_preferences_menu_action_entries, G_N_ELEMENTS (gpa_preferences_menu_action_entries), clipboard); ui_manager = gtk_ui_manager_new (); gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); accel_group = gtk_ui_manager_get_accel_group (ui_manager); gtk_window_add_accel_group (GTK_WINDOW (clipboard), accel_group); if (! gtk_ui_manager_add_ui_from_string (ui_manager, ui_description, -1, &error)) { g_message ("building clipboard menus failed: %s", error->message); g_error_free (error); exit (EXIT_FAILURE); } /* Fixup the icon theme labels which are too long for the toolbar. */ action = gtk_action_group_get_action (action_group, "WindowsKeyringEditor"); g_object_set (action, "short_label", _("Keyring"), NULL); action = gtk_action_group_get_action (action_group, "WindowsFileManager"); g_object_set (action, "short_label", _("Files"), NULL); #ifdef ENABLE_CARD_MANAGER action = gtk_action_group_get_action (action_group, "WindowsCardManager"); g_object_set (action, "short_label", _("Card"), NULL); #endif /* Take care of sensitiveness of widgets. */ action = gtk_action_group_get_action (action_group, "EditCut"); add_selection_sensitive_action (clipboard, action); action = gtk_action_group_get_action (action_group, "EditCopy"); add_selection_sensitive_action (clipboard, action); action = gtk_action_group_get_action (action_group, "EditDelete"); add_selection_sensitive_action (clipboard, action); action = gtk_action_group_get_action (action_group, "EditPaste"); /* Initialized later. */ add_paste_sensitive_action (clipboard, action); *menu = gtk_ui_manager_get_widget (ui_manager, "/MainMenu"); *toolbar = gtk_ui_manager_get_widget (ui_manager, "/ToolBar"); gpa_toolbar_set_homogeneous (GTK_TOOLBAR (*toolbar), FALSE); #else GError *err = NULL; GtkBuilder *gtk_builder = gtk_builder_new_from_string (icons_string, -1); if (gtk_builder_add_from_string( gtk_builder, ui_string , -1, &err) == 0) { printf("ERROR: %s \n", err->message); } GMenuModel *menu_bar_model = G_MENU_MODEL (gtk_builder_get_object (GTK_BUILDER (gtk_builder), "menu")); *menu = gtk_menu_bar_new_from_model (menu_bar_model); GObject *grid = gtk_builder_get_object (GTK_BUILDER (gtk_builder), "toolbar"); GtkCssProvider *css_provider = gtk_css_provider_new(); GdkDisplay *display = gdk_display_get_default(); GdkScreen *screen = gdk_display_get_default_screen (display); gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER(css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER); gtk_css_provider_load_from_data(css_provider, "#toolbar {\n" //" padding-left: 55px;\n" // " padding-right: 5px;\n" // " border-radius: 3px;\n" "}\n", -1, NULL); GtkStyleContext *style_context; style_context = gtk_widget_get_style_context (GTK_WIDGET (grid)); *toolbar = GTK_WIDGET (grid); // We must set the name to the toolbar for css to recognize it gtk_widget_set_name(*toolbar, "toolbar"); gtk_style_context_add_class (style_context, "toolbar"); GtkApplication *gpa_app = get_gpa_application (); g_action_map_add_action_entries (G_ACTION_MAP (gpa_app), gpa_windows_menu_g_action_entries, G_N_ELEMENTS (gpa_windows_menu_g_action_entries), clipboard); g_action_map_add_action_entries (G_ACTION_MAP (gpa_app), g_entries, G_N_ELEMENTS (g_entries), clipboard); g_action_map_add_action_entries (G_ACTION_MAP (gpa_app), gpa_help_menu_g_action_entries, G_N_ELEMENTS (gpa_help_menu_g_action_entries), clipboard); g_action_map_add_action_entries (G_ACTION_MAP (gpa_app), gpa_preferences_menu_g_action_entries, G_N_ELEMENTS (gpa_preferences_menu_g_action_entries), clipboard); GSimpleAction *action; action = (GSimpleAction*)g_action_map_lookup_action (G_ACTION_MAP (gpa_app), "edit_cut"); add_selection_sensitive_action (clipboard, action); action = (GSimpleAction*)g_action_map_lookup_action (G_ACTION_MAP (gpa_app), "edit_copy"); add_selection_sensitive_action (clipboard, action); action = (GSimpleAction*)g_action_map_lookup_action (G_ACTION_MAP (gpa_app), "edit_delete"); add_selection_sensitive_action (clipboard, action); action = (GSimpleAction*)g_action_map_lookup_action (G_ACTION_MAP (gpa_app), "edit_paste"); // Initialized later add_paste_sensitive_action (clipboard, action); #endif } /* Callback for the destroy signal. */ static void clipboard_closed (GtkWidget *widget, gpointer param) { instance = NULL; } /* Construct the clipboard text. */ static GtkWidget * clipboard_text_new (GpaClipboard *clipboard) { GtkWidget *scroller; clipboard->text_view = gtk_text_view_new (); gtk_widget_grab_focus (clipboard->text_view); gtk_text_view_set_left_margin (GTK_TEXT_VIEW (clipboard->text_view), 4); gtk_text_view_set_right_margin (GTK_TEXT_VIEW (clipboard->text_view), 4); clipboard->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (clipboard->text_view)); #ifndef MY_GTK_TEXT_BUFFER_NO_HAS_SELECTION /* A change in selection status causes a property change, which we can listen in on. */ g_signal_connect_swapped (clipboard->text_buffer, "notify::has-selection", G_CALLBACK (update_selection_sensitive_actions), clipboard); #else /* Runs very often. The changed signal is necessary for backspace actions. */ g_signal_connect_swapped (clipboard->text_buffer, "mark-set", G_CALLBACK (update_selection_sensitive_actions), clipboard); g_signal_connect_after (clipboard->text_buffer, "backspace", G_CALLBACK (update_selection_sensitive_actions), clipboard); #endif scroller = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroller), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroller), GTK_SHADOW_IN); gtk_container_add (GTK_CONTAINER (scroller), clipboard->text_view); return scroller; } /* Construct a new class object of GpaClipboard. */ static GObject * gpa_clipboard_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *object; GpaClipboard *clipboard; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *icon; GtkWidget *label; gchar *markup; GtkWidget *menubar; GtkWidget *text_box; GtkWidget *text_frame; GtkWidget *toolbar; GtkWidget *align; guint pt, pb, pl, pr; /* Invoke parent's constructor. */ object = parent_class->constructor (type, n_construct_properties, construct_properties); clipboard = GPA_CLIPBOARD (object); /* Initialize. */ gpa_window_set_title (GTK_WINDOW (clipboard), _("Clipboard")); gtk_window_set_default_size (GTK_WINDOW (clipboard), 640, 480); /* Realize the window so that we can create pixmaps without warnings and also access the clipboard. */ gtk_widget_realize (GTK_WIDGET (clipboard)); /* Use a vbox to show the menu, toolbar and the text container. */ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); /* We need to create the text_buffer before we create the menus and the toolbar, because of widget sensitivity issues, which depend on the selection status of the text_buffer. */ text_frame = clipboard_text_new (clipboard); /* Get the menu and the toolbar. */ clipboard_action_new (clipboard, &menubar, &toolbar); gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0); /* Add a fancy label that tells us: This is the clipboard. */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5); /* FIXME: Need better icon. */ icon = gtk_image_new_from_icon_name ("edit-paste", GTK_ICON_SIZE_DND); gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, TRUE, 0); label = gtk_label_new (NULL); markup = g_strdup_printf ("%s", _("Clipboard")); gtk_label_set_markup (GTK_LABEL (label), markup); g_free (markup); gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 10); gtk_widget_set_halign (GTK_WIDGET (label), GTK_ALIGN_START); gtk_widget_set_valign (GTK_WIDGET (label), GTK_ALIGN_CENTER); /* Third a text entry. */ text_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); align = gtk_alignment_new (0.5, 0.5, 1, 1); gtk_alignment_get_padding (GTK_ALIGNMENT (align), &pt, &pb, &pl, &pr); gtk_alignment_set_padding (GTK_ALIGNMENT (align), pt, pb + 5, pl + 5, pr + 5); gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (text_box), text_frame, TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER (align), text_box); gtk_container_add (GTK_CONTAINER (clipboard), vbox); g_signal_connect (object, "destroy", G_CALLBACK (clipboard_closed), object); /* Update the sensitivity of paste items. */ { GtkClipboard *clip; /* Do this once for all paste sensitive items. Note that the window is realized already. */ clip = gtk_widget_get_clipboard (GTK_WIDGET (clipboard), GDK_SELECTION_CLIPBOARD); g_signal_connect (clip, "owner_change", G_CALLBACK (clipboard_owner_change_cb), clipboard); set_paste_sensitivity (clipboard, clip); } /* Update the sensitivity of selection items. */ update_selection_sensitive_actions (clipboard); return object; } static GpaClipboard * gpa_clipboard_new () { GpaClipboard *clipboard; clipboard = g_object_new (GPA_CLIPBOARD_TYPE, NULL); return clipboard; } /* API */ GtkWidget * gpa_clipboard_get_instance (void) { if (! instance) instance = gpa_clipboard_new (); return GTK_WIDGET (instance); } gboolean gpa_clipboard_is_open (void) { return (instance != NULL); } diff --git a/src/encryptdlg.c b/src/encryptdlg.c index 6b13fb6..d18050b 100644 --- a/src/encryptdlg.c +++ b/src/encryptdlg.c @@ -1,398 +1,398 @@ /* encryptdlg.c - The GNU Privacy Assistant * Copyright (C) 2000, 2001 G-N-U GmbH. * Copyright (C) 2002, 2003 Miguel Coca. * Copyright (C) 2008 g10 Code GmbH. * * This file is part of GPA * * GPA 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. * * GPA 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include #include #include #include "gpa.h" #include "gtktools.h" #include "gpawidgets.h" #include "gpakeyselector.h" #include "encryptdlg.h" /* Internal functions */ static void changed_select_row_cb (GtkTreeSelection *treeselection, gpointer user_data); static void toggle_sign_cb (GtkToggleButton *togglebutton, gpointer user_data); /* Properties */ enum { PROP_0, PROP_WINDOW, PROP_FORCE_ARMOR, PROP_ARMOR, PROP_SIGN }; static GObjectClass *parent_class = NULL; static void gpa_file_encrypt_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GpaFileEncryptDialog *dialog = GPA_FILE_ENCRYPT_DIALOG (object); switch (prop_id) { case PROP_WINDOW: g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (dialog))); break; case PROP_FORCE_ARMOR: g_value_set_boolean (value, dialog->force_armor); break; case PROP_ARMOR: g_value_set_boolean (value, gpa_file_encrypt_dialog_get_armor (dialog)); break; case PROP_SIGN: g_value_set_boolean (value, gpa_file_encrypt_dialog_get_sign (dialog)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gpa_file_encrypt_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GpaFileEncryptDialog *dialog = GPA_FILE_ENCRYPT_DIALOG (object); switch (prop_id) { case PROP_WINDOW: gtk_window_set_transient_for (GTK_WINDOW (dialog), g_value_get_object (value)); break; case PROP_FORCE_ARMOR: dialog->force_armor = g_value_get_boolean (value); break; case PROP_ARMOR: gpa_file_encrypt_dialog_set_armor (dialog, g_value_get_boolean (value)); break; case PROP_SIGN: gpa_file_encrypt_dialog_set_sign (dialog, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gpa_file_encrypt_dialog_finalize (GObject *object) { G_OBJECT_CLASS (parent_class)->finalize (object); } static void gpa_file_encrypt_dialog_init (GpaFileEncryptDialog *dialog) { } static GObject* gpa_file_encrypt_dialog_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *object; GpaFileEncryptDialog *dialog; GtkWidget *vboxEncrypt; GtkWidget *labelKeys; GtkWidget *scrollerKeys; GtkWidget *clistKeys; GtkWidget *checkerSign; GtkWidget *checkerArmor; GtkWidget *labelWho; GtkWidget *scrollerWho; GtkWidget *clistWho; /* Invoke parent's constructor */ object = parent_class->constructor (type, n_construct_properties, construct_properties); dialog = GPA_FILE_ENCRYPT_DIALOG (object); /* Initialize */ /* Set up the dialog */ gpa_window_set_title (GTK_WINDOW (dialog), _("Encrypt documents")); gtk_dialog_add_buttons (GTK_DIALOG (dialog), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_OK"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE); gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); //vboxEncrypt = GTK_DIALOG (dialog)->vbox; vboxEncrypt = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); gtk_container_set_border_width (GTK_CONTAINER (vboxEncrypt), 5); labelKeys = gtk_label_new_with_mnemonic (_("_Public Keys")); gtk_widget_set_halign (GTK_WIDGET (labelKeys), GTK_ALIGN_START); gtk_widget_set_valign (GTK_WIDGET (labelKeys), GTK_ALIGN_CENTER); gtk_box_pack_start (GTK_BOX (vboxEncrypt), labelKeys, FALSE, FALSE, 0); scrollerKeys = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollerKeys), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (vboxEncrypt), scrollerKeys, TRUE, TRUE, 0); gtk_widget_set_size_request (scrollerKeys, 400, 200); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollerKeys), GTK_SHADOW_IN); clistKeys = gpa_key_selector_new (FALSE, TRUE); g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (clistKeys))), "changed", G_CALLBACK (changed_select_row_cb), dialog); dialog->clist_keys = clistKeys; gtk_container_add (GTK_CONTAINER (scrollerKeys), clistKeys); gtk_label_set_mnemonic_widget (GTK_LABEL (labelKeys), clistKeys); checkerSign = gtk_check_button_new_with_mnemonic (_("_Sign")); gtk_box_pack_start (GTK_BOX (vboxEncrypt), checkerSign, FALSE, FALSE, 0); dialog->check_sign = checkerSign; g_signal_connect (G_OBJECT (checkerSign), "toggled", G_CALLBACK (toggle_sign_cb), dialog); labelWho = gtk_label_new_with_mnemonic (_("Sign _as ")); gtk_box_pack_start (GTK_BOX (vboxEncrypt), labelWho, FALSE, TRUE, 0); scrollerWho = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollerWho), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_set_size_request (scrollerWho, 400, 200); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollerWho), GTK_SHADOW_IN); gtk_box_pack_start (GTK_BOX (vboxEncrypt), scrollerWho, TRUE, TRUE, 0); clistWho = gpa_key_selector_new (TRUE, TRUE); dialog->clist_who = clistWho; gtk_container_add (GTK_CONTAINER (scrollerWho), clistWho); gtk_label_set_mnemonic_widget (GTK_LABEL (labelWho), clistWho); /* FIXME: We can't make the key selector insensitive, as it will make itself sensitive again automatically after the keyloading. So we make the whole scroller insensitive. This is a bit overzealous, but should not affect usability too much. Eventually we could add a property to the key selector to force insensitivity even across key reloads. */ #if 0 gtk_widget_set_sensitive (clistWho, FALSE); #else dialog->scroller_who = scrollerWho; gtk_widget_set_sensitive (scrollerWho, FALSE); #endif checkerArmor = gtk_check_button_new_with_mnemonic (_("A_rmor")); gtk_box_pack_start (GTK_BOX (vboxEncrypt), checkerArmor, FALSE, FALSE, 0); dialog->check_armor = checkerArmor; if (dialog->force_armor) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->check_armor), TRUE); gtk_widget_set_sensitive (dialog->check_armor, FALSE); } return object; } static void gpa_file_encrypt_dialog_class_init (GpaFileEncryptDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->constructor = gpa_file_encrypt_dialog_constructor; object_class->finalize = gpa_file_encrypt_dialog_finalize; object_class->set_property = gpa_file_encrypt_dialog_set_property; object_class->get_property = gpa_file_encrypt_dialog_get_property; /* Properties */ g_object_class_install_property (object_class, PROP_WINDOW, g_param_spec_object ("window", "Parent window", "Parent window", GTK_TYPE_WIDGET, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_FORCE_ARMOR, g_param_spec_boolean ("force-armor", "Force armor", "Force armor mode", FALSE, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_ARMOR, g_param_spec_boolean ("armor", "Armor", "Armor mode", FALSE, G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_SIGN, g_param_spec_boolean ("sign", "Sign", "Sign", FALSE, G_PARAM_WRITABLE)); } GType gpa_file_encrypt_dialog_get_type (void) { static GType encrypt_dialog_type = 0; if (!encrypt_dialog_type) { static const GTypeInfo encrypt_dialog_info = { sizeof (GpaFileEncryptDialogClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gpa_file_encrypt_dialog_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GpaFileEncryptDialog), 0, /* n_preallocs */ (GInstanceInitFunc) gpa_file_encrypt_dialog_init, }; encrypt_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "GpaFileEncryptDialog", &encrypt_dialog_info, 0); } return encrypt_dialog_type; } /* API */ GtkWidget * gpa_file_encrypt_dialog_new (GtkWidget *parent, gboolean force_armor) { GpaFileEncryptDialog *dialog; dialog = g_object_new (GPA_FILE_ENCRYPT_DIALOG_TYPE, "window", parent, "force-armor", force_armor, NULL); return GTK_WIDGET(dialog); } GList * gpa_file_encrypt_dialog_recipients (GpaFileEncryptDialog *dialog) { return gpa_key_selector_get_selected_keys (GPA_KEY_SELECTOR (dialog->clist_keys)); } GList * gpa_file_encrypt_dialog_signers (GpaFileEncryptDialog *dialog) { return gpa_key_selector_get_selected_keys (GPA_KEY_SELECTOR (dialog->clist_who)); } gboolean gpa_file_encrypt_dialog_get_armor (GpaFileEncryptDialog *dialog) { return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->check_armor)); } void gpa_file_encrypt_dialog_set_armor (GpaFileEncryptDialog *dialog, gboolean armor) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->check_armor), armor); } gboolean gpa_file_encrypt_dialog_get_sign (GpaFileEncryptDialog *dialog) { return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->check_sign)); } void gpa_file_encrypt_dialog_set_sign (GpaFileEncryptDialog *dialog, gboolean sign) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->check_sign), sign); } static void changed_select_row_cb (GtkTreeSelection *treeselection, gpointer user_data) { GpaFileEncryptDialog *dialog = user_data; if (gpa_key_selector_has_selection (GPA_KEY_SELECTOR (dialog->clist_keys))) { gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE); } else { gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE); } } static void toggle_sign_cb (GtkToggleButton *togglebutton, gpointer user_data) { GpaFileEncryptDialog *dialog = user_data; /* FIXME: See above. */ #if 0 gtk_widget_set_sensitive (dialog->clist_who, gtk_toggle_button_get_active (togglebutton)); #else gtk_widget_set_sensitive (dialog->scroller_who, gtk_toggle_button_get_active (togglebutton)); #endif } diff --git a/src/fileman.c b/src/fileman.c index 4d95a5d..5a67206 100644 --- a/src/fileman.c +++ b/src/fileman.c @@ -1,1313 +1,1313 @@ /* fileman.c - The GNU Privacy Assistant Copyright (C) 2000, 2001 G-N-U GmbH. Copyright (C) 2007, 2008 g10 Code GmbH This file is part of GPA. GPA 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 3 of the License, or (at your option) any later version. GPA 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, see . */ /* The file encryption/decryption/sign window. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include "gpa.h" #include "gtktools.h" #include "gpawidgets.h" #include "siglist.h" #include "helpmenu.h" #include "icons.h" #include "fileman.h" #include "gpafiledecryptop.h" #include "gpafileencryptop.h" #include "gpafilesignop.h" #include "gpafileverifyop.h" #if ! GTK_CHECK_VERSION (2, 10, 0) #define GTK_STOCK_SELECT_ALL "gtk-select-all" #endif /* Object and class definition. */ struct _GpaFileManager { GtkWindow parent; GtkWidget *window; GtkWidget *list_files; GList *selection_sensitive_actions; }; struct _GpaFileManagerClass { GtkWindowClass parent_class; }; /* There is only one instance of the file manage class. Use a global variable to keep track of it. */ static GpaFileManager *instance; /* We also need to save the parent class. */ static GObjectClass *parent_class; /* Definition of the sensitivity function type. */ typedef gboolean (*sensitivity_func_t)(gpointer); /* Constants to define the file list. */ enum { FILE_NAME_COLUMN, FILE_N_COLUMNS }; #define DND_TARGET_URI_LIST 1 /* Drag and drop target list. */ static GtkTargetEntry dnd_target_list[] = { { "text/uri-list", 0, DND_TARGET_URI_LIST } }; /* Local prototypes */ static GObject *gpa_file_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties); /* * GtkWidget boilerplate. */ static void gpa_file_manager_finalize (GObject *object) { G_OBJECT_CLASS (parent_class)->finalize (object); } static void gpa_file_manager_init (GpaFileManager *fileman) { fileman->selection_sensitive_actions = NULL; } static void gpa_file_manager_class_init (GpaFileManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->constructor = gpa_file_manager_constructor; object_class->finalize = gpa_file_manager_finalize; } GType gpa_file_manager_get_type (void) { static GType fileman_type = 0; if (!fileman_type) { static const GTypeInfo fileman_info = { sizeof (GpaFileManagerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gpa_file_manager_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GpaFileManager), 0, /* n_preallocs */ (GInstanceInitFunc) gpa_file_manager_init, }; fileman_type = g_type_register_static (GTK_TYPE_WINDOW, "GpaFileManager", &fileman_info, 0); } return fileman_type; } /* * File manager methods */ /* Return the currently selected files as a new list of filenames * structs. The list and the texts must be freed by the caller. */ static GList * get_selected_files (GtkWidget *list) { GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (list)); GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); GList *selection = gtk_tree_selection_get_selected_rows (sel, &model); GList *files = NULL; while (selection) { gpa_file_item_t file_item; gchar *filename; GtkTreeIter iter; gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) selection->data); gtk_tree_model_get (model, &iter, FILE_NAME_COLUMN, &filename, -1); file_item = g_malloc0 (sizeof (*file_item)); file_item->filename_in = filename; files = g_list_append (files, file_item); selection = g_list_next (selection); } /* Free the selection */ g_list_foreach (selection, (GFunc) gtk_tree_path_free, NULL); g_list_free (selection); return files; } /* Add file FILENAME to the file list of FILEMAN and select it */ static gboolean add_file (GpaFileManager *fileman, const gchar *filename) { GtkListStore *store; GtkTreeIter iter; GtkTreePath *path; GtkTreeSelection *sel; gchar *filename_utf8; /* The tree contains filenames in the UTF-8 encoding. */ filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); /* Try to convert from the current locale as fallback. This is important for windows where g_filename_to_utf8 does not take locale into account because the filedialogs already convert to utf8. */ if (!filename_utf8) { filename_utf8 = g_locale_to_utf8 (filename, -1, NULL, NULL, NULL); } /* Last fallback is guranteed to never be NULL so in doubt we can still fail later showing a filename that can't be found to the user etc.*/ if (!filename_utf8) { filename_utf8 = g_filename_display_name (filename); } store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (fileman->list_files))); /* Check for duplicates. */ path = gtk_tree_path_new_first (); if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path)) do { gchar *tmp; gboolean exists; gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, FILE_NAME_COLUMN, &tmp, -1); exists = g_str_equal (filename_utf8, tmp); g_free (tmp); if (exists) { g_free (filename_utf8); gtk_tree_path_free (path); return FALSE; /* This file is already in our list. */ } } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter)); gtk_tree_path_free (path); /* Append it to our list. */ gtk_list_store_append (store, &iter); /* FIXME: Add the file status when/if gpgme supports it */ gtk_list_store_set (store, &iter, FILE_NAME_COLUMN, filename_utf8, -1); /* Select the row */ sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (fileman->list_files)); gtk_tree_selection_select_iter (sel, &iter); return TRUE; } /* Add a file created by an operation to the list */ static void file_created_cb (GpaFileOperation *op, gpa_file_item_t item, gpointer data) { GpaFileManager *fileman = data; add_file (fileman, item->filename_out); } /* Do whatever is required with a file operation, to ensure proper clean up */ static void register_operation (GpaFileManager *fileman, GpaFileOperation *op) { g_signal_connect (G_OBJECT (op), "created_file", G_CALLBACK (file_created_cb), fileman); g_signal_connect (G_OBJECT (op), "completed", G_CALLBACK (g_object_unref), NULL); } /* Management of the selection sensitive actions. */ /* Return true if a selection is active. */ static gboolean has_selection (gpointer param) { GpaFileManager *fileman = param; GtkTreeSelection *sel; sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (fileman->list_files)); return (gtk_tree_selection_count_selected_rows (sel) > 0); } /* Add WIDGET to the list of sensitive actions of FILEMAN. */ static void add_selection_sensitive_action (GpaFileManager *fileman, GSimpleAction *action, sensitivity_func_t callback) { g_object_set_data (G_OBJECT (action), "gpa_sensitivity", callback); fileman->selection_sensitive_actions = g_list_append (fileman->selection_sensitive_actions, action); } /* Update the sensitivity of the widget DATA and pass PARAM through to the sensitivity callback. Usable as an iterator function in g_list_foreach. */ static void update_selection_sensitive_action (gpointer data, gpointer param) { sensitivity_func_t func; func = g_object_get_data (G_OBJECT (data), "gpa_sensitivity"); g_simple_action_set_enabled (G_SIMPLE_ACTION (data), func (param)); } /* Call update_selection_sensitive_action for all widgets in the list of sensitive actions and pass FILEMAN through as the user data parameter. */ static void update_selection_sensitive_actions (GpaFileManager *fileman) { g_list_foreach (fileman->selection_sensitive_actions, update_selection_sensitive_action, (gpointer) fileman); } /* Actions as called by the menu items. */ static GSList * get_load_file_name (GtkWidget *parent, const gchar *title, const gchar *directory) { static GtkWidget *dialog; GtkResponseType response; GSList *filenames = NULL; if (! dialog) { dialog = gtk_file_chooser_dialog_new (title, GTK_WINDOW (parent), GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Open"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE); } if (directory) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), directory); gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (dialog)); /* Run the dialog until there is a valid response. */ response = gtk_dialog_run (GTK_DIALOG (dialog)); if (response == GTK_RESPONSE_OK) filenames = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (dialog)); gtk_widget_hide (dialog); return filenames; } /* Handle menu item "File/Open". */ void open_file_one (gpointer data, gpointer user_data) { GpaFileManager *fileman = user_data; gchar *filename = (gchar *) data; /* FIXME: We are ignoring errors here. */ add_file (fileman, filename); g_free (filename); } static void file_open (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaFileManager *fileman = param; GSList *filenames; filenames = get_load_file_name (GTK_WIDGET (fileman), _("Open File"), NULL); if (! filenames) return; g_slist_foreach (filenames, open_file_one, fileman); g_slist_free (filenames); } /* Handle menu item "File/Clear". */ static void file_clear (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaFileManager *fileman = param; GtkListStore *store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (fileman->list_files))); gtk_list_store_clear (store); } /* Handle menu item "File/Verify". */ static void file_verify (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaFileManager *fileman = param; GList *files; GpaFileVerifyOperation *op; files = get_selected_files (fileman->list_files); if (!files) return; op = gpa_file_verify_operation_new (GTK_WIDGET (fileman), files); register_operation (fileman, GPA_FILE_OPERATION (op)); } /* Handle menu item "File/Sign". */ static void file_sign (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaFileManager *fileman = param; GList * files; GpaFileSignOperation *op; files = get_selected_files (fileman->list_files); if (!files) return; op = gpa_file_sign_operation_new (GTK_WIDGET (fileman), files, FALSE); register_operation (fileman, GPA_FILE_OPERATION (op)); } /* Handle menu item "File/Encrypt". */ static void file_encrypt (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaFileManager *fileman = param; GList *files; GpaFileEncryptOperation *op; files = get_selected_files (fileman->list_files); if (!files) return; op = gpa_file_encrypt_operation_new (GTK_WIDGET (fileman), files, FALSE); register_operation (fileman, GPA_FILE_OPERATION (op)); } /* Handle menu item "File/Decrypt". */ static void file_decrypt (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaFileManager *fileman = param; GList *files; GpaFileDecryptOperation *op; files = get_selected_files (fileman->list_files); if (!files) return; op = gpa_file_decrypt_verify_operation_new (GTK_WIDGET (fileman), files); register_operation (fileman, GPA_FILE_OPERATION (op)); } /* Handle menu item "File/Close". */ static void file_close (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaFileManager *fileman = param; gtk_widget_destroy (GTK_WIDGET (fileman)); } /* Handle menu item "File/Quit". */ static void file_quit (GSimpleAction *simple, GVariant *parameter, gpointer param) { g_application_quit (G_APPLICATION (get_gpa_application ())); } /* Handle menu item "Edit/Select All". */ static void edit_select_all (GSimpleAction *simple, GVariant *parameter, gpointer param) { GpaFileManager *fileman = param; gtk_tree_selection_select_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (fileman->list_files))); } /* Construct the file manager menu and toolbar widgets and return them. */ static void fileman_action_new (GpaFileManager *fileman, GtkWidget **menubar, GtkWidget **toolbar) { static const GActionEntry entries[] = { { "File", NULL }, { "Edit", NULL }, { "file_open", file_open }, { "file_clear", file_clear }, { "file_sign", file_sign }, { "file_verify", file_verify }, { "file_encrypt", file_encrypt }, { "file_decrypt", file_decrypt }, { "file_close", file_close }, { "file_quit", file_quit }, { "edit_select_all", edit_select_all }, }; /* static const GtkActionEntry old_entries[] = { // Toplevel. { "File", NULL, N_("_File"), NULL }, { "Edit", NULL, N_("_Edit"), NULL }, // File menu. - { "FileOpen", GTK_STOCK_OPEN, NULL, NULL, + { "FileOpen", _("_Open"), NULL, NULL, N_("Open a file"), G_CALLBACK (file_open) }, { "FileClear", GTK_STOCK_CLEAR, NULL, NULL, N_("Close all files"), G_CALLBACK (file_clear) }, { "FileSign", GPA_STOCK_SIGN, NULL, NULL, N_("Sign the selected file"), G_CALLBACK (file_sign) }, { "FileVerify", GPA_STOCK_VERIFY, NULL, NULL, N_("Check signatures of selected file"), G_CALLBACK (file_verify) }, { "FileEncrypt", GPA_STOCK_ENCRYPT, NULL, NULL, N_("Encrypt the selected file"), G_CALLBACK (file_encrypt) }, { "FileDecrypt", GPA_STOCK_DECRYPT, NULL, NULL, N_("Decrypt the selected file"), G_CALLBACK (file_decrypt) }, - { "FileClose", GTK_STOCK_CLOSE, NULL, NULL, + { "FileClose", _("_Close"), NULL, NULL, N_("Close the window"), G_CALLBACK (file_close) }, { "FileQuit", GTK_STOCK_QUIT, NULL, NULL, N_("Quit the program"), G_CALLBACK (g_application_quit) }, // Edit menu. { "EditSelectAll", GTK_STOCK_SELECT_ALL, NULL, "A", N_("Select all files"), G_CALLBACK (edit_select_all) } }; */ /* static const char *ui_description = "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " #ifdef ENABLE_CARD_MANAGER " " #endif " " " " #if 0 " " #endif " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " #ifdef ENABLE_CARD_MANAGER " " #endif #if 0 " " #endif " " ""; */ static const char *menu_string = { "" "" "" "_File" "
" "" "Open" "app.file_open" "" "" "Clear" "app.file_clear" "" "
" "
" "" "Sign" "app.file_sign" "" "" "Verify" "app.file_verify" "" "" "Encrypt" "app.file_encrypt" "" "" "Decrypt" "app.file_decrypt" "" "
" "
" "" "Close" "app.file_close" "" "" "Quit" "app.file_quit" "" "
" "
" "" "Edit" "
" "" "Mark All" "app.file_close" "" "
" "
" "" "Backend Settings" "app.edit_backend_preferences" "" "" "Settings" "app.edit_preferences" "" "
" "
" "" "Window" "" "Keyring Manager" "app.windows_keyring_editor" "" "" "File Manager" "app.windows_file_manager" "" "" "Clipboard" "app.windows_clipboard" "" "" "Card Manager" "app.windows_card_manager" "" "" "" "Help" "" "About" "app.help_about" "" "" "
" "" "True" "False" "False" "" "" "True" "False" "True" "document-open" "app.file_open" "true" "Open a file" "" "" "False" "True" "" "" "" "" "True" "False" "True" "edit-clear" "app.file_close" "true" "Close all files" "" "" "False" "True" "" "" "" "" "" "" "" "" "True" "False" "True" "sign" "app.file_sign" "true" "Sign the selected file" "" "" "False" "True" "" "" "" "" "True" "False" "True" "verify" "app.file_verify" "true" "Check signatures of selected files" "" "" "False" "True" "" "" "" "" "True" "False" "True" "encrypt" "app.file_encrypt" "true" "Encrypt the selected file" "" "" "False" "True" "" "" "" "" "True" "False" "True" "decrypt" "app.file_decrypt" "true" "Decrypt the selected file" "" "" "False" "True" "" "" "" "" "" "" "" "" "True" "False" "True" "preferences-desktop" "app.edit_preferences" "true" "Configure the application" "" "" "False" "True" "" "" "" "" "" "" "" "" "True" "False" "True" "keyring" "app.windows_keyring_editor" "true" "Open the keyring editor" "" "" "False" "True" "" "" "" "" "True" "False" "True" "edit-paste" "app.windows_clipboard" "true" "Open the clipboard" "" "" "False" "True" "" "" "" "" "True" "False" "True" "smartcard" "app.windows_card_manager" "true" "Open the card manager" "" "" "False" "True" "" "" "" "
" }; /* GtkAccelGroup *accel_group; GtkActionGroup *action_group; GtkAction *action; GtkUIManager *ui_manager; GError *error; action_group = gtk_action_group_new ("MenuActions"); gtk_action_group_set_translation_domain (action_group, PACKAGE); gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), fileman); gtk_action_group_add_actions (action_group, gpa_help_menu_action_entries, G_N_ELEMENTS (gpa_help_menu_action_entries), fileman); gtk_action_group_add_actions (action_group, gpa_windows_menu_action_entries, G_N_ELEMENTS (gpa_windows_menu_action_entries), fileman); gtk_action_group_add_actions (action_group, gpa_preferences_menu_action_entries, G_N_ELEMENTS (gpa_preferences_menu_action_entries), fileman); ui_manager = gtk_ui_manager_new (); gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); accel_group = gtk_ui_manager_get_accel_group (ui_manager); gtk_window_add_accel_group (GTK_WINDOW (fileman), accel_group); if (! gtk_ui_manager_add_ui_from_string (ui_manager, ui_description, -1, &error)) { g_message ("building fileman menus failed: %s", error->message); g_error_free (error); exit (EXIT_FAILURE); } // Fixup the icon theme labels which are too long for the toolbar. action = gtk_action_group_get_action (action_group, "WindowsKeyringEditor"); g_object_set (action, "short_label", _("Keyring"), NULL); #ifdef ENABLE_CARD_MANAGER action = gtk_action_group_get_action (action_group, "WindowsCardManager"); g_object_set (action, "short_label", _("Card"), NULL); #endif // Take care of sensitiveness of widgets. action = gtk_action_group_get_action (action_group, "FileSign"); add_selection_sensitive_action (fileman, action, has_selection); action = gtk_action_group_get_action (action_group, "FileVerify"); add_selection_sensitive_action (fileman, action, has_selection); action = gtk_action_group_get_action (action_group, "FileEncrypt"); add_selection_sensitive_action (fileman, action, has_selection); action = gtk_action_group_get_action (action_group, "FileDecrypt"); add_selection_sensitive_action (fileman, action, has_selection); *menubar = gtk_ui_manager_get_widget (ui_manager, "/MainMenu"); *toolbar = gtk_ui_manager_get_widget (ui_manager, "/ToolBar"); gpa_toolbar_set_homogeneous (GTK_TOOLBAR (*toolbar), FALSE); */ GError *err = NULL; GtkBuilder *gtk_builder = gtk_builder_new_from_string (menu_string, -1); if (gtk_builder_add_from_string( gtk_builder, menu_string , -1, &err) == 0) { printf("ERROR: %s \n", err->message); } GMenuModel *menu_bar_model = G_MENU_MODEL (gtk_builder_get_object (GTK_BUILDER (gtk_builder), "main_menu")); *menubar = gtk_menu_bar_new_from_model (menu_bar_model); /* GMenuModel *popup_menu_model = G_MENU_MODEL (gtk_builder_get_object (GTK_BUILDER (gtk_builder), "popupmenu")); *popup = gtk_menu_new_from_model (popup_menu_model); */ GObject *grid = gtk_builder_get_object (GTK_BUILDER (gtk_builder), "toolbar"); GtkCssProvider *css_provider = gtk_css_provider_new(); GdkDisplay *display = gdk_display_get_default(); GdkScreen *screen = gdk_display_get_default_screen (display); gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER(css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER); gtk_css_provider_load_from_data(css_provider, "#toolbar {\n" //" padding-left: 55px;\n" // " padding-right: 5px;\n" // " border-radius: 3px;\n" "}\n", -1, NULL); GtkStyleContext *style_context; style_context = gtk_widget_get_style_context (GTK_WIDGET (grid)); //gtk_widget_add_css_class (grid, "toolbar"); *toolbar = GTK_WIDGET (grid); // We must set the name to the toolbar for css to recognize it gtk_widget_set_name(*toolbar, "toolbar"); gtk_style_context_add_class (style_context, "toolbar"); GtkApplication *gpa_app = get_gpa_application (); g_action_map_add_action_entries (G_ACTION_MAP (gpa_app), gpa_windows_menu_g_action_entries, G_N_ELEMENTS (gpa_windows_menu_g_action_entries), fileman); g_action_map_add_action_entries (G_ACTION_MAP (gpa_app), entries, G_N_ELEMENTS (entries), fileman); g_action_map_add_action_entries (G_ACTION_MAP (gpa_app), gpa_help_menu_g_action_entries, G_N_ELEMENTS (gpa_help_menu_g_action_entries), fileman); g_action_map_add_action_entries (G_ACTION_MAP (gpa_app), gpa_preferences_menu_g_action_entries, G_N_ELEMENTS (gpa_preferences_menu_g_action_entries), fileman); GSimpleAction *action; action = (GSimpleAction*)g_action_map_lookup_action (G_ACTION_MAP (gpa_app), "file_sign"); add_selection_sensitive_action (fileman, action, has_selection); action = (GSimpleAction*)g_action_map_lookup_action (G_ACTION_MAP (gpa_app), "file_verify"); add_selection_sensitive_action (fileman, action, has_selection); action = (GSimpleAction*)g_action_map_lookup_action (G_ACTION_MAP (gpa_app), "file_encrypt"); add_selection_sensitive_action (fileman, action, has_selection); action = (GSimpleAction*)g_action_map_lookup_action (G_ACTION_MAP (gpa_app), "file_decrypt"); add_selection_sensitive_action (fileman, action, has_selection); } /* Drag and Drop handler. */ /* Handler for "drag-drop". This signal is emitted when the user drops the selection. */ static gboolean dnd_drop_handler (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint tim, gpointer user_data) { GdkAtom target_type = gdk_atom_intern ("text/uri-list", FALSE); GList *targets = gdk_drag_context_list_targets(context); /* If the source offers a target we request the data from her. */ if (targets && g_list_find (targets, GDK_ATOM_TO_POINTER (target_type))) { gtk_drag_get_data (widget, context, target_type, tim); return TRUE; } return FALSE; } /* Handler for "drag-data-received". This signal is emitted when the data has been received from the source. */ static void dnd_data_received_handler (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint target_type, guint tim, gpointer user_data) { GpaFileManager *fileman = user_data; gboolean dnd_success = FALSE; gboolean delete_selection_data = FALSE; // const guchar *our_selection_data = gtk_selection_data_get_data(selection_data); /* Is that usable by us? */ if (selection_data && gtk_selection_data_get_length(selection_data) >= 0 ) { GdkDragAction drag_action = gdk_drag_context_get_suggested_action(context); if (drag_action == GDK_ACTION_MOVE) delete_selection_data = TRUE; /* Check that we got a format we can use. */ if (target_type == DND_TARGET_URI_LIST) { //char *p = (char *) selection_data->data; char *p = (char *)gtk_selection_data_get_data(selection_data); char **list; int i; list = g_uri_list_extract_uris (p); for (i=0; list && list[i]; i++) { char *name = g_filename_from_uri (list[i], NULL, NULL); if (name) { /* Canonical line endings are required for an uri-list. */ if ((p = strchr (name, '\r'))) *p = 0; add_file (fileman, name); g_free (name); } } g_strfreev (list); dnd_success = TRUE; } } /* Finish the DnD processing. */ gtk_drag_finish (context, dnd_success, delete_selection_data, tim); } /* Construct the file list object. */ static GtkWidget * file_list_new (GpaFileManager * fileman) { GtkWidget *scrollerFile; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeSelection *sel; GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING); GtkWidget *list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("File"), renderer, "text", FILE_NAME_COLUMN, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); gtk_tree_selection_set_mode (sel, GTK_SELECTION_MULTIPLE); g_signal_connect_swapped (sel, "changed", G_CALLBACK (update_selection_sensitive_actions), fileman); scrollerFile = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollerFile), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollerFile), GTK_SHADOW_IN); fileman->list_files = list; gtk_widget_grab_focus (list); gtk_container_add (GTK_CONTAINER (scrollerFile), list); return scrollerFile; } /* Callback for the destroy signal. */ static void file_manager_closed (GtkWidget *widget, gpointer param) { instance = NULL; } /* Construct a new class object of GpaFileManager. */ static GObject* gpa_file_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *object; GpaFileManager *fileman; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *label; GtkWidget *icon; gchar *markup; GtkWidget *menubar; GtkWidget *file_box; GtkWidget *file_frame; GtkWidget *toolbar; GtkWidget *align; guint pt, pb, pl, pr; /* Invoke parent's constructor. */ object = parent_class->constructor (type, n_construct_properties, construct_properties); fileman = GPA_FILE_MANAGER (object); /* Initialize. */ gpa_window_set_title (GTK_WINDOW (fileman), _("File Manager")); gtk_window_set_default_size (GTK_WINDOW (fileman), 640, 480); /* Realize the window so that we can create pixmaps without warnings. */ gtk_widget_realize (GTK_WIDGET (fileman)); /* Use a vbox to show the menu, toolbar and the file container. */ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); /* Get the menu and the toolbar. */ fileman_action_new (fileman, &menubar, &toolbar); gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0); /* Add a fancy label that tells us: This is the file manager. */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5); icon = gtk_image_new_from_icon_name ("folder", GTK_ICON_SIZE_DND); gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, TRUE, 0); label = gtk_label_new (NULL); markup = g_strdup_printf ("%s", _("File Manager")); gtk_label_set_markup (GTK_LABEL (label), markup); g_free (markup); gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 10); gtk_widget_set_halign (GTK_WIDGET (label), GTK_ALIGN_START); gtk_widget_set_valign (GTK_WIDGET (label), GTK_ALIGN_CENTER); /* Third a hbox with the file list. */ align = gtk_alignment_new (0.5, 0.5, 1, 1); gtk_alignment_get_padding (GTK_ALIGNMENT (align), &pt, &pb, &pl, &pr); gtk_alignment_set_padding (GTK_ALIGNMENT (align), pt, pb + 5, pl + 5, pr + 5); gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0); file_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); file_frame = file_list_new (fileman); gtk_box_pack_start (GTK_BOX (file_box), file_frame, TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER (align), file_box); gtk_container_add (GTK_CONTAINER (fileman), vbox); g_signal_connect (object, "destroy", G_CALLBACK (file_manager_closed), object); /* Make the file box a DnD destination. */ gtk_drag_dest_set (file_box, (GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT), dnd_target_list, DIM (dnd_target_list), GDK_ACTION_COPY); g_signal_connect (file_box, "drag-drop", G_CALLBACK (dnd_drop_handler), fileman); g_signal_connect (file_box, "drag-data-received", G_CALLBACK (dnd_data_received_handler), fileman); return object; } static GpaFileManager * gpa_fileman_new () { GpaFileManager *fileman; fileman = g_object_new (GPA_FILE_MANAGER_TYPE, NULL); update_selection_sensitive_actions (fileman); return fileman; } /* API */ GtkWidget * gpa_file_manager_get_instance (void) { if (!instance) { instance = gpa_fileman_new (); } return GTK_WIDGET (instance); } gboolean gpa_file_manager_is_open (void) { return (instance != NULL); } void gpa_file_manager_open_file (GpaFileManager *fileman, const gchar *filename) { if (!add_file (fileman, filename)) gpa_window_error (_("The file is already open."), GTK_WIDGET (fileman)); /* FIXME: Release filename? */ } diff --git a/src/filesigndlg.c b/src/filesigndlg.c index 36fddaf..3746922 100644 --- a/src/filesigndlg.c +++ b/src/filesigndlg.c @@ -1,466 +1,466 @@ /* filesigndlg.c - The GNU Privacy Assistant Copyright (C) 2000, 2001 G-N-U GmbH. Copyright (C) 2008 g10 Code GmbH. This file is part of GPA. GPA 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 3 of the License, or (at your option) any later version. GPA 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, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include "gpa.h" #include "gtktools.h" #include "gpawidgets.h" #include "gpakeyselector.h" #include "filesigndlg.h" /* Properties */ enum { PROP_0, PROP_WINDOW, PROP_FORCE_ARMOR, PROP_ARMOR, PROP_FORCE_SIG_MODE, PROP_SIG_MODE }; static GObjectClass *parent_class = NULL; static void gpa_file_sign_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GpaFileSignDialog *dialog = GPA_FILE_SIGN_DIALOG (object); switch (prop_id) { case PROP_WINDOW: g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (dialog))); break; case PROP_FORCE_ARMOR: g_value_set_boolean (value, gpa_file_sign_dialog_get_force_armor (dialog)); break; case PROP_ARMOR: g_value_set_boolean (value, gpa_file_sign_dialog_get_armor (dialog)); break; case PROP_FORCE_SIG_MODE: g_value_set_boolean (value, gpa_file_sign_dialog_get_force_sig_mode (dialog)); break; case PROP_SIG_MODE: g_value_set_int (value, gpa_file_sign_dialog_get_sig_mode (dialog)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gpa_file_sign_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GpaFileSignDialog *dialog = GPA_FILE_SIGN_DIALOG (object); switch (prop_id) { case PROP_WINDOW: gtk_window_set_transient_for (GTK_WINDOW (dialog), g_value_get_object (value)); break; case PROP_FORCE_ARMOR: gpa_file_sign_dialog_set_force_armor (dialog, g_value_get_boolean (value)); break; case PROP_ARMOR: gpa_file_sign_dialog_set_armor (dialog, g_value_get_boolean (value)); break; case PROP_FORCE_SIG_MODE: gpa_file_sign_dialog_set_force_sig_mode (dialog, g_value_get_boolean (value)); break; case PROP_SIG_MODE: gpa_file_sign_dialog_set_sig_mode (dialog, g_value_get_int (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gpa_file_sign_dialog_finalize (GObject *object) { G_OBJECT_CLASS (parent_class)->finalize (object); } static void gpa_file_sign_dialog_init (GpaFileSignDialog *dialog) { } static GObject* gpa_file_sign_dialog_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *object; GpaFileSignDialog *dialog; GtkWidget *vboxSign; GtkWidget *label; GtkWidget *frameMode; GtkWidget *vboxMode; GtkWidget *radio_sign_comp; GtkWidget *radio_sign; GtkWidget *radio_sign_sep; GtkWidget *checkerArmor; GtkWidget *frameWho; GtkWidget *vboxWho; GtkWidget *labelWho; GtkWidget *scrollerWho; GtkWidget *clistWho; /* Invoke parent's constructor */ object = parent_class->constructor (type, n_construct_properties, construct_properties); dialog = GPA_FILE_SIGN_DIALOG (object); /* Initialize */ /* Set up the dialog */ gtk_dialog_add_buttons (GTK_DIALOG (dialog), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_OK"), GTK_RESPONSE_OK, NULL); gpa_window_set_title (GTK_WINDOW (dialog), _("Sign documents")); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); vboxSign = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); // gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vboxSign); GtkWidget *box = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); gtk_box_pack_start (GTK_BOX (box), vboxSign, TRUE, TRUE, 0); frameWho = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frameWho), GTK_SHADOW_NONE); labelWho = gtk_label_new_with_mnemonic (_("Sign _as")); gtk_label_set_use_markup (GTK_LABEL (labelWho), TRUE); gtk_frame_set_label_widget (GTK_FRAME (frameWho), labelWho); gtk_box_pack_start (GTK_BOX (vboxSign), frameWho, FALSE, FALSE, 0); vboxWho = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (frameWho), vboxWho); scrollerWho = gtk_scrolled_window_new (NULL, NULL); gtk_widget_set_size_request (scrollerWho, 400, 200); gtk_box_pack_start (GTK_BOX (vboxWho), scrollerWho, TRUE, TRUE, 0); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollerWho), GTK_SHADOW_IN); clistWho = gpa_key_selector_new (TRUE, TRUE); dialog->clist_who = clistWho; gtk_container_add (GTK_CONTAINER (scrollerWho), clistWho); gtk_label_set_mnemonic_widget (GTK_LABEL (labelWho), clistWho); frameMode = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frameMode), GTK_SHADOW_NONE); label = gtk_label_new (_("Signing Mode")); gtk_label_set_use_markup (GTK_LABEL (label), TRUE); gtk_frame_set_label_widget (GTK_FRAME (frameMode), label); gtk_box_pack_start (GTK_BOX (vboxSign), frameMode, FALSE, FALSE, 0); vboxMode = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (frameMode), vboxMode); dialog->frame_mode = frameMode; radio_sign_comp = gtk_radio_button_new_with_mnemonic (NULL, _("Si_gn and compress")); gtk_box_pack_start (GTK_BOX (vboxMode), radio_sign_comp, FALSE, FALSE, 0); dialog->radio_comp = radio_sign_comp; radio_sign = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (radio_sign_comp), _("Clear_text signature")); gtk_box_pack_start (GTK_BOX (vboxMode), radio_sign, FALSE, FALSE, 0); dialog->radio_sign = radio_sign; /* FIXME: We hide the radio button here. It still can be activated invisibly by setting the "sig-mode" property. This is used by the clipboard code, which also hides the whole sig mode selection frame, so no harm done. For the file sign mode, hiding the cleartext option is the right thing to do. But eventually, all this should be freely configurable by the caller, instead of relying on such knowledge. */ gtk_widget_set_no_show_all (radio_sign, TRUE); gtk_widget_hide (radio_sign); radio_sign_sep = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (radio_sign_comp), _("_Detached signature")); gtk_box_pack_start (GTK_BOX (vboxMode), radio_sign_sep, FALSE, FALSE, 0); dialog->radio_sep = radio_sign_sep; /* Allow for the frameMode to be hidden despite what show_all does. */ gtk_widget_show_all (frameMode); gtk_widget_set_no_show_all (frameMode, TRUE); checkerArmor = gtk_check_button_new_with_mnemonic (_("A_rmor")); gtk_box_pack_start (GTK_BOX (vboxSign), checkerArmor, FALSE, FALSE, 0); /* Take care of any child widgets there might be. */ gtk_widget_show_all (checkerArmor); gtk_widget_set_no_show_all (checkerArmor, TRUE); dialog->check_armor = checkerArmor; return object; } static void gpa_file_sign_dialog_class_init (GpaFileSignDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->constructor = gpa_file_sign_dialog_constructor; object_class->finalize = gpa_file_sign_dialog_finalize; object_class->set_property = gpa_file_sign_dialog_set_property; object_class->get_property = gpa_file_sign_dialog_get_property; /* Properties */ g_object_class_install_property (object_class, PROP_WINDOW, g_param_spec_object ("window", "Parent window", "Parent window", GTK_TYPE_WIDGET, G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_FORCE_ARMOR, g_param_spec_boolean ("force-armor", "Force armor", "Force armor mode", FALSE, G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_ARMOR, g_param_spec_boolean ("armor", "Armor mode", "Armor mode", FALSE, G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_FORCE_SIG_MODE, g_param_spec_boolean ("force-sig-mode", "Force signature mode", "Force signature mode", FALSE, G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_SIG_MODE, g_param_spec_int ("sig-mode", "Signature mode", "Signature mode", GPGME_SIG_MODE_NORMAL, GPGME_SIG_MODE_CLEAR, GPGME_SIG_MODE_NORMAL, G_PARAM_WRITABLE)); } GType gpa_file_sign_dialog_get_type (void) { static GType sign_dialog_type = 0; if (!sign_dialog_type) { static const GTypeInfo sign_dialog_info = { sizeof (GpaFileSignDialogClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gpa_file_sign_dialog_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GpaFileSignDialog), 0, /* n_preallocs */ (GInstanceInitFunc) gpa_file_sign_dialog_init, }; sign_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "GpaFileSignDialog", &sign_dialog_info, 0); } return sign_dialog_type; } /* API */ GtkWidget * gpa_file_sign_dialog_new (GtkWidget *parent) { GpaFileSignDialog *dialog; dialog = g_object_new (GPA_FILE_SIGN_DIALOG_TYPE, "window", parent, NULL); return GTK_WIDGET(dialog); } GList * gpa_file_sign_dialog_signers (GpaFileSignDialog *dialog) { return gpa_key_selector_get_selected_keys (GPA_KEY_SELECTOR(dialog->clist_who)); } gboolean gpa_file_sign_dialog_get_armor (GpaFileSignDialog *dialog) { g_return_val_if_fail (GPA_IS_FILE_SIGN_DIALOG (dialog), FALSE); g_return_val_if_fail (dialog->check_armor != NULL, FALSE); return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->check_armor)); } void gpa_file_sign_dialog_set_armor (GpaFileSignDialog *dialog, gboolean armor) { g_return_if_fail (GPA_IS_FILE_SIGN_DIALOG (dialog)); g_return_if_fail (dialog->check_armor != NULL); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->check_armor), armor); } gboolean gpa_file_sign_dialog_get_force_armor (GpaFileSignDialog *dialog) { g_return_val_if_fail (GPA_IS_FILE_SIGN_DIALOG (dialog), FALSE); return dialog->force_armor; } void gpa_file_sign_dialog_set_force_armor (GpaFileSignDialog *dialog, gboolean force_armor) { g_return_if_fail (GPA_IS_FILE_SIGN_DIALOG (dialog)); g_return_if_fail (dialog->check_armor != NULL); if (force_armor == dialog->force_armor) return; if (force_armor) gtk_widget_hide (dialog->check_armor); else gtk_widget_show (dialog->check_armor); dialog->force_armor = force_armor; } gpgme_sig_mode_t gpa_file_sign_dialog_get_sig_mode (GpaFileSignDialog *dialog) { gpgme_sig_mode_t sig_mode = GPGME_SIG_MODE_NORMAL; g_return_val_if_fail (GPA_IS_FILE_SIGN_DIALOG (dialog), GPGME_SIG_MODE_NORMAL); g_return_val_if_fail (dialog->frame_mode != NULL, GPGME_SIG_MODE_NORMAL); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->radio_comp))) sig_mode = GPGME_SIG_MODE_NORMAL; else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_sign))) sig_mode = GPGME_SIG_MODE_CLEAR; else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(dialog->radio_sep))) sig_mode = GPGME_SIG_MODE_DETACH; return sig_mode; } void gpa_file_sign_dialog_set_sig_mode (GpaFileSignDialog *dialog, gpgme_sig_mode_t mode) { GtkWidget *button = NULL; g_return_if_fail (GPA_IS_FILE_SIGN_DIALOG (dialog)); g_return_if_fail (dialog->frame_mode != NULL); if (mode == GPGME_SIG_MODE_NORMAL) button = dialog->radio_comp; else if (mode == GPGME_SIG_MODE_CLEAR) button = dialog->radio_sign; else if (mode == GPGME_SIG_MODE_DETACH) button = dialog->radio_sep; if (button != NULL) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); } gboolean gpa_file_sign_dialog_get_force_sig_mode (GpaFileSignDialog *dialog) { g_return_val_if_fail (GPA_IS_FILE_SIGN_DIALOG (dialog), FALSE); return dialog->force_sig_mode; } void gpa_file_sign_dialog_set_force_sig_mode (GpaFileSignDialog *dialog, gboolean force_sig_mode) { g_return_if_fail (GPA_IS_FILE_SIGN_DIALOG (dialog)); g_return_if_fail (dialog->frame_mode != NULL); if (force_sig_mode == dialog->force_sig_mode) return; if (force_sig_mode) gtk_widget_hide (dialog->frame_mode); else gtk_widget_show (dialog->frame_mode); } diff --git a/src/gpabackupop.c b/src/gpabackupop.c index 316dbb0..e9fe51f 100644 --- a/src/gpabackupop.c +++ b/src/gpabackupop.c @@ -1,346 +1,346 @@ /* gpabackupop.c - The GpaBackupOperation object. Copyright (C) 2003 Miguel Coca. Copyright (C) 2005, 2008 g10 Code GmbH. This file is part of GPA. GPA 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. GPA 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 GPA; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include "gpa.h" #include "i18n.h" #include "gtktools.h" #include "gpabackupop.h" static GObjectClass *parent_class = NULL; static gboolean gpa_backup_operation_idle_cb (gpointer data); /* GObject boilerplate. */ /* Properties. */ enum { PROP_0, PROP_KEY, PROP_FINGERPRINT, PROP_PROTOCOL }; static void gpa_backup_operation_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GpaBackupOperation *op = GPA_BACKUP_OPERATION (object); switch (prop_id) { case PROP_KEY: g_value_set_pointer (value, op->key); break; case PROP_FINGERPRINT: g_value_set_string (value, op->fpr); break; case PROP_PROTOCOL: g_value_set_int (value, op->protocol); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gpa_backup_operation_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GpaBackupOperation *op = GPA_BACKUP_OPERATION (object); gchar *fpr; gpgme_key_t key; switch (prop_id) { case PROP_KEY: key = (gpgme_key_t) g_value_get_pointer (value); if (key) { op->key = key; gpgme_key_ref (op->key); op->fpr = g_strdup (op->key->subkeys->fpr); op->key_id = g_strdup (gpa_gpgme_key_get_short_keyid (op->key)); } break; case PROP_FINGERPRINT: fpr = (gchar*) g_value_get_pointer (value); if (fpr) { op->key = NULL; op->fpr = g_strdup (fpr); op->key_id = g_strdup (fpr + strlen (fpr) - 8); } break; case PROP_PROTOCOL: op->protocol = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gpa_backup_operation_finalize (GObject *object) { GpaBackupOperation *op = GPA_BACKUP_OPERATION (object); gpgme_key_unref (op->key); g_free (op->fpr); g_free (op->key_id); G_OBJECT_CLASS (parent_class)->finalize (object); } static void gpa_backup_operation_init (GpaBackupOperation *op) { op->key = NULL; op->fpr = NULL; op->key_id = NULL; op->protocol = GPGME_PROTOCOL_UNKNOWN; } static GObject* gpa_backup_operation_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *object; GpaBackupOperation *op; /* Invoke parent's constructor */ object = parent_class->constructor (type, n_construct_properties, construct_properties); op = GPA_BACKUP_OPERATION (object); /* Begin working when we are back into the main loop */ g_idle_add (gpa_backup_operation_idle_cb, op); return object; } static void gpa_backup_operation_class_init (GpaBackupOperationClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->constructor = gpa_backup_operation_constructor; object_class->finalize = gpa_backup_operation_finalize; object_class->set_property = gpa_backup_operation_set_property; object_class->get_property = gpa_backup_operation_get_property; /* Properties */ g_object_class_install_property (object_class, PROP_KEY, g_param_spec_pointer ("key", "Key", "Key", G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_FINGERPRINT, g_param_spec_pointer ("fpr", "fpr", "Fingerprint", G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_PROTOCOL, g_param_spec_int ("protocol", "Protocol", "The gpgme protocol used for FPR.", GPGME_PROTOCOL_OpenPGP, GPGME_PROTOCOL_UNKNOWN, GPGME_PROTOCOL_UNKNOWN, G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY)); } GType gpa_backup_operation_get_type (void) { static GType file_operation_type = 0; if (!file_operation_type) { static const GTypeInfo file_operation_info = { sizeof (GpaBackupOperationClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gpa_backup_operation_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GpaBackupOperation), 0, /* n_preallocs */ (GInstanceInitFunc) gpa_backup_operation_init, }; file_operation_type = g_type_register_static (GPA_OPERATION_TYPE, "GpaBackupOperation", &file_operation_info, 0); } return file_operation_type; } /* Private functions */ static void gpa_backup_operation_do_backup (GpaBackupOperation *op, gchar *filename) { if (gpa_backup_key (op->fpr, filename, (op->protocol == GPGME_PROTOCOL_CMS))) { gchar *message; message = g_strdup_printf (_("A copy of your secret key has " "been made to the file:\n\n" "\t\"%s\"\n\n" "This is sensitive information, " "and should be stored carefully\n" "(for example, on a USB stick " "kept in a safe place)."), filename); gpa_window_message (message, GPA_OPERATION (op)->window); g_free (message); gpa_options_set_backup_generated (gpa_options_get_instance (), TRUE); } else { gchar *message = g_strdup_printf (_("An error ocurred during the " "backup operation.")); gpa_window_error (message, GPA_OPERATION (op)->window); } } /* Return the filename in filename encoding. */ static gchar* gpa_backup_operation_dialog_run (GtkWidget *parent, const gchar *key_id, int is_x509) { static GtkWidget *dialog; GtkResponseType response; gchar *default_comp; gchar *filename = NULL; gchar *id_text; GtkWidget *id_label; if (! dialog) { dialog = gtk_file_chooser_dialog_new (_("Backup key to file"), GTK_WINDOW (parent), - GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL); + GTK_FILE_CHOOSER_ACTION_SAVE, _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Save"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_home_dir ()); } /* Set the label with more explanations. */ id_text = g_strdup_printf (_("Generating backup of key: 0x%s"), key_id); id_label = gtk_label_new (id_text); g_free (id_text); gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), id_label); /* Set the default file name. I am not sure whether ".p12" or ".pem" is better for an _armored_ pkcs#12. */ default_comp = g_strdup_printf ("%s%csecret-key-%s.%s", gnupg_homedir, G_DIR_SEPARATOR, key_id, is_x509? "p12":"asc"); gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), default_comp); g_free (default_comp); response = gtk_dialog_run (GTK_DIALOG (dialog)); if (response == GTK_RESPONSE_OK) { filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); if (filename) g_strdup (filename); } gtk_widget_hide (dialog); return filename; } static gboolean gpa_backup_operation_idle_cb (gpointer data) { GpaBackupOperation *op = data; gchar *file; file = gpa_backup_operation_dialog_run (GPA_OPERATION (op)->window, op->key_id, !!(op->protocol==GPGME_PROTOCOL_CMS)); if (file) gpa_backup_operation_do_backup (op, file); /* FIXME: Error handling. */ g_signal_emit_by_name (GPA_OPERATION (op), "completed", 0); return FALSE; /* Remove us from the idle chain. */ } /* API */ GpaBackupOperation* gpa_backup_operation_new (GtkWidget *window, gpgme_key_t key) { GpaBackupOperation *op; op = g_object_new (GPA_BACKUP_OPERATION_TYPE, "window", window, "key", key, "protocol", key->protocol, NULL); return op; } GpaBackupOperation* gpa_backup_operation_new_from_fpr (GtkWidget *window, const gchar *fpr, gpgme_protocol_t protocol) { GpaBackupOperation *op; op = g_object_new (GPA_BACKUP_OPERATION_TYPE, "window", window, "fpr", fpr, "protocol", protocol, NULL); return op; } diff --git a/src/gpadatebutton.c b/src/gpadatebutton.c index 28840c3..95534a5 100644 --- a/src/gpadatebutton.c +++ b/src/gpadatebutton.c @@ -1,327 +1,327 @@ /* gpadatebutton.c - A button to show and select a date. * Copyright (C) 2009 g10 Code GmbH * * This file is part of GPA. * * GPA 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 3 of the License, or * (at your option) any later version. * * GPA 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, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "gpadatebutton.h" #include "i18n.h" /* Object's class definition. */ struct _GpaDateButtonClass { GtkButtonClass parent_class; /* The signal function for "date-set". */ void (*date_set)(GpaDateButton *self); }; /* Object definition. */ struct _GpaDateButton { GtkButton parent_instance; GtkWidget *dialog; /* NULL or the dialog popup window. */ GtkWidget *calendar; /* The calendar object. */ GtkWidget *label; guint current_year; guint current_month; /* 1..12 ! */ guint current_day; int ignore_next_selection; }; /* The parent class. */ static GObjectClass *parent_class; /* Local prototypes */ static void gpa_date_button_finalize (GObject *object); /************************************************************ ******************* Implementation ********************* ************************************************************/ static void update_widgets (GpaDateButton *self) { char buf[20]; if (!self->current_day && !self->current_month && !self->current_year) *buf = 0; else snprintf (buf, sizeof buf, "%04d-%02d-%02d", self->current_year, self->current_month, self->current_day); gtk_label_set_text (GTK_LABEL (self->label), *buf? buf : _("(not set)")); if (self->calendar && *buf) { gtk_calendar_select_month (GTK_CALENDAR (self->calendar), self->current_month-1, self->current_year); gtk_calendar_select_day (GTK_CALENDAR (self->calendar), self->current_day); } } /* Signal handler for "destroy" to the dialog window. */ static void destroy_cb (GtkWidget *widget, gpointer user_data) { GpaDateButton *self = GPA_DATE_BUTTON (user_data); self->dialog = NULL; } static void day_selected_cb (GtkWidget *widget, gpointer user_data) { GpaDateButton *self = GPA_DATE_BUTTON (user_data); if (self->ignore_next_selection) { self->ignore_next_selection = 0; return; } gtk_calendar_get_date (GTK_CALENDAR (self->calendar), &self->current_year, &self->current_month, &self->current_day); self->current_month++; update_widgets (self); g_signal_emit_by_name (self, "date-set"); gtk_widget_destroy (self->dialog); } static void month_changed_cb (GtkWidget *widget, gpointer user_data) { GpaDateButton *self = GPA_DATE_BUTTON (user_data); self->ignore_next_selection = 1; } /* Create the widgets. */ static void create_widgets (GpaDateButton *self) { self->label = gtk_label_new (NULL); gtk_label_set_justify (GTK_LABEL (self->label), GTK_JUSTIFY_LEFT); update_widgets (self); gtk_widget_show (self->label); gtk_container_add (GTK_CONTAINER (self), self->label); } /************************************************************ ****************** Object Management ******************** ************************************************************/ /* Overloaded method for clicked. */ static void gpa_date_button_clicked (GtkButton *button) { GpaDateButton *self = GPA_DATE_BUTTON (button); GtkWidget *toplevel; if (!self->dialog) { toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self)); if (!gtk_widget_is_toplevel (toplevel)) toplevel = NULL; self->dialog = gtk_dialog_new_with_buttons (NULL, GTK_WINDOW (toplevel), (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), - GTK_STOCK_CLOSE, GTK_RESPONSE_REJECT, + _("_Close"), GTK_RESPONSE_REJECT, NULL); g_signal_connect (self->dialog, "destroy", G_CALLBACK (destroy_cb), self); g_signal_connect_swapped (self->dialog, "response", G_CALLBACK (gtk_widget_destroy), self->dialog); self->calendar = gtk_calendar_new (); GtkWidget *box = gtk_dialog_get_content_area(GTK_DIALOG(self->dialog)); gtk_container_add (GTK_CONTAINER (box), self->calendar); g_signal_connect (self->calendar, "day-selected", G_CALLBACK (day_selected_cb), self); g_signal_connect (self->calendar, "month-changed", G_CALLBACK (month_changed_cb), self); gtk_widget_show_all (self->dialog); } update_widgets (self); gtk_window_present (GTK_WINDOW (self->dialog)); } static void gpa_date_button_class_init (void *class_ptr, void *class_data) { GpaDateButtonClass *klass = class_ptr; (void)class_data; parent_class = g_type_class_peek_parent (klass); G_OBJECT_CLASS (klass)->finalize = gpa_date_button_finalize; GTK_BUTTON_CLASS (klass)->clicked = gpa_date_button_clicked; g_signal_new ("date-set", G_TYPE_FROM_CLASS (G_OBJECT_CLASS (klass)), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GpaDateButtonClass, date_set), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void gpa_date_button_init (GTypeInstance *instance, void *class_ptr) { GpaDateButton *self = GPA_DATE_BUTTON (instance); (void)class_ptr; create_widgets (self); } static void gpa_date_button_finalize (GObject *object) { GpaDateButton *self = GPA_DATE_BUTTON (object); (void)self; parent_class->finalize (object); } /* Construct the class. */ GType gpa_date_button_get_type (void) { static GType this_type = 0; if (!this_type) { static const GTypeInfo this_info = { sizeof (GpaDateButtonClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, gpa_date_button_class_init, (GClassFinalizeFunc) NULL, NULL, /* class_data */ sizeof (GpaDateButton), 0, /* n_preallocs */ gpa_date_button_init }; this_type = g_type_register_static (GTK_TYPE_BUTTON, "GpaDateButton", &this_info, 0); } return this_type; } /************************************************************ ********************** Public API ************************ ************************************************************/ GtkWidget * gpa_date_button_new (void) { GtkWidget *obj; obj = GTK_WIDGET (g_object_new (GPA_DATE_BUTTON_TYPE, NULL)); return obj; } void gpa_date_button_set_date (GpaDateButton *self, GDate *date) { g_return_if_fail (IS_GPA_DATE_BUTTON (self)); if (!date) { self->current_day = 0; self->current_month = 0; self->current_year = 0; } else { self->current_day = g_date_get_day (date); self->current_month = g_date_get_month (date); self->current_year = g_date_get_year (date); } update_widgets (self); } /* Store the current date at R_DATE. Returns true if the date is valid. */ gboolean gpa_date_button_get_date (GpaDateButton *self, GDate *r_date) { g_return_val_if_fail (IS_GPA_DATE_BUTTON (self), FALSE); g_date_clear (r_date, 1); if (!g_date_valid_dmy (self->current_day, self->current_month, self->current_year)) return FALSE; g_date_set_dmy (r_date, self->current_day, self->current_month, self->current_year); return TRUE; } diff --git a/src/gpaexportfileop.c b/src/gpaexportfileop.c index af6d700..ae42eac 100644 --- a/src/gpaexportfileop.c +++ b/src/gpaexportfileop.c @@ -1,199 +1,199 @@ /* gpaexportfileop.c - The GpaExportFileOperation object. * Copyright (C) 2003, Miguel Coca. * Copyright (C) 2008 g10 Code GmbH. * * This file is part of GPA * * GPA 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. * * GPA 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include "gpa.h" #include "i18n.h" #include "gtktools.h" #include "gpaexportfileop.h" static GObjectClass *parent_class = NULL; static gboolean gpa_export_file_operation_get_destination (GpaExportOperation *operation, gpgme_data_t *dest, gboolean *armor); static void gpa_export_file_operation_complete_export (GpaExportOperation *operation); /* GObject boilerplate */ static void gpa_export_file_operation_finalize (GObject *object) { GpaExportFileOperation *op = GPA_EXPORT_FILE_OPERATION (object); /* Cleanup */ if (op->fd != -1) { close (op->fd); } if (op->file) { g_free (op->file); } G_OBJECT_CLASS (parent_class)->finalize (object); } static void gpa_export_file_operation_init (GpaExportFileOperation *op) { op->file = NULL; op->fd = -1; } static GObject* gpa_export_file_operation_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *object; /* GpaExportFileOperation *op; */ /* Invoke parent's constructor */ object = parent_class->constructor (type, n_construct_properties, construct_properties); /* op = GPA_EXPORT_FILE_OPERATION (object); */ return object; } static void gpa_export_file_operation_class_init (GpaExportFileOperationClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GpaExportOperationClass *export_class = GPA_EXPORT_OPERATION_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->constructor = gpa_export_file_operation_constructor; object_class->finalize = gpa_export_file_operation_finalize; export_class->get_destination = gpa_export_file_operation_get_destination; export_class->complete_export = gpa_export_file_operation_complete_export; } GType gpa_export_file_operation_get_type (void) { static GType file_operation_type = 0; if (!file_operation_type) { static const GTypeInfo file_operation_info = { sizeof (GpaExportFileOperationClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gpa_export_file_operation_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GpaExportFileOperation), 0, /* n_preallocs */ (GInstanceInitFunc) gpa_export_file_operation_init, }; file_operation_type = g_type_register_static (GPA_EXPORT_OPERATION_TYPE, "GpaExportFileOperation", &file_operation_info, 0); } return file_operation_type; } /* Virtual methods */ static gboolean gpa_export_file_operation_get_destination (GpaExportOperation *operation, gpgme_data_t *dest, gboolean *armor) { GpaExportFileOperation *op = GPA_EXPORT_FILE_OPERATION (operation); GtkWidget *dialog; GtkResponseType response; GtkWidget *armor_check = NULL; dialog = gtk_file_chooser_dialog_new (_("Export public keys to file"), GTK_WINDOW (GPA_OPERATION (op)->window), - GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL); + GTK_FILE_CHOOSER_ACTION_SAVE, _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Save"), GTK_RESPONSE_OK, NULL); gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); /* Customize the dialog, adding the "armor" option. */ if (! gpa_options_get_simplified_ui (gpa_options_get_instance ())) { armor_check = gtk_check_button_new_with_mnemonic (_("_armor")); gtk_widget_show_all (armor_check); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (armor_check), *armor); gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), armor_check); } /* Run the dialog until there is a valid response. */ do { response = gtk_dialog_run (GTK_DIALOG (dialog)); /* Save the selected file, free'ing the previous value if required. */ if (op->file) g_free (op->file); op->file = g_strdup (gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog))); *armor = (armor_check == NULL) ? TRUE : gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (armor_check)); } while (response == GTK_RESPONSE_OK && (op->fd = gpa_open_output_direct (op->file, dest, GPA_OPERATION (op)->window)) == -1); gtk_widget_destroy (dialog); return (response == GTK_RESPONSE_OK); } static void gpa_export_file_operation_complete_export (GpaExportOperation *operation) { GpaExportFileOperation *op = GPA_EXPORT_FILE_OPERATION (operation); gchar *message = g_strdup_printf (_("The keys have been exported to %s."), op->file); gpa_window_message (message, GPA_OPERATION (op)->window); g_free (message); } /* API */ GpaExportFileOperation* gpa_export_file_operation_new (GtkWidget *window, GList *keys) { GpaExportFileOperation *op; op = g_object_new (GPA_EXPORT_FILE_OPERATION_TYPE, "window", window, "keys", keys, NULL); return op; } diff --git a/src/gpaimportfileop.c b/src/gpaimportfileop.c index 81d7995..0f52e99 100644 --- a/src/gpaimportfileop.c +++ b/src/gpaimportfileop.c @@ -1,174 +1,174 @@ /* gpaimportfileop.c - The GpaImportFileOperation object. * Copyright (C) 2003, Miguel Coca. * Copyright (C) 2008 g10 Code GmbH. * * This file is part of GPA * * GPA 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. * * GPA 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include "gpa.h" #include "i18n.h" #include "gtktools.h" #include "gpaimportfileop.h" static GObjectClass *parent_class = NULL; static gboolean gpa_import_file_operation_get_source (GpaImportOperation *operation); static void gpa_import_file_operation_complete_import (GpaImportOperation *operation); /* GObject boilerplate */ static void gpa_import_file_operation_finalize (GObject *object) { GpaImportFileOperation *op = GPA_IMPORT_FILE_OPERATION (object); /* Cleanup */ if (op->fd != -1) close (op->fd); if (op->file) g_free (op->file); G_OBJECT_CLASS (parent_class)->finalize (object); } static void gpa_import_file_operation_init (GpaImportFileOperation *op) { op->file = NULL; op->fd = -1; } static GObject* gpa_import_file_operation_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *object; /* GpaImportFileOperation *op; */ /* Invoke parent's constructor */ object = parent_class->constructor (type, n_construct_properties, construct_properties); /* op = GPA_IMPORT_FILE_OPERATION (object); */ return object; } static void gpa_import_file_operation_class_init (GpaImportFileOperationClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GpaImportOperationClass *import_class = GPA_IMPORT_OPERATION_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->constructor = gpa_import_file_operation_constructor; object_class->finalize = gpa_import_file_operation_finalize; import_class->get_source = gpa_import_file_operation_get_source; import_class->complete_import = gpa_import_file_operation_complete_import; } GType gpa_import_file_operation_get_type (void) { static GType file_operation_type = 0; if (!file_operation_type) { static const GTypeInfo file_operation_info = { sizeof (GpaImportFileOperationClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gpa_import_file_operation_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GpaImportFileOperation), 0, /* n_preallocs */ (GInstanceInitFunc) gpa_import_file_operation_init, }; file_operation_type = g_type_register_static (GPA_IMPORT_OPERATION_TYPE, "GpaImportFileOperation", &file_operation_info, 0); } return file_operation_type; } /* Virtual methods */ static gboolean gpa_import_file_operation_get_source (GpaImportOperation *operation) { GpaImportFileOperation *op = GPA_IMPORT_FILE_OPERATION (operation); GtkWidget *dialog; GtkResponseType response; dialog = gtk_file_chooser_dialog_new (_("Import keys from file"), GTK_WINDOW (GPA_OPERATION (op)->window), - GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); + GTK_FILE_CHOOSER_ACTION_OPEN, _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Open"), GTK_RESPONSE_OK, NULL); gpgme_data_release (operation->source); operation->source = NULL; /* Run the dialog until there is a valid response. */ do { response = gtk_dialog_run (GTK_DIALOG (dialog)); /* Save the selected file, free'ing the previous value if required. */ if (op->file) g_free (op->file); op->file = g_strdup (gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog))); } while (response == GTK_RESPONSE_OK && (op->fd = gpa_open_input (op->file, &operation->source, GPA_OPERATION (op)->window)) == -1); gtk_widget_destroy (dialog); return (response == GTK_RESPONSE_OK); } static void gpa_import_file_operation_complete_import (GpaImportOperation *operation) { /* Nothing special to do */ } /* API */ GpaImportFileOperation* gpa_import_file_operation_new (GtkWidget *window) { GpaImportFileOperation *op; op = g_object_new (GPA_IMPORT_FILE_OPERATION_TYPE, "window", window, NULL); return op; } diff --git a/src/gparecvkeydlg.c b/src/gparecvkeydlg.c index 476f528..1b0e805 100644 --- a/src/gparecvkeydlg.c +++ b/src/gparecvkeydlg.c @@ -1,201 +1,201 @@ /* gparecvkeydlg.c - The GNU Privacy Assistant Copyright (C) 2000, 2001 G-N-U GmbH. Copyright (C) 2008 g10 Code GmbH This file is part of GPA. GPA 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 3 of the License, or (at your option) any later version. GPA 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, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include "gpa.h" #include "gparecvkeydlg.h" #include "gtktools.h" /* Properties. */ enum { PROP_0, PROP_WINDOW, }; static GObjectClass *parent_class = NULL; static void gpa_receive_key_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GpaReceiveKeyDialog *dialog = GPA_RECEIVE_KEY_DIALOG (object); switch (prop_id) { case PROP_WINDOW: g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (dialog))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gpa_receive_key_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GpaReceiveKeyDialog *dialog = GPA_RECEIVE_KEY_DIALOG (object); switch (prop_id) { case PROP_WINDOW: gtk_window_set_transient_for (GTK_WINDOW (dialog), g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gpa_receive_key_dialog_finalize (GObject *object) { G_OBJECT_CLASS (parent_class)->finalize (object); } static void gpa_receive_key_dialog_init (GpaReceiveKeyDialog *dialog) { GtkWidget *label; GtkWidget *hbox; gtk_dialog_add_buttons (GTK_DIALOG (dialog), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_OK"), GTK_RESPONSE_OK, NULL); GtkWidget *box = gtk_dialog_get_content_area( GTK_DIALOG( dialog)); gtk_container_set_border_width (GTK_CONTAINER (box),10); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); label = gtk_label_new (is_gpg_version_at_least ("2.1.0")? _("Which key do you want to import?") : _("Which key do you want to import? (The key must " "be specified by key ID).")); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 10); dialog->entry = gtk_entry_new (); gtk_entry_set_activates_default (GTK_ENTRY (dialog->entry), TRUE); if (is_gpg_version_at_least ("2.1.0")) { gtk_box_pack_start (GTK_BOX (box), dialog->entry, FALSE, TRUE, 10); } else { hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (box), hbox, FALSE, TRUE, 10); label = gtk_label_new_with_mnemonic (_("Key _ID:")); gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->entry); gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), dialog->entry, TRUE, TRUE, 0); } } static void gpa_receive_key_dialog_class_init (GpaReceiveKeyDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = gpa_receive_key_dialog_finalize; object_class->set_property = gpa_receive_key_dialog_set_property; object_class->get_property = gpa_receive_key_dialog_get_property; /* Properties */ g_object_class_install_property (object_class, PROP_WINDOW, g_param_spec_object ("window", "Parent window", "Parent window", GTK_TYPE_WIDGET, G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY)); } GType gpa_receive_key_dialog_get_type (void) { static GType verify_dialog_type = 0; if (!verify_dialog_type) { static const GTypeInfo verify_dialog_info = { sizeof (GpaReceiveKeyDialogClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gpa_receive_key_dialog_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GpaReceiveKeyDialog), 0, /* n_preallocs */ (GInstanceInitFunc) gpa_receive_key_dialog_init, }; verify_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "GpaReceiveKeyDialog", &verify_dialog_info, 0); } return verify_dialog_type; } /* API */ /* Create a new receive key dialog. */ GtkWidget* gpa_receive_key_dialog_new (GtkWidget *parent) { GpaReceiveKeyDialog *dialog; dialog = g_object_new (GPA_RECEIVE_KEY_DIALOG_TYPE, "window", parent, NULL); return GTK_WIDGET(dialog); } /* Retrieve the selected key ID. */ const gchar* gpa_receive_key_dialog_get_id (GpaReceiveKeyDialog *dialog) { return gtk_entry_get_text (GTK_ENTRY (dialog->entry)); } diff --git a/src/gtktools.c b/src/gtktools.c index 61cace3..a6511c3 100644 --- a/src/gtktools.c +++ b/src/gtktools.c @@ -1,242 +1,242 @@ /* gtktools.c - The GNU Privacy Assistant Copyright (C) 2000, 2001 G-N-U GmbH. Copyright (C) 2008, 2014 g10 Code GmbH. This file is part of GPA. GPA 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 3 of the License, or (at your option) any later version. GPA 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, see . */ #ifdef HAVE_CONFIG_H # include #endif /* NOTE: Here are a lot of old GTK+ functions and wrappers. They should be replaced by modern GTK+ code and some of the wrappers are not needed anymore. */ #include #include #include #include "gpa.h" #include "gtktools.h" #include "gpawindowkeeper.h" #include "icons.h" /* Deprecated - use gpa_show_warning instead. */ void gpa_window_error (const gchar *message, GtkWidget *messenger) { gpa_show_warn (messenger, NULL, "%s", message); } /* Deprecated - use gpa_show_info instead. */ void gpa_window_message (const gchar *message, GtkWidget * messenger) { gpa_show_info (messenger, "%s", message); } /* Create a dialog with a textview containing STRING. */ static GtkWidget * create_diagnostics_dialog (GtkWidget *parent, const char *string) { GtkWidget *widget, *scrollwidget, *textview; GtkDialog *dialog; GtkTextBuffer *textbuffer; widget = gtk_dialog_new_with_buttons ("Diagnostics", parent? GTK_WINDOW (parent):NULL, GTK_DIALOG_MODAL, - GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL, + _("_Close"), GTK_RESPONSE_CANCEL, NULL); dialog = GTK_DIALOG (widget); gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); gtk_window_set_default_size (GTK_WINDOW (dialog), 570, 320); gtk_dialog_set_default_response (dialog, GTK_RESPONSE_CANCEL); scrollwidget = gtk_scrolled_window_new (NULL, NULL); gtk_container_set_border_width (GTK_CONTAINER (scrollwidget), 5); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwidget), GTK_SHADOW_IN); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwidget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); GtkWidget *box; box = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); gtk_box_pack_start (GTK_BOX (box), scrollwidget, TRUE, TRUE, 0); textview = gtk_text_view_new (); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (textview), GTK_WRAP_NONE); gtk_text_view_set_editable (GTK_TEXT_VIEW (textview), FALSE); gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (textview), FALSE); textbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview)); gtk_text_buffer_set_text (textbuffer, string, -1); gtk_container_add (GTK_CONTAINER (scrollwidget), textview); gtk_widget_show_all (widget); return widget; } static void show_gtk_message (GtkWidget *parent, GtkMessageType mtype, GpaContext *ctx, const char *format, va_list arg_ptr) { GtkWidget *dialog, *dialog2; char *buffer; buffer = g_strdup_vprintf (format, arg_ptr); dialog = gtk_message_dialog_new (parent? GTK_WINDOW (parent):NULL, GTK_DIALOG_MODAL, mtype, GTK_BUTTONS_CLOSE, "%s", buffer); g_free (buffer); buffer = NULL; if (ctx) gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("_Details"), GTK_RESPONSE_HELP, NULL); gtk_widget_show_all (dialog); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_HELP && ctx) { /* If requested and possible get diagnostics from GPGME. */ buffer = gpa_context_get_diag (ctx); if (!buffer) gpa_show_info (parent, "No diagnostic data available"); else { dialog2 = create_diagnostics_dialog (parent, buffer); g_free (buffer); gtk_dialog_run (GTK_DIALOG (dialog2)); gtk_widget_destroy (dialog2); } } gtk_widget_destroy (dialog); } /* Show a modal info message. */ void gpa_show_info (GtkWidget *parent, const char *format, ...) { va_list arg_ptr; va_start (arg_ptr, format); show_gtk_message (parent, GTK_MESSAGE_INFO, NULL, format, arg_ptr); va_end (arg_ptr); } /* Show a modal warning message. PARENT is the parent windows, CTX is * eitehr NULL or a related GPGME context to be used to allow shoing * additional information. */ void gpa_show_warn (GtkWidget *parent, GpaContext *ctx, const char *format, ...) { va_list arg_ptr; va_start (arg_ptr, format); show_gtk_message (parent, GTK_MESSAGE_WARNING, ctx, format, arg_ptr); va_end (arg_ptr); } /* Set a tooltip TEXT to WIDGET. TEXT and WIDGET may both be NULL. This function is useful so that GPA can be build with older GTK+ versions. */ void gpa_add_tooltip (GtkWidget *widget, const char *text) { #if GTK_CHECK_VERSION (2, 12, 0) if (widget && text && *text) { size_t len = strlen (text); if (text[len-1] == '\n') { /* Remove trailing line feeds. The reason for this may be * that the tooltip text is used for other purposes as * well. */ char *buf = g_strdup (text); for ( ;len && buf[len-1] == '\n'; len--) buf[len-1] = 0; if (*buf) gtk_widget_set_tooltip_text (widget, buf); g_free (buf); } else gtk_widget_set_tooltip_text (widget, text); } #endif } /* Set the title of COLUMN to TITLE and also set TOOLTIP. */ void gpa_set_column_title (GtkTreeViewColumn *column, const char *title, const char *tooltip) { GtkWidget *label; label = gtk_label_new (title); /* We need to show the label before setting the widget. */ gtk_widget_show (label); gtk_tree_view_column_set_widget (column, label); if (tooltip) gpa_add_tooltip (gtk_tree_view_column_get_widget (column), tooltip); } static void set_homogeneous (GtkWidget *widget, gpointer data) { gboolean *is_hom_p = data; gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), *is_hom_p); } /* Set the homogeneous property for all children of TOOLBAR to IS_HOM. */ void gpa_toolbar_set_homogeneous (GtkToolbar *toolbar, gboolean is_hom) { gtk_container_foreach (GTK_CONTAINER (toolbar), (GtkCallback) set_homogeneous, &is_hom); } /* Customized set title function. */ void gpa_window_set_title (GtkWindow *window, const char *string) { const char *prefix = GPA_LONG_NAME; char *buffer; if (!string || !*string) { gtk_window_set_title (window, prefix); } else { buffer = g_strdup_printf ("%s - %s", prefix, string); gtk_window_set_title (window, buffer); g_free (buffer); } } diff --git a/src/keygendlg.c b/src/keygendlg.c index 4a53b69..df8281e 100644 --- a/src/keygendlg.c +++ b/src/keygendlg.c @@ -1,411 +1,411 @@ /* keygendlg.c - The GNU Privacy Assistant Copyright (C) 2009 g10 Code GmbH This file is part of GPA. GPA 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 3 of the License, or (at your option) any later version. GPA 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, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include "gpa.h" #include "gpawidgets.h" #include "gtktools.h" #include "gpadatebox.h" #include "keygendlg.h" /* A table of algorithm combinations we offer to create. */ static struct { gpa_keygen_algo_t algo; const char *name; } algorithm_table[] = { { GPA_KEYGEN_ALGO_RSA_RSA, N_("RSA")}, { GPA_KEYGEN_ALGO_RSA, N_("RSA (sign only)")}, { GPA_KEYGEN_ALGO_DSA_ELGAMAL, N_("DSA")}, { GPA_KEYGEN_ALGO_DSA, N_("DSA (sign only)")}, { 0, NULL} }; struct _GpaKeyGenDlg { gboolean forcard; /* Specifies if this is a dialog for on-card key generation or not. */ GtkWidget *dialog; /* The dialog object. */ GtkWidget *entry_algo; /* Maybe NULL. */ GtkWidget *entry_keysize; /* Maybe NULL. */ GtkWidget *entry_name; GtkWidget *entry_email; GtkWidget *entry_comment; GtkWidget *entry_expire; GtkWidget *entry_backup; /* Maybe NULL. */ GtkWidget *label_userid; }; typedef struct _GpaKeyGenDlg GpaKeyGenDlg; static gboolean validate_name (GpaKeyGenDlg *self) { const char *s; s = gpa_validate_gpg_name (gtk_entry_get_text (GTK_ENTRY (self->entry_name))); if (s) gpa_window_error (s, self->dialog); return !s; } static gboolean validate_email (GpaKeyGenDlg *self) { const char *s; s = gpa_validate_gpg_email (gtk_entry_get_text (GTK_ENTRY (self->entry_email))); if (s) gpa_window_error (s, self->dialog); return !s; } static gboolean validate_comment (GpaKeyGenDlg *self) { const char *s; s = gpa_validate_gpg_comment (gtk_entry_get_text (GTK_ENTRY (self->entry_comment))); if (s) gpa_window_error (s, self->dialog); return !s; } /* This callback gets called each time the user clicks on the [OK] or [Cancel] buttons. If the button was [OK], it verifies that the input makes sense. */ static void response_cb (GtkDialog *dlg, gint response, gpointer user_data) { GpaKeyGenDlg *self = user_data; const char *temp; int keysize; if (response != GTK_RESPONSE_OK) return; temp = (self->entry_keysize ? gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (self->entry_keysize)) : NULL); keysize = temp? atoi (temp):0; if (!validate_name (self) || !validate_email (self) || !validate_comment (self)) { g_signal_stop_emission_by_name (dlg, "response"); } else if (self->forcard) ; else if (keysize < 1024) { gpa_window_error (_("You must enter a key size."), self->dialog); g_signal_stop_emission_by_name (dlg, "response"); } /* FIXME: check that the expire date is not in the past. */ } static void update_preview_cb (void *widget, void *user_data) { GpaKeyGenDlg *self = user_data; const char *name, *email, *comment; char *uid; (void)widget; name = gtk_entry_get_text (GTK_ENTRY (self->entry_name)); if (!name) name = ""; email = gtk_entry_get_text (GTK_ENTRY (self->entry_email)); if (!email) email = ""; comment = gtk_entry_get_text (GTK_ENTRY (self->entry_comment)); if (!comment) comment = ""; uid = g_strdup_printf ("%s%s%s%s%s%s%s", name, *comment? " (":"", comment, *comment? ")":"", *email? " <":"", email, *email? ">":""); gtk_label_set_text (GTK_LABEL (self->label_userid), uid); g_free (uid); } /* Helper to create the dialog. PARENT is the parent window. */ static void create_dialog (GpaKeyGenDlg *self, GtkWidget *parent, const char *forcard) { GtkWidget *dialog; GtkWidget *vbox; GtkWidget *grid; GtkWidget *hbox; GtkWidget *label; GtkWidget *combo; GtkWidget *entry; GtkWidget *button; int rowidx, idx; dialog = gtk_dialog_new_with_buttons (forcard ? _("Generate card key") : _("Generate key"), GTK_WINDOW (parent), GTK_DIALOG_MODAL, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_OK"), GTK_RESPONSE_OK, NULL); self->dialog = dialog; gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); // vbox = GTK_DIALOG (dialog)->vbox; vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); grid = gtk_grid_new (); gtk_container_set_border_width (GTK_CONTAINER (grid), 5); gtk_box_pack_start (GTK_BOX (vbox), grid, FALSE, FALSE, 0); rowidx = 0; label = gtk_label_new_with_mnemonic (_("_Algorithm: ")); gtk_widget_set_halign (GTK_WIDGET (label), 1.0); gtk_widget_set_valign (GTK_WIDGET (label), 0.5); gtk_grid_attach (GTK_GRID (grid), label, 0, rowidx, 1, 1); if (forcard) { label = gtk_label_new (forcard); gtk_widget_set_halign (GTK_WIDGET (label), 0.0); gtk_widget_set_valign (GTK_WIDGET (label), 0.5); gtk_grid_attach (GTK_GRID (grid), label, 1, rowidx, 1, 1); rowidx++; } else { combo = gtk_combo_box_text_new (); for (idx=0; algorithm_table[idx].name; idx++) gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), algorithm_table[idx].name); gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo); gtk_grid_attach (GTK_GRID (grid), combo, 1, rowidx, 1, 1); self->entry_algo = combo; rowidx++; label = gtk_label_new_with_mnemonic (_("_Key size (bits): ")); gtk_widget_set_halign (GTK_WIDGET (label), 1.0); gtk_widget_set_valign (GTK_WIDGET (label), 0.5); gtk_grid_attach (GTK_GRID (grid), label, 0, rowidx, 1, 1); combo = gtk_combo_box_text_new (); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "1024"); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "1536"); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "2048"); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "3072"); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "4096"); gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 2); gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo); gtk_grid_attach (GTK_GRID (grid), combo, 1, rowidx, 1, 1); self->entry_keysize = combo; rowidx++; } label = gtk_label_new (NULL); /* Dummy label. */ gtk_grid_attach (GTK_GRID (grid), label, 0, rowidx, 2, 1); rowidx++; label = gtk_label_new_with_mnemonic (_("User ID: ")); gtk_widget_set_halign (GTK_WIDGET (label), 1.0); gtk_widget_set_valign (GTK_WIDGET (label), 0.5); gtk_grid_attach (GTK_GRID (grid), label, 0, rowidx, 1, 1); label = gtk_label_new (NULL); gtk_widget_set_halign (GTK_WIDGET (label), 0.0); gtk_widget_set_valign (GTK_WIDGET (label), 0.5); gtk_grid_attach (GTK_GRID (grid), label, 1, rowidx, 1, 1); self->label_userid = label; rowidx++; label = gtk_label_new (NULL); /* Dummy label. */ gtk_grid_attach (GTK_GRID (grid), label, 0, rowidx, 2, 1); rowidx++; label = gtk_label_new_with_mnemonic (_("_Name: ")); gtk_widget_set_halign (GTK_WIDGET (label), 1.0); gtk_widget_set_valign (GTK_WIDGET (label), 0.5); gtk_grid_attach (GTK_GRID (grid), label, 0, rowidx, 1, 1); entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry); gtk_grid_attach (GTK_GRID (grid), entry, 1, rowidx, 1, 1); self->entry_name = entry; g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (update_preview_cb), self); rowidx++; label = gtk_label_new_with_mnemonic (_("_Email: ")); gtk_widget_set_halign (GTK_WIDGET (label), 1.0); gtk_widget_set_valign (GTK_WIDGET (label), 0.5); gtk_grid_attach (GTK_GRID (grid), label, 0, rowidx, 1, 1); entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry); gtk_grid_attach (GTK_GRID (grid), entry, 1, rowidx, 1, 1); self->entry_email = entry; g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (update_preview_cb), self); rowidx++; label = gtk_label_new_with_mnemonic (_("_Comment: ")); gtk_widget_set_halign (GTK_WIDGET (label), 1.0); gtk_widget_set_valign (GTK_WIDGET (label), 0.5); gtk_grid_attach (GTK_GRID (grid), label, 0, rowidx, 1, 1); entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry); gtk_grid_attach (GTK_GRID (grid), entry, 1, rowidx, 1, 1); self->entry_comment = entry; g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (update_preview_cb), self); rowidx++; label = gtk_label_new_with_mnemonic (_("_Expires: ")); gtk_widget_set_halign (GTK_WIDGET (label), 1.0); gtk_widget_set_valign (GTK_WIDGET (label), 0.5); gtk_grid_attach (GTK_GRID (grid), label, 0, rowidx, 1, 1); button = gpa_date_box_new (); gtk_grid_attach (GTK_GRID (grid), button, 1, rowidx, 1, 1); self->entry_expire = button; rowidx++; if (forcard) { label = gtk_label_new_with_mnemonic (_("Backup: ")); gtk_widget_set_halign (GTK_WIDGET (label), 1.0); gtk_widget_set_valign (GTK_WIDGET (label), 0.5); gtk_grid_attach (GTK_GRID (grid), label, 0, rowidx, 1, 1); button = gtk_check_button_new (); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); gtk_grid_attach (GTK_GRID (grid), hbox, 1, rowidx, 1, 1); self->entry_backup = button; gpa_add_tooltip (hbox, _("If checked the encryption key will be created " "and stored to a backup file and then loaded into " "the card. This is recommended so that encrypted " "messages can be decrypted even if the card has a " "malfunction.")); } else self->entry_backup = NULL; } /* Run the "Generate Key" dialog and if the user presses OK, return the values from the dialog in a newly allocated gpa_keygen_para_t struct. If FORCARD is not NULL display a dialog suitable for generation of keys on the OpenPGP smartcard; thye string will be shown to identify the capabilities of the card. If the user pressed "Cancel", return NULL. The returned struct has to be freed with gpa_keygen_para_free. */ gpa_keygen_para_t * gpa_key_gen_run_dialog (GtkWidget *parent, const char *forcard) { GpaKeyGenDlg *self; gpa_keygen_para_t *params; self = xcalloc (1, sizeof *self); self->forcard = !!forcard; create_dialog (self, parent, forcard); g_signal_connect (G_OBJECT (self->dialog), "response", G_CALLBACK (response_cb), self); gtk_widget_show_all (self->dialog); if (gtk_dialog_run (GTK_DIALOG (self->dialog)) != GTK_RESPONSE_OK) { gtk_widget_destroy (self->dialog); g_free (self); return NULL; } /* The user pressed OK: Populate gpa_keygen_para_t struct and return it. */ params = gpa_keygen_para_new (); params->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->entry_name))); params->email = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->entry_email))); params->comment= g_strdup (gtk_entry_get_text (GTK_ENTRY (self->entry_comment))); if (forcard) params->algo = GPA_KEYGEN_ALGO_VIA_CARD; else { char *temp; int idx; idx = gtk_combo_box_get_active (GTK_COMBO_BOX (self->entry_algo)); if (idx < 0 || idx >= DIM (algorithm_table) || !algorithm_table[idx].name) { gpa_keygen_para_free (params); gtk_widget_destroy (self->dialog); g_free (self); g_return_val_if_reached (NULL); } params->algo = algorithm_table[idx].algo; temp = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (self->entry_keysize)); params->keysize = temp? atoi (temp) : 0; } gpa_date_box_get_date (GPA_DATE_BOX (self->entry_expire), ¶ms->expire); params->backup = self->entry_backup ? gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->entry_backup)) : 0; gtk_widget_destroy (self->dialog); g_free (self); return params; } diff --git a/src/keyimpseldlg.c b/src/keyimpseldlg.c index e811bea..06153ff 100644 --- a/src/keyimpseldlg.c +++ b/src/keyimpseldlg.c @@ -1,168 +1,168 @@ /* keyimpseldlg.c - The GNU Privacy Assistant - Key import selection dialog Copyright (C) 2002 G-N-U GmbH Copyright (C) 2008 g10 Code GmbH. This file is part of GPA GPA 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 3 of the License, or (at your option) any later version. GPA 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, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "gpa.h" #include "gtktools.h" #include "gpawidgets.h" #include "keyimpseldlg.h" typedef struct _GPAKeyImportSelectionDialog { GtkWidget *window; const gchar *keyserver; GtkCList *clist_which; GList *keys, *imported_keys; } GPAKeyImportSelectionDialog; static void key_import_selection_do_import (GPAKeyImportSelectionDialog *dialog) { if (dialog->clist_which->selection) { gint row = GPOINTER_TO_INT (dialog->clist_which->selection->data); gchar *key_id = gtk_clist_get_row_data (dialog->clist_which, row); gchar *full_key_id = g_strconcat ("0x", key_id, NULL); #if 0 /* FIXME: Reimplement this when gpgme supports searches */ gpapa_receive_public_key_from_server (full_key_id, dialog->keyserver, gpa_callback, dialog->window); #endif g_free (full_key_id); } } static void key_import_selection_ok (gpointer param) { GPAKeyImportSelectionDialog *dialog = param; if (!dialog->clist_which->selection) { gpa_window_error (_("No keys selected"), dialog->window); return; } key_import_selection_do_import (dialog); gtk_widget_destroy (dialog->window); } static void key_import_selection_cancel (gpointer param) { GPAKeyImportSelectionDialog *dialog = param; dialog->imported_keys = NULL; gtk_widget_destroy (dialog->window); } static void key_import_selection_destroy (GtkWidget *widget, gpointer param) { g_application_quit (); } /* Run the key import selection dialog and import the selected keys from the given keyserver. */ void gpa_key_import_selection_dialog_run (GtkWidget *parent, GList *keys, const gchar *keyserver) { GPAKeyImportSelectionDialog dialog; GtkWidget *windowSelect; GtkWidget *vboxSelect; GtkWidget *vboxWhich; GtkWidget *labelWhich; GtkWidget *scrollerWhich; GtkWidget *clistWhich; GtkWidget *hButtonBoxSelect; GtkWidget *buttonCancel; GtkWidget *buttonSelect; dialog.keys = keys; dialog.imported_keys = NULL; dialog.keyserver = keyserver; if (g_list_length (dialog.keys) == 0) { gpa_window_error (_("Keyserver did not return any matching keys."), parent); return; } windowSelect = gtk_window_new (GTK_WINDOW_TOPLEVEL); gpa_window_set_title (GTK_WINDOW (windowSelect), _("Select keys to import")); dialog.window = windowSelect; g_signal_connect (G_OBJECT (windowSelect), "destroy", G_CALLBACK (key_import_selection_destroy), NULL); vboxSelect = gtk_vbox_new (FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (vboxSelect), 5); vboxWhich = gtk_vbox_new (FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (vboxWhich), 5); gtk_box_pack_start (GTK_BOX (vboxSelect), vboxWhich, TRUE, TRUE, 0); labelWhich = gtk_label_new_with_mnemonic (_("_Import")); gtk_misc_set_alignment (GTK_MISC (labelWhich), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (vboxWhich), labelWhich, FALSE, TRUE, 0); scrollerWhich = gtk_scrolled_window_new (NULL, NULL); gtk_widget_set_size_request (scrollerWhich, 260, 75); gtk_box_pack_start (GTK_BOX (vboxWhich), scrollerWhich, TRUE, TRUE, 0); clistWhich = gpa_key_list_new_from_glist (parent, dialog.keys); dialog.clist_which = GTK_CLIST (clistWhich); gtk_container_add (GTK_CONTAINER (scrollerWhich), clistWhich); gtk_label_set_mnemonic_widget (GTK_LABEL (labelWhich), clistWhich); hButtonBoxSelect = gtk_hbutton_box_new (); gtk_box_pack_start (GTK_BOX (vboxSelect), hButtonBoxSelect, FALSE, FALSE, 0); gtk_button_box_set_layout (GTK_BUTTON_BOX (hButtonBoxSelect), GTK_BUTTONBOX_END); gtk_button_box_set_spacing (GTK_BUTTON_BOX (hButtonBoxSelect), 10); gtk_container_set_border_width (GTK_CONTAINER (hButtonBoxSelect), 5); - buttonSelect = gtk_button_new_from_stock (GTK_STOCK_OK); + buttonSelect = gtk_button_new_from_stock (_("_OK")); g_signal_connect_swapped (G_OBJECT (buttonSelect), "clicked", G_CALLBACK (key_import_selection_ok), &dialog); gtk_container_add (GTK_CONTAINER (hButtonBoxSelect), buttonSelect); - buttonCancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL); + buttonCancel = gtk_button_new_from_stock (_("_Cancel")); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (key_import_selection_cancel), &dialog); gtk_container_add (GTK_CONTAINER (hButtonBoxSelect), buttonCancel); gtk_container_add (GTK_CONTAINER (windowSelect), vboxSelect); gtk_window_set_modal (GTK_WINDOW (windowSelect), TRUE); gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (parent)); gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER_ON_PARENT); gtk_widget_show_all (window); gtk_main (); } diff --git a/src/ownertrustdlg.c b/src/ownertrustdlg.c index 3f2f6e4..83ad49f 100644 --- a/src/ownertrustdlg.c +++ b/src/ownertrustdlg.c @@ -1,259 +1,259 @@ /* keyring.c - The GNU Privacy Assistant * Copyright (C) 2000, 2001 G-N-U GmbH. * * This file is part of GPA * * GPA 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. * * GPA 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include "gpa.h" #include "gpawidgets.h" #include "gtktools.h" #include "gpgmeedit.h" /* * Owner Trust dialog */ static void init_radio_buttons (gpgme_validity_t trust, GtkWidget *unknown_radio, GtkWidget *never_radio, GtkWidget *marginal_radio, GtkWidget *full_radio, GtkWidget *ultimate_radio) { switch (trust) { case GPGME_VALIDITY_UNKNOWN: case GPGME_VALIDITY_UNDEFINED: gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (unknown_radio), TRUE); break; case GPGME_VALIDITY_NEVER: gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (never_radio), TRUE); break; case GPGME_VALIDITY_MARGINAL: gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (marginal_radio), TRUE); break; case GPGME_VALIDITY_FULL: gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (full_radio), TRUE); break; case GPGME_VALIDITY_ULTIMATE: gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ultimate_radio), TRUE); break; } } static gpgme_validity_t get_selected_validity (GtkWidget *unknown_radio, GtkWidget *never_radio, GtkWidget *marginal_radio, GtkWidget *full_radio, GtkWidget *ultimate_radio) { if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (unknown_radio))) { return GPGME_VALIDITY_UNKNOWN; } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (never_radio))) { return GPGME_VALIDITY_NEVER; } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (marginal_radio))) { return GPGME_VALIDITY_MARGINAL; } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (full_radio))) { return GPGME_VALIDITY_FULL; } else { return GPGME_VALIDITY_ULTIMATE; } } /* Run the owner trust dialog modally. */ gboolean gpa_ownertrust_run_dialog (gpgme_key_t key, GtkWidget *parent, gpgme_validity_t *return_trust) { GtkWidget *dialog; GtkWidget *key_info; GtkWidget *grid; GtkWidget *frame; GtkWidget *unknown_radio, *never_radio, *marginal_radio, *full_radio, *ultimate_radio; GtkWidget *label; GtkResponseType response; gpgme_validity_t trust = key->owner_trust; gboolean result; /* Create the dialog */ dialog = gtk_dialog_new_with_buttons (_("Change key ownertrust"), GTK_WINDOW(parent), GTK_DIALOG_MODAL, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_OK"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); key_info = gpa_key_info_new (key); GtkWidget *box = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); gtk_box_pack_start(GTK_BOX (box), key_info, FALSE, FALSE, 0); /* Create the "Owner Trust" frame */ frame = gtk_frame_new (_("Owner Trust")); gtk_box_pack_start (GTK_BOX (box), frame, FALSE, FALSE, 0); grid = gtk_grid_new(); unknown_radio = gtk_radio_button_new (NULL); gtk_grid_attach(GTK_GRID(grid), unknown_radio, 0, 0, 1, 1); label = gtk_label_new_with_mnemonic (_("_Unknown")); gtk_label_set_mnemonic_widget (GTK_LABEL (label), unknown_radio); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_widget_set_valign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID (grid), label, 1, 0, 1, 1); label = gtk_label_new (_("You don't know how much to trust this user to " "verify other people's keys.\n")); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_widget_set_valign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID (grid), label, 1, 1, 1, 1); never_radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (unknown_radio)); gtk_grid_attach(GTK_GRID (grid), never_radio, 0, 2, 1, 1); label = gtk_label_new_with_mnemonic (_("_Never")); gtk_label_set_mnemonic_widget (GTK_LABEL (label), never_radio); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_widget_set_valign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID (grid), label, 1, 2, 1, 1); label = gtk_label_new (_("You don't trust this user at all to verify the " "validity of other people's keys at all.\n")); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_widget_set_valign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID (grid), label, 1, 3, 1, 1); marginal_radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (unknown_radio)); gtk_grid_attach(GTK_GRID (grid), marginal_radio, 0, 4, 1, 1); label = gtk_label_new_with_mnemonic (_("_Marginal")); gtk_label_set_mnemonic_widget (GTK_LABEL (label), marginal_radio); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_widget_set_valign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID (grid), label, 1, 4, 1, 1); label = gtk_label_new (_("You don't trust this user's ability to " "verify the validity of other people's keys " "enough to consider keys valid based on his/her " "sole word.\n" "However, provided this user's key is " "valid, you will consider a key signed by this " "user valid if it is also signed by at least " "other two marginally trusted users with " "valid keys\n")); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_widget_set_valign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID (grid), label, 1, 5, 1, 1); full_radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (unknown_radio)); gtk_grid_attach(GTK_GRID (grid), full_radio, 0, 6, 1, 1); label = gtk_label_new_with_mnemonic (_("_Full")); gtk_label_set_mnemonic_widget (GTK_LABEL (label), full_radio); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_widget_set_valign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID (grid), label, 1, 6, 1, 1); label = gtk_label_new (_("You trust this user's ability to " "verify the validity of other people's keys " "so much, that you'll consider valid any key " "signed by him/her, provided this user's key " "is valid.\n")); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_widget_set_valign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID (grid), label, 1, 7, 1, 1); ultimate_radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (unknown_radio)); gtk_grid_attach(GTK_GRID (grid), ultimate_radio, 0, 8, 1, 1); label = gtk_label_new_with_mnemonic (_("U_ltimate")); gtk_label_set_mnemonic_widget (GTK_LABEL (label), ultimate_radio); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_widget_set_valign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID (grid), label, 1, 8, 1, 1); label = gtk_label_new (_("You consider this key valid, and trust the user " "so much that you will consider any key signed " "by him/her fully valid.\n\n" "(Warning: This is intended to be used for keys " "you own. Don't use it with other people's keys " "unless you really know what you are doing)\n")); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_widget_set_valign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID (grid), label, 1, 9, 1, 1); /* Initialize */ init_radio_buttons (trust, unknown_radio, never_radio, marginal_radio, full_radio, ultimate_radio); gtk_container_add (GTK_CONTAINER (frame), grid); gtk_window_resize(GTK_WINDOW(dialog), 400, 300); /* Run */ gtk_widget_show_all (dialog); response = gtk_dialog_run (GTK_DIALOG (dialog)); /* Return the ownertrust */ if (response == GTK_RESPONSE_OK) { gpgme_validity_t new_trust = get_selected_validity (unknown_radio, never_radio, marginal_radio, full_radio, ultimate_radio); /* If the user didn't change the trust, don't edit the key */ if (trust == new_trust || (trust == GPGME_VALIDITY_UNDEFINED && new_trust == GPGME_VALIDITY_UNKNOWN)) { result = FALSE; } else { *return_trust = new_trust; result = TRUE; } } else { result = FALSE; } gtk_widget_destroy (dialog); return result; } diff --git a/src/passwddlg.c b/src/passwddlg.c index d821ebf..25c6233 100644 --- a/src/passwddlg.c +++ b/src/passwddlg.c @@ -1,161 +1,161 @@ /* passwddlg.c - The GNU Privacy Assistant * Copyright (C) 2002, Miguel Coca. * * This file is part of GPA * * GPA 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. * * GPA 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include "gpa.h" #include "passwddlg.h" #include "gtktools.h" #include "qdchkpwd.h" #include static void passwd_activated_cb (GtkWidget *entry, gpointer param) { GtkWidget *repeat_entry = param; gtk_widget_grab_focus (repeat_entry); } static gboolean is_passphrase_correct (GtkWidget *parent, const gchar *passwd, const gchar *repeat) { gboolean result = TRUE; if (!g_str_equal (passwd, repeat)) { gpa_window_error (_("In \"Passphrase\" and \"Repeat passphrase\",\n" "you must enter the same passphrase."), parent); result = FALSE; } else if (strlen (passwd) == 0) { gpa_window_error (_("You did not enter a passphrase.\n" "It is needed to protect your private key."), parent); result = FALSE; } else if (strlen (passwd) < 10 || qdchkpwd (passwd) < 0.6) { GtkWidget *dialog; dialog = gtk_message_dialog_new (GTK_WINDOW (parent), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, _("Warning: You have entered a " "passphrase\n" "that is obviously not secure.\n\n" "Please enter a new passphrase.")); gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("_Enter new passphrase"), GTK_RESPONSE_CANCEL, _("Take this one _anyway"), GTK_RESPONSE_OK, NULL); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_CANCEL) { result = FALSE; } gtk_widget_destroy (dialog); } return result; } gpg_error_t gpa_change_passphrase_dialog_run (void *hook, const char *uid_hint, const char *passphrase_info, int prev_was_bad, int fd) { GtkWidget *dialog; GtkWidget *vbox; GtkWidget *grid; GtkWidget *label, *entry, *passwd_entry, *repeat_entry; GtkResponseType response; gchar *passwd = NULL; const gchar *repeat; dialog = gtk_dialog_new_with_buttons (_("Choose new passphrase"), NULL, GTK_DIALOG_MODAL, - GTK_STOCK_OK, GTK_RESPONSE_OK, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + _("_OK"), GTK_RESPONSE_OK, + _("_Cancel"), GTK_RESPONSE_CANCEL, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); grid = gtk_grid_new(); gtk_container_set_border_width (GTK_CONTAINER (grid), 5); gtk_box_pack_start (GTK_BOX (vbox), grid, FALSE, TRUE, 5); label = gtk_label_new (_("Passphrase: ")); gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1); gtk_widget_set_halign (GTK_WIDGET (label), 1.0); gtk_widget_set_valign (GTK_WIDGET (label), 0.5); entry = passwd_entry = gtk_entry_new (); gtk_grid_attach (GTK_GRID (grid), entry, 1, 0, 1, 1); gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE); label = gtk_label_new (_("Repeat Passphrase: ")); gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1); gtk_widget_set_halign (GTK_WIDGET (label), 1.0); gtk_widget_set_valign (GTK_WIDGET (label), 0.5); entry = repeat_entry = gtk_entry_new (); gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); gtk_grid_attach (GTK_GRID (grid), entry, 1, 1, 1, 1); gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE); /* Pressing enter on the passphrase entry switches the focus to the * "repeat" entry. */ g_signal_connect (G_OBJECT (passwd_entry), "activate", G_CALLBACK (passwd_activated_cb), repeat_entry); /* Run the dialog until the input is correct or the user cancels */ do { gtk_entry_set_text (GTK_ENTRY (passwd_entry), ""); gtk_entry_set_text (GTK_ENTRY (repeat_entry), ""); gtk_widget_grab_focus (passwd_entry); gtk_widget_show_all (dialog); response = gtk_dialog_run (GTK_DIALOG (dialog)); g_free (passwd); passwd = g_strdup (gtk_entry_get_text (GTK_ENTRY (passwd_entry))); repeat = gtk_entry_get_text (GTK_ENTRY (repeat_entry)); } while (response == GTK_RESPONSE_OK && !is_passphrase_correct (dialog, passwd, repeat)); gtk_widget_destroy (dialog); if (response == GTK_RESPONSE_OK) { write (fd, passwd, strlen (passwd)); g_free (passwd); /* GnuPG wants a newline here */ write (fd, "\n", 1); return gpg_error (GPG_ERR_NO_ERROR); } else { return gpg_error (GPG_ERR_CANCELED); } } diff --git a/src/recipientdlg.c b/src/recipientdlg.c index 0782d9c..2369d4f 100644 --- a/src/recipientdlg.c +++ b/src/recipientdlg.c @@ -1,1240 +1,1240 @@ /* recipientdlg.c - A dialog to select a mail recipient. Copyright (C) 2008 g10 Code GmbH. This file is part of GPA GPA 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 3 of the License, or (at your option) any later version. GPA 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, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include "gpa.h" #include "i18n.h" #include "gtktools.h" #include "selectkeydlg.h" #include "recipientdlg.h" struct _RecipientDlg { GtkDialog parent; GtkWidget *clist_keys; GtkWidget *statushint; GtkWidget *radio_pgp; GtkWidget *radio_x509; GtkWidget *radio_auto; GtkWidget *popup_menu; /* Flag to disable updates of the status hint. This is actual a counter with updates only allowed if it is zero. */ int freeze_update_statushint; /* Flag to disable any key selection. This is used while a key selection is active. Implemented as a counter. */ int freeze_key_selection; /* Set if this dialog has usable key to be passed back to the caller. You need to call update_statushint to set it. */ int usable; /* The selected protocol. This is also set by update_statushint. */ gpgme_protocol_t selected_protocol; }; struct _RecipientDlgClass { GtkDialogClass parent_class; }; /* The parent class. */ static GObjectClass *parent_class; /* Indentifiers for our properties. */ enum { PROP_0, PROP_WINDOW, PROP_FORCE_ARMOR }; /* For performance reasons we truncate the listing of ambiguous keys at a reasonable value. */ #define TRUNCATE_KEYSEARCH_AT 40 /* An object to keep information about keys. */ struct keyinfo_s { /* An array with associated key(s) or NULL if none found/selected. */ gpgme_key_t *keys; /* The allocated size of the KEYS array. This includes the terminating NULL entry. */ unsigned int dimof_keys; /* If set, indicates that the KEYS array has been truncated. */ int truncated:1; }; /* Management information for each recipient. This data is used per recipient. */ struct userdata_s { /* The recipient's address. */ char *mailbox; /* Information about PGP keys. */ struct keyinfo_s pgp; /* Information about X.509 keys. */ struct keyinfo_s x509; /* If the user has set this field, no encryption key will be required for the recipient. */ int ignore_recipient; }; /* Identifiers for the columns of the RECPLIST. */ enum { RECPLIST_MAILBOX, /* The rfc822 mailbox to whom a key needs to be associated. */ RECPLIST_HAS_PGP, /* A PGP certificate is available. */ RECPLIST_HAS_X509, /* An X.509 certificate is available. */ RECPLIST_KEYID, /* The key ID of the associated key. */ RECPLIST_USERDATA, /* Pointer to management information (struct userdata_s *). */ RECPLIST_N_COLUMNS }; /* Create the main list of this dialog. */ static GtkWidget * recplist_window_new (void) { GtkListStore *store; GtkWidget *list; GtkCellRenderer *renderer; GtkTreeViewColumn *column; /* Create a model and associate a view. */ store = gtk_list_store_new (RECPLIST_N_COLUMNS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER); list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); /* Define the columns. */ renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "markup", RECPLIST_MAILBOX, NULL); gpa_set_column_title (column, _("Recipient"), _("Shows the recipients of the message." " A key needs to be assigned to each recipient.")); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); renderer = gtk_cell_renderer_toggle_new (); column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "active", RECPLIST_HAS_PGP, NULL); gpa_set_column_title (column, "PGP", _("Checked if at least one matching" " OpenPGP certificate has been found.")); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); renderer = gtk_cell_renderer_toggle_new (); column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "active", RECPLIST_HAS_X509, NULL); gpa_set_column_title (column, "X.509", _("Checked if at least one matching" " X.509 certificate for use with S/MIME" " has been found.")); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "text", RECPLIST_KEYID, NULL); gpa_set_column_title (column, _("Key ID"), _("Shows the key ID of the selected key or" " an indication that a key needs to be selected.")); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); return list; } /* Get an interator for the selected row. Store it in ITER and returns the mdeol. if nothing is selected NULL is return and ITER is not valid. */ static GtkTreeModel * get_selected_row (RecipientDlg *dialog, GtkTreeIter *iter) { GtkTreeSelection *selection; GtkTreeModel *model; g_return_val_if_fail (dialog, NULL); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->clist_keys)); if (gtk_tree_selection_count_selected_rows (selection) == 1 && gtk_tree_selection_get_selected (selection, &model, iter)) return model; return NULL; } /* Compute and display a new help text for the statushint. */ static void update_statushint (RecipientDlg *dialog) { gpgme_protocol_t req_protocol, sel_protocol; GtkTreeModel *model; GtkTreeIter iter; int missing_keys = 0; int ambiguous_pgp_keys = 0; int ambiguous_x509_keys = 0; int n_pgp_keys = 0; int n_x509_keys = 0; int n_keys = 0; const char *hint; int okay = 0; if (dialog->freeze_update_statushint) return; model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->clist_keys)); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->radio_pgp))) req_protocol = GPGME_PROTOCOL_OpenPGP; else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->radio_x509))) req_protocol = GPGME_PROTOCOL_CMS; else req_protocol = GPGME_PROTOCOL_UNKNOWN; sel_protocol = GPGME_PROTOCOL_UNKNOWN; if (gtk_tree_model_get_iter_first (model, &iter)) { do { gboolean has_pgp, has_x509; struct userdata_s *info; gtk_tree_model_get (model, &iter, RECPLIST_HAS_PGP, &has_pgp, RECPLIST_HAS_X509, &has_x509, RECPLIST_USERDATA, &info, -1); if (!info) missing_keys++; /* Oops */ else if (info->ignore_recipient) ; else if (!info->pgp.keys && !info->x509.keys) missing_keys++; else if ((req_protocol == GPGME_PROTOCOL_OpenPGP && !has_pgp) ||(req_protocol == GPGME_PROTOCOL_CMS && !has_x509)) ; /* Not of the requested protocol. */ else { n_keys++; if (info->pgp.keys && info->pgp.keys[0]) { n_pgp_keys++; if (info->pgp.keys[1]) ambiguous_pgp_keys++; } if (info->x509.keys && info->x509.keys[0]) { n_x509_keys++; if (info->x509.keys[1]) ambiguous_x509_keys++; } } } while (gtk_tree_model_iter_next (model, &iter)); } if (req_protocol == GPGME_PROTOCOL_UNKNOWN) { /* We select the protocol with the most available keys, preferring PGP. */ if (n_pgp_keys >= n_x509_keys) sel_protocol = GPGME_PROTOCOL_OpenPGP; else if (n_x509_keys) sel_protocol = GPGME_PROTOCOL_CMS; } else sel_protocol = req_protocol; if (missing_keys) hint = _("You need to select a key for each recipient.\n" "To select a key right-click on the respective line."); else if ((sel_protocol == GPGME_PROTOCOL_OpenPGP && ambiguous_pgp_keys) || (sel_protocol == GPGME_PROTOCOL_CMS && ambiguous_x509_keys) || (sel_protocol == GPGME_PROTOCOL_UNKNOWN && (ambiguous_pgp_keys || ambiguous_x509_keys ))) hint = _("You need to select exactly one key for each recipient.\n" "To select a key right-click on the respective line."); else if ((sel_protocol == GPGME_PROTOCOL_OpenPGP && n_keys != n_pgp_keys) || (sel_protocol == GPGME_PROTOCOL_CMS && n_keys != n_x509_keys) || (sel_protocol == GPGME_PROTOCOL_UNKNOWN)) hint = _("Although you selected keys for all recipients " "a common encryption protocol can't be used. " "Please decide on one protocol by clicking one " "of the above radio buttons."); else if (n_pgp_keys && sel_protocol == GPGME_PROTOCOL_OpenPGP) { hint = _("Using OpenPGP for encryption."); okay = 1; } else if (n_x509_keys && sel_protocol == GPGME_PROTOCOL_CMS) { hint = _("Using S/MIME for encryption."); okay = 1; } else hint = _("No recipients - encryption is not possible"); gtk_label_set_text (GTK_LABEL (dialog->statushint), hint); gtk_label_set_line_wrap (GTK_LABEL (dialog->statushint), TRUE); dialog->usable = okay; dialog->selected_protocol = sel_protocol; gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, okay); } /* Add KEY to the keyarray of KEYINFO. Ownership of KEY is moved to KEYARRAY. Returns the number of keys in KEYINFO. */ static unsigned int append_key_to_keyinfo (struct keyinfo_s *keyinfo, gpgme_key_t key) { unsigned int nkeys; if (!keyinfo->keys) { keyinfo->dimof_keys = 5; /* Space for 4 keys. */ keyinfo->keys = g_new (gpgme_key_t, keyinfo->dimof_keys); keyinfo->keys[0] = NULL; } for (nkeys=0; keyinfo->keys[nkeys]; nkeys++) ; /* Note that we silently skip a KEY of NULL because we can't store a NULL in the array. */ if (key) { if (nkeys+1 >= keyinfo->dimof_keys) { keyinfo->dimof_keys += 10; keyinfo->keys = g_renew (gpgme_key_t, keyinfo->keys, keyinfo->dimof_keys); } keyinfo->keys[nkeys++] = key; keyinfo->keys[nkeys] = NULL; } return nkeys; } /* Clear the content of a keyinfo object. */ static void clear_keyinfo (struct keyinfo_s *keyinfo) { unsigned int nkeys; if (keyinfo) { if (keyinfo->keys) { for (nkeys=0; keyinfo->keys[nkeys]; nkeys++) gpgme_key_unref (keyinfo->keys[nkeys]); g_free (keyinfo->keys); keyinfo->keys = NULL; } keyinfo->dimof_keys = 0; keyinfo->truncated = 0; } } /* Update the row in the list described by by STORE and ITER. The new data shall be taken from INFO. */ static void update_recplist_row (GtkListStore *store, GtkTreeIter *iter, struct userdata_s *info) { char *infostr = NULL; char *oldinfostr = NULL; int any_pgp = 0, any_x509 = 0; gpgme_key_t key; char *mailbox; char *oldmailbox; if (info->pgp.keys && info->pgp.keys[0]) any_pgp = 1; if (info->x509.keys && info->x509.keys[0]) any_x509 = 1; if (info->ignore_recipient) infostr = NULL; else if (any_pgp && any_x509 && info->pgp.keys[1] && info->x509.keys[1]) infostr = g_strdup (_("[Ambiguous keys. Right-click to select]")); else if (any_pgp && info->pgp.keys[1]) infostr = g_strdup (_("[Ambiguous PGP key. Right-click to select]")); else if (any_x509 && info->x509.keys[1]) infostr = g_strdup (_("[Ambiguous X.509 key. Right-click to select]")); else if (any_pgp && !info->pgp.keys[1]) { /* Exactly one key found. */ key = info->pgp.keys[0]; infostr = gpa_gpgme_key_get_userid (key->uids); } else if (any_x509 && !info->x509.keys[1]) { key = info->x509.keys[0]; infostr = gpa_gpgme_key_get_userid (key->uids); } else infostr = g_strdup (_("[Right-click to select]")); mailbox = g_markup_printf_escaped ("%s", info->ignore_recipient? "true":"false", info->mailbox); g_print (" mbox=`%s' fmt=`%s'\n", info->mailbox, mailbox); gtk_tree_model_get (GTK_TREE_MODEL (store), iter, RECPLIST_MAILBOX, &oldmailbox, RECPLIST_KEYID, &oldinfostr, -1); gtk_list_store_set (store, iter, RECPLIST_MAILBOX, mailbox, RECPLIST_HAS_PGP, any_pgp, RECPLIST_HAS_X509, any_x509, RECPLIST_KEYID, infostr, -1); g_free (oldmailbox); g_free (mailbox); g_free (infostr); g_free (oldinfostr); } /* Parse one recipient, this is the working horse of parse_recipeints. */ static void parse_one_recipient (gpgme_ctx_t ctx, GtkListStore *store, GtkTreeIter *iter, struct userdata_s *info) { static int have_locate = -1; gpgme_key_t key = NULL; gpgme_keylist_mode_t mode; if (have_locate == -1) have_locate = is_gpg_version_at_least ("2.0.10"); g_return_if_fail (info); clear_keyinfo (&info->pgp); gpgme_set_protocol (ctx, GPGME_PROTOCOL_OpenPGP); mode = gpgme_get_keylist_mode (ctx); if (have_locate) gpgme_set_keylist_mode (ctx, (mode | (GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_EXTERN))); if (!gpgme_op_keylist_start (ctx, info->mailbox, 0)) { while (!gpgme_op_keylist_next (ctx, &key)) { if (key->revoked || key->disabled || key->expired || !key->can_encrypt) gpgme_key_unref (key); else if (append_key_to_keyinfo (&info->pgp, key) >= TRUNCATE_KEYSEARCH_AT) { /* Note that the truncation flag is not 100% correct. In case the next iteration would not yield a new key we have not actually truncated the search. */ info->pgp.truncated = 1; break; } } } gpgme_op_keylist_end (ctx); gpgme_set_keylist_mode (ctx, mode); clear_keyinfo (&info->x509); gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); if (!gpgme_op_keylist_start (ctx, info->mailbox, 0)) { while (!gpgme_op_keylist_next (ctx, &key)) { if (key->revoked || key->disabled || key->expired || !key->can_encrypt) gpgme_key_unref (key); else if (append_key_to_keyinfo (&info->x509,key) >= TRUNCATE_KEYSEARCH_AT) { info->x509.truncated = 1; break; } } } gpgme_op_keylist_end (ctx); update_recplist_row (store, iter, info); } /* Parse the list of recipients, find possible keys and update the store. */ static void parse_recipients (GtkListStore *store) { GtkTreeModel *model; GtkTreeIter iter; gpg_error_t err; gpgme_ctx_t ctx; err = gpgme_new (&ctx); if (err) gpa_gpgme_error (err); model = GTK_TREE_MODEL (store); /* Walk through the list, reading each row. */ if (gtk_tree_model_get_iter_first (model, &iter)) do { struct userdata_s *info; gtk_tree_model_get (model, &iter, RECPLIST_USERDATA, &info, -1); /* Do something with the data */ /*g_print ("parsing mailbox `%s'\n", info? info->mailbox:"(null)");*/ parse_one_recipient (ctx, store, &iter,info); } while (gtk_tree_model_iter_next (model, &iter)); gpgme_release (ctx); } /* Callback for the row-activated signal. */ static void recplist_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data) { /*RecipientDlg *dialog = user_data;*/ GtkTreeIter iter; GtkTreeModel *model; char *mailbox; model = gtk_tree_view_get_model (tree_view); if (!gtk_tree_model_get_iter (model, &iter, path)) return; gtk_tree_model_get (model, &iter, RECPLIST_MAILBOX, &mailbox, -1); g_free (mailbox); } static void recplist_row_changed_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *changediter, gpointer user_data) { RecipientDlg *dialog = user_data; g_return_if_fail (dialog); update_statushint (dialog); } static void rbutton_toggled_cb (GtkToggleButton *button, gpointer user_data) { RecipientDlg *dialog = user_data; GtkTreeViewColumn *column; int pgp = FALSE; int x509 = FALSE; if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->radio_pgp))) { pgp = TRUE; } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->radio_x509))) { x509 = TRUE; } else { pgp = TRUE; x509 = TRUE; } column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->clist_keys), RECPLIST_HAS_PGP); gtk_tree_view_column_set_visible (column, pgp); column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->clist_keys), RECPLIST_HAS_X509); gtk_tree_view_column_set_visible (column, x509); update_statushint (dialog); } /* The select key selection has returned. */ static void select_key_response_cb (SelectKeyDlg *seldlg, int response, void *user_data) { RecipientDlg *dialog = user_data; gpgme_key_t key; if (response != GTK_RESPONSE_OK) { /* The dialog was canceled */ gtk_widget_destroy (GTK_WIDGET (seldlg)); dialog->freeze_key_selection--; return; } key = select_key_dlg_get_key (seldlg); if (key) { GtkTreeModel *model; GtkTreeIter iter; struct userdata_s *info = NULL; char *uidstr = gpa_gpgme_key_get_userid (key->uids); g_free (uidstr); if ((model = get_selected_row (dialog, &iter))) { gtk_tree_model_get (model, &iter, RECPLIST_USERDATA, &info, -1); if (info) { if (key->protocol == GPGME_PROTOCOL_OpenPGP) { clear_keyinfo (&info->pgp); gpgme_key_ref (key); append_key_to_keyinfo (&info->pgp, key); } else if (key->protocol == GPGME_PROTOCOL_CMS) { clear_keyinfo (&info->x509); gpgme_key_ref (key); append_key_to_keyinfo (&info->x509, key); } update_recplist_row (GTK_LIST_STORE (model), &iter, info); update_statushint (dialog); } } gpgme_key_unref (key); } gtk_widget_destroy (GTK_WIDGET (seldlg)); dialog->freeze_key_selection--; } static void do_select_key (RecipientDlg *dialog, gpgme_protocol_t protocol) { GtkTreeModel *model; GtkTreeIter iter; struct userdata_s *info = NULL; SelectKeyDlg *seldlg; if ((model = get_selected_row (dialog, &iter))) { gtk_tree_model_get (model, &iter, RECPLIST_USERDATA, &info, -1); if (info) { gpgme_key_t *keys; if (protocol == GPGME_PROTOCOL_OpenPGP) keys = info->pgp.keys; else if (protocol == GPGME_PROTOCOL_CMS) keys = info->x509.keys; else keys = NULL; seldlg = select_key_dlg_new_with_keys (GTK_WIDGET (dialog), protocol, keys, info->mailbox); g_signal_connect (G_OBJECT (seldlg), "response", G_CALLBACK (select_key_response_cb), dialog); gtk_widget_show_all (GTK_WIDGET (seldlg)); } } else dialog->freeze_key_selection--; } static void recplist_popup_pgp (GSimpleAction *simple, GVariant *parameter, gpointer user_data) { RecipientDlg *dialog = user_data; do_select_key (dialog, GPGME_PROTOCOL_OpenPGP); } static void recplist_popup_x509 (GSimpleAction *simple, GVariant *parameter, gpointer user_data) { RecipientDlg *dialog = user_data; do_select_key (dialog, GPGME_PROTOCOL_CMS); } static void recplist_popup_ignore (GSimpleAction *simple, GVariant *parameter, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; struct userdata_s *info; RecipientDlg *dialog = user_data; if ((model = get_selected_row (dialog, &iter))) { gtk_tree_model_get (model, &iter, RECPLIST_USERDATA, &info, -1); info->ignore_recipient = !info->ignore_recipient; update_recplist_row (GTK_LIST_STORE (model), &iter, info); update_statushint (dialog); } dialog->freeze_key_selection--; } /* Left Click on the list auto selects an action. */ static void recplist_default_action (RecipientDlg *dialog) { dialog->freeze_key_selection--; } static gint recplist_display_popup_menu (RecipientDlg *dialog, GdkEvent *event, GtkListStore *list) { GtkMenu *menu; GdkEventButton *event_button; g_return_val_if_fail (dialog, FALSE); g_return_val_if_fail (event, FALSE); menu = GTK_MENU (dialog->popup_menu); if (event->type == GDK_BUTTON_PRESS) { event_button = (GdkEventButton *) event; if (event_button->button == 1 || event_button->button == 3) { GtkTreeSelection *selection; GtkTreePath *path; GtkTreeIter iter; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); /* Make sure the clicked key is selected. */ if (!dialog->freeze_key_selection && gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (list), event_button->x, event_button->y, &path, NULL, NULL, NULL)) { dialog->freeze_key_selection++; gtk_tree_model_get_iter (gtk_tree_view_get_model (GTK_TREE_VIEW (list)), &iter, path); if (!gtk_tree_selection_iter_is_selected (selection, &iter)) { gtk_tree_selection_unselect_all (selection); gtk_tree_selection_select_path (selection, path); } if (event_button->button == 1) recplist_default_action (dialog); else gtk_menu_popup_at_pointer (menu, NULL); } return TRUE; } } return FALSE; } /* Create the popup menu for the recipient list. */ static GtkWidget * recplist_popup_menu_new (GtkWidget *window, RecipientDlg *dialog) { static const GActionEntry entries [] = { { "select_gpg_key", recplist_popup_pgp }, { "select_cms_key", recplist_popup_x509 }, { "toggle_ignore_flag", recplist_popup_ignore }, }; static const char *menu_string = "" "" "
" "" "Select _PGP key" "app.select_pgp_key" "" "" "Select _S\\/MIME key" "app.select_cms_key" "" "" "Toggle _Ignore flag" "app.toggle_ignore_flag" "" "
" "
" "
"; GError *err = NULL; GtkWidget *popup_menu_widget; GtkBuilder *gtk_builder = gtk_builder_new (); if (gtk_builder_add_from_string( gtk_builder, menu_string , -1, &err) == 0) { printf("ERROR menu: %s \n", err->message); } GMenuModel *popup_menu_model = G_MENU_MODEL (gtk_builder_get_object (GTK_BUILDER (gtk_builder), "popup_menu")); popup_menu_widget = gtk_menu_new_from_model (popup_menu_model); GApplication *gpa_app = G_APPLICATION (get_gpa_application ()); g_action_map_add_action_entries (G_ACTION_MAP (gpa_app), entries, G_N_ELEMENTS (entries), window); return popup_menu_widget; } /************************************************************ ****************** Object Management ******************** ************************************************************/ static void recipient_dlg_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { RecipientDlg *dialog = RECIPIENT_DLG (object); switch (prop_id) { case PROP_WINDOW: g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (dialog))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void recipient_dlg_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { RecipientDlg *dialog = RECIPIENT_DLG (object); switch (prop_id) { case PROP_WINDOW: gtk_window_set_transient_for (GTK_WINDOW (dialog), g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void recipient_dlg_finalize (GObject *object) { /* Fixme: Release the store. */ G_OBJECT_CLASS (parent_class)->finalize (object); } static void recipient_dlg_init (RecipientDlg *dialog) { } static GObject* recipient_dlg_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *object; RecipientDlg *dialog; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *widget; GtkWidget *labelKeys; GtkWidget *scrollerKeys; GtkWidget *clistKeys; object = parent_class->constructor (type, n_construct_properties, construct_properties); dialog = RECIPIENT_DLG (object); gpa_window_set_title (GTK_WINDOW (dialog), _("Select keys for recipients")); gtk_dialog_add_buttons (GTK_DIALOG (dialog), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_OK"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE); gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); //vbox = GTK_DIALOG (dialog)->vbox; vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); labelKeys = gtk_label_new_with_mnemonic (_("_Recipient list")); gtk_widget_set_halign (GTK_WIDGET (labelKeys), GTK_ALIGN_START); gtk_widget_set_valign (GTK_WIDGET (labelKeys), GTK_ALIGN_CENTER); gtk_box_pack_start (GTK_BOX (vbox), labelKeys, FALSE, FALSE, 0); scrollerKeys = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollerKeys), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (vbox), scrollerKeys, TRUE, TRUE, 0); gtk_widget_set_size_request (scrollerKeys, 400, 200); clistKeys = recplist_window_new (); dialog->clist_keys = clistKeys; gtk_container_add (GTK_CONTAINER (scrollerKeys), clistKeys); gtk_label_set_mnemonic_widget (GTK_LABEL (labelKeys), clistKeys); dialog->popup_menu = recplist_popup_menu_new (dialog->clist_keys, dialog); g_signal_connect_swapped (G_OBJECT (dialog->clist_keys), "button_press_event", G_CALLBACK (recplist_display_popup_menu), dialog); dialog->radio_pgp = gtk_radio_button_new_with_mnemonic (NULL, _("Use _PGP")); dialog->radio_x509 = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (dialog->radio_pgp)), _("Use _X.509")); dialog->radio_auto = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (dialog->radio_pgp)), _("_Auto selection")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->radio_auto), TRUE); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), dialog->radio_pgp, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), dialog->radio_x509, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), dialog->radio_auto, FALSE, FALSE, 0); widget = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); dialog->statushint = gtk_label_new (NULL); gtk_box_pack_start (GTK_BOX (vbox), dialog->statushint, FALSE, FALSE, 0); g_signal_connect (G_OBJECT (GTK_TREE_VIEW (dialog->clist_keys)), "row-activated", G_CALLBACK (recplist_row_activated_cb), dialog); g_signal_connect (G_OBJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->clist_keys))), "row-changed", G_CALLBACK (recplist_row_changed_cb), dialog); g_signal_connect (G_OBJECT (dialog->radio_pgp), "toggled", G_CALLBACK (rbutton_toggled_cb), dialog); g_signal_connect (G_OBJECT (dialog->radio_x509), "toggled", G_CALLBACK (rbutton_toggled_cb), dialog); g_signal_connect (G_OBJECT (dialog->radio_auto), "toggled", G_CALLBACK (rbutton_toggled_cb), dialog); return object; } static void recipient_dlg_class_init (RecipientDlgClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->constructor = recipient_dlg_constructor; object_class->finalize = recipient_dlg_finalize; object_class->set_property = recipient_dlg_set_property; object_class->get_property = recipient_dlg_get_property; g_object_class_install_property (object_class, PROP_WINDOW, g_param_spec_object ("window", "Parent window", "Parent window", GTK_TYPE_WIDGET, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); } GType recipient_dlg_get_type (void) { static GType this_type; if (!this_type) { static const GTypeInfo this_info = { sizeof (RecipientDlgClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) recipient_dlg_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (RecipientDlg), 0, /* n_preallocs */ (GInstanceInitFunc) recipient_dlg_init, }; this_type = g_type_register_static (GTK_TYPE_DIALOG, "RecipientDlg", &this_info, 0); } return this_type; } /************************************************************ ********************** Public API ************************ ************************************************************/ RecipientDlg * recipient_dlg_new (GtkWidget *parent) { RecipientDlg *dialog; dialog = g_object_new (RECIPIENT_DLG_TYPE, "window", parent, NULL); return dialog; } /* Put RECIPIENTS into the list. PROTOCOL select the default protocol. */ void recipient_dlg_set_recipients (RecipientDlg *dialog, GSList *recipients, gpgme_protocol_t protocol) { GtkListStore *store; GSList *recp; GtkTreeIter iter; const char *name; GtkWidget *widget; g_return_if_fail (dialog); dialog->freeze_update_statushint++; if (protocol == GPGME_PROTOCOL_OpenPGP) widget = dialog->radio_pgp; else if (protocol == GPGME_PROTOCOL_CMS) widget = dialog->radio_x509; else widget = dialog->radio_auto; gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE); if (widget != dialog->radio_auto) { gtk_widget_set_sensitive (GTK_WIDGET (dialog->radio_pgp), FALSE); gtk_widget_set_sensitive (GTK_WIDGET (dialog->radio_x509), FALSE); gtk_widget_set_sensitive (GTK_WIDGET (dialog->radio_auto), FALSE); } store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->clist_keys))); gtk_list_store_clear (store); for (recp = recipients; recp; recp = g_slist_next (recp)) { name = recp->data; if (name && *name) { struct userdata_s *info = g_malloc0 (sizeof *info); info->mailbox = g_strdup (name); gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, RECPLIST_MAILBOX, g_strdup (""), RECPLIST_HAS_PGP, FALSE, RECPLIST_HAS_X509, FALSE, RECPLIST_KEYID, NULL, RECPLIST_USERDATA, info, -1); } } parse_recipients (store); dialog->freeze_update_statushint--; update_statushint (dialog); } /* Return the selected keys as well as the selected protocol. */ gpgme_key_t * recipient_dlg_get_keys (RecipientDlg *dialog, gpgme_protocol_t *r_protocol) { GtkTreeModel *model; GtkTreeIter iter; size_t idx, nkeys; gpgme_key_t key, *keyarray; gpgme_protocol_t protocol; g_return_val_if_fail (dialog, NULL); if (!dialog->usable) return NULL; /* No valid keys available. */ protocol = dialog->selected_protocol; model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->clist_keys)); /* Count the number of possible keys. */ nkeys = 0; if (gtk_tree_model_get_iter_first (model, &iter)) { do nkeys++; while (gtk_tree_model_iter_next (model, &iter)); } keyarray = g_new (gpgme_key_t, nkeys+1); idx = 0; if (gtk_tree_model_get_iter_first (model, &iter)) { do { char *mailbox; struct userdata_s *info; if (idx >= nkeys) { g_debug ("key list grew unexpectedly\n"); break; } gtk_tree_model_get (model, &iter, RECPLIST_MAILBOX, &mailbox, RECPLIST_USERDATA, &info, -1); if (info && !info->ignore_recipient) { if (protocol == GPGME_PROTOCOL_OpenPGP && info->pgp.keys) key = info->pgp.keys[0]; else if (protocol == GPGME_PROTOCOL_CMS && info->x509.keys) key = info->x509.keys[0]; else key = NULL; if (key) { gpgme_key_ref (key); keyarray[idx++] = key; } } g_free (mailbox); } while (gtk_tree_model_iter_next (model, &iter)); } g_assert (idx < nkeys+1); keyarray[idx] = NULL; if (r_protocol) *r_protocol = protocol; return keyarray; } diff --git a/src/selectkeydlg.c b/src/selectkeydlg.c index 8886a60..866325a 100644 --- a/src/selectkeydlg.c +++ b/src/selectkeydlg.c @@ -1,369 +1,369 @@ /* selectkeydlg.c - A dialog to select a key. * Copyright (C) 2008 g10 Code GmbH. * * This file is part of GPA * * GPA 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 3 of the License, or * (at your option) any later version. * * GPA 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, see . */ #include #include "gpa.h" #include "i18n.h" #include "gtktools.h" #include "keylist.h" #include "selectkeydlg.h" struct _SelectKeyDlg { GtkDialog parent; GpaKeyList *keylist; gpgme_protocol_t protocol; gpgme_key_t *initial_keys; const char *initial_pattern; }; struct _SelectKeyDlgClass { GtkDialogClass parent_class; }; /* The parent class. */ static GObjectClass *parent_class; /* Indentifiers for our properties. */ enum { PROP_0, PROP_WINDOW, PROP_PROTOCOL, PROP_INITIAL_KEYS, PROP_INITIAL_PATTERN }; /* Signal handler for selection changes of the keylist. */ static void keylist_selection_changed_cb (GtkTreeSelection *treeselection, gpointer user_data) { SelectKeyDlg *dialog = user_data; gboolean okay; g_debug ("keyring_selection_changed_cb called"); okay = gpa_keylist_has_single_selection (dialog->keylist); gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, okay); } /************************************************************ ****************** Object Management ******************** ************************************************************/ static void select_key_dlg_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SelectKeyDlg *dialog = SELECT_KEY_DLG (object); switch (prop_id) { case PROP_WINDOW: g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (dialog))); break; case PROP_PROTOCOL: g_value_set_int (value, dialog->protocol); break; case PROP_INITIAL_KEYS: g_value_set_pointer (value, dialog->initial_keys); break; case PROP_INITIAL_PATTERN: g_value_set_string (value, dialog->initial_pattern); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void select_key_dlg_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SelectKeyDlg *dialog = SELECT_KEY_DLG (object); switch (prop_id) { case PROP_WINDOW: gtk_window_set_transient_for (GTK_WINDOW (dialog), g_value_get_object (value)); break; case PROP_PROTOCOL: dialog->protocol = g_value_get_int (value); break; case PROP_INITIAL_KEYS: dialog->initial_keys = (gpgme_key_t*)g_value_get_pointer (value); break; case PROP_INITIAL_PATTERN: dialog->initial_pattern = g_value_get_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void select_key_dlg_finalize (GObject *object) { SelectKeyDlg *dialog = SELECT_KEY_DLG (object); gpa_gpgme_release_keyarray (dialog->initial_keys); /* Fixme: Release the store. */ G_OBJECT_CLASS (parent_class)->finalize (object); } static void select_key_dlg_init (SelectKeyDlg *dialog) { } static GObject* select_key_dlg_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *object; SelectKeyDlg *dialog; GtkWidget *vbox; GtkWidget *scroller; object = parent_class->constructor (type, n_construct_properties, construct_properties); dialog = SELECT_KEY_DLG (object); gpa_window_set_title (GTK_WINDOW (dialog), _("Select a key")); gtk_dialog_add_buttons (GTK_DIALOG (dialog), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_OK"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE); gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); // vbox = GTK_DIALOG (dialog)->vbox; vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); scroller = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroller), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (vbox), scroller, TRUE, TRUE, 0); gtk_widget_set_size_request (scroller, 400, 200); /* Create the keylist and initialize if with our initial keys. Because we don't need them then anymore, release our own copy of the keys. */ dialog->keylist = gpa_keylist_new_with_keys (GTK_WIDGET (dialog), TRUE, dialog->protocol, dialog->initial_keys, dialog->initial_pattern, KEY_USAGE_ENCR, TRUE); gpa_gpgme_release_keyarray (dialog->initial_keys); dialog->initial_keys = NULL; gtk_container_add (GTK_CONTAINER (scroller), GTK_WIDGET(dialog->keylist)); g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->keylist))), "changed", G_CALLBACK (keylist_selection_changed_cb), dialog); return object; } static void select_key_dlg_class_init (SelectKeyDlgClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->constructor = select_key_dlg_constructor; object_class->finalize = select_key_dlg_finalize; object_class->set_property = select_key_dlg_set_property; object_class->get_property = select_key_dlg_get_property; g_object_class_install_property (object_class, PROP_WINDOW, g_param_spec_object ("window", "Parent window", "Parent window", GTK_TYPE_WIDGET, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_PROTOCOL, g_param_spec_int ("protocol", "Protocol", "The gpgme protocol used to restruct the key listing.", GPGME_PROTOCOL_OpenPGP, GPGME_PROTOCOL_UNKNOWN, GPGME_PROTOCOL_UNKNOWN, G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_INITIAL_KEYS, g_param_spec_pointer ("initial-keys", "Initial-keys", "An array of gpgme_key_t with the initial set of keys or NULL.", G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_INITIAL_PATTERN, g_param_spec_string ("initial-pattern", "Initial-pattern", "A string with pattern to be used for the search boxor NULL.", NULL, G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY)); } GType select_key_dlg_get_type (void) { static GType this_type; if (!this_type) { static const GTypeInfo this_info = { sizeof (SelectKeyDlgClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) select_key_dlg_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (SelectKeyDlg), 0, /* n_preallocs */ (GInstanceInitFunc) select_key_dlg_init, }; this_type = g_type_register_static (GTK_TYPE_DIALOG, "SelectKeyDlg", &this_info, 0); } return this_type; } /************************************************************ ********************** Public API ************************ ************************************************************/ SelectKeyDlg * select_key_dlg_new (GtkWidget *parent) { SelectKeyDlg *dialog; dialog = g_object_new (SELECT_KEY_DLG_TYPE, "window", parent, NULL); return dialog; } /* Same as select_key_dlg_new but with the options to select the protocol and to set initial keys and a search string. */ SelectKeyDlg * select_key_dlg_new_with_keys (GtkWidget *parent, gpgme_protocol_t protocol, gpgme_key_t *keys, const char *pattern) { SelectKeyDlg *dialog; dialog = g_object_new (SELECT_KEY_DLG_TYPE, "window", parent, "protocol", (int)protocol, "initial-keys", gpa_gpgme_copy_keyarray (keys), "initial-pattern", pattern, NULL); return dialog; } /* Return the selected key. */ gpgme_key_t select_key_dlg_get_key (SelectKeyDlg *dialog) { gpgme_key_t key; g_return_val_if_fail (dialog, NULL); g_return_val_if_fail (dialog->keylist, NULL); key = gpa_keylist_get_selected_key (dialog->keylist); return key; } /* Return an array of selected keys. FIXME: For now it returns only one key. */ gpgme_key_t * select_key_dlg_get_keys (SelectKeyDlg *dialog) { gpgme_key_t *keyarray; g_return_val_if_fail (dialog, NULL); g_return_val_if_fail (dialog->keylist, NULL); keyarray = g_new (gpgme_key_t, 1+1); keyarray[0] = gpa_keylist_get_selected_key (dialog->keylist); keyarray[1] = NULL; return keyarray; }