[Gpa-commits] r837 - in trunk: . src

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Thu Mar 6 20:42:47 CET 2008


Author: werner
Date: 2008-03-06 20:42:46 +0100 (Thu, 06 Mar 2008)
New Revision: 837

Added:
   trunk/src/selectkeydlg.c
   trunk/src/selectkeydlg.h
Modified:
   trunk/AUTHORS
   trunk/ChangeLog
   trunk/src/ChangeLog
   trunk/src/Makefile.am
   trunk/src/gpa.c
   trunk/src/gpa.h
   trunk/src/keylist.c
   trunk/src/keylist.h
   trunk/src/recipientdlg.c
   trunk/src/server.c
Log:
Properly shutdown the server.
Add new key selection dialog.
Fixed keylisting.


Modified: trunk/AUTHORS
===================================================================
--- trunk/AUTHORS	2008-03-06 16:00:47 UTC (rev 836)
+++ trunk/AUTHORS	2008-03-06 19:42:46 UTC (rev 837)
@@ -1,5 +1,8 @@
-Program: GPA, GPAPA
+Program: GPA
 Maintainer: Miguel Coca <mcoca at gnu.org>
+Bug reports: <bug-gpa at gnupg.org>
+Security related bug reports: <security at gnupg.org>
+License: GPLv3+
 
 
 Authors
@@ -64,21 +67,26 @@
 Ling Li <ling at caltech.edu>
         See ChangeLogs.
 
-Josué Burgos <jobugar at arrakis.es>
+Josué Burgos <jobugar at arrakis.es>
         Designed the gpa.png icon.
 
-Can Berk Güder <cbguder at su.sabanciuniv.edu>
+Can Berk Güder <cbguder at su.sabanciuniv.edu>
         Turkish translation.
 
 Emilian Nowak <emil5 at go2.pl>
         Polish translation.
-
+        
 Daniel Nylander <po at danielnylander.se>
-       Swedish translation.
-
+        Swedish translation.
+        
 Zdenek Hatas <zdenek.hatas at gmail.com>
-       Czech translation. 
+        Czech translation. 
 
 Maxim Britov <maxim.britov at gmail.com>
-       Russian translation.
+        Russian translation.
 
+Marcus Brinkmann  <marcus at g10code.de>
+        Clipboard code, cleanups, bug fixes.
+        
+
+        
\ No newline at end of file

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2008-03-06 16:00:47 UTC (rev 836)
+++ trunk/ChangeLog	2008-03-06 19:42:46 UTC (rev 837)
@@ -1,3 +1,10 @@
+2008-03-06  Werner Koch  <wk at g10code.com>
+
+	Note that the code is now under the GPLv3+ due to a couple of new
+	stuff.
+	
+	* AUTHORS: Add bug reporting address.  Add license info.
+
 2008-02-28  Marcus Brinkmann  <marcus at g10code.de>
 
 	* configure.ac: Invoke AC_SYS_LARGEFILE.

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2008-03-06 16:00:47 UTC (rev 836)
+++ trunk/src/ChangeLog	2008-03-06 19:42:46 UTC (rev 837)
@@ -1,3 +1,31 @@
+2008-03-06  Werner Koch  <wk at g10code.com>
+
+	* keylist.c: Change license to GPLv3+.  Cosmetic changes.
+	(gpa_keylist_get_selected_key): New.
+	(gpa_keylist_elgamal_dialog): Remove.
+	(gpa_keylist_next): Remove detection of Elgamal signatures.  It is
+	pointless as gpg has no more support for those keys.
+	(gpa_keylist_new_public_only): New.
+	(gpa_keylist_class_init, gpa_keylist_get_property)
+	(gpa_keylist_set_property): Add property.
+	(gpa_keylist_set_brief, gpa_keylist_set_detailed) 
+	(gpa_keylist_next): Do not display the image in public_only mode.
+	(gpa_keylist_has_single_secret_selection, gpa_keylist_next):
+	Implement public_only.
+	(gpa_keylist_init): Make a dummy fucntion and move all stuff to ..
+	(gpa_keylist_constructor): .. New.
+	(gpa_keylist_class_init): Register constructor.
+	* keylist.h (_GpaKeyList): Add field public_only.
+
+	* selectkeydlg.h, selectkeydlg.c: New.
+
+	* gpa.c: Move variables definitions to the top.
+	(quit_if_no_window): Do not quit if only the server has been
+	started.
+	(dummy_log_func): Use only for G_OS_WIN32.
+	* server.c (gpa_stop_server): New.
+	(connection_startup, connection_finish): Add shutdown logic.
+
 2008-03-06  Marcus Brinkmann  <marcus at g10code.de>
 
 	* settingsdlg.c (default_keyserver_frame): Invoke
@@ -4909,80 +4937,84 @@
 
 2000-07-25 09:02:34  Werner Koch  (wk at habibti.openit.de)
 
-  * gpa.c (gpa_windowTips_show): Moved from here to ...
-  * help.c: ... here.  Complete rewrote to read the tips rom a file.
-  (get_language): New.
-  (gpa_tips.en, gpa_tips.de): New.
+	* gpa.c (gpa_windowTips_show): Moved from here to ...
+	* help.c: ... here.  Complete rewrote to read the tips rom a file.
+	(get_language): New.
+	(gpa_tips.en, gpa_tips.de): New.
 
 2000-06-28 17:23:03  Werner Koch  (wk at habibti.openit.de)
 
-  * gpa.c:  Removed the --tooltip-kludge option, becuase the bug as
-  been fixed meanwhile.
-  * gtktools.c (gpa_widget_show): Removed it here too.
+	* gpa.c:  Removed the --tooltip-kludge option, becuase the bug as
+	been fixed meanwhile.
+	* gtktools.c (gpa_widget_show): Removed it here too.
 
 2000-06-28 15:32:07  Jan-Oliver Wagner (jan at intevation.de)
 
-  * gtktools.c (gpa_widget_set_centered): fixed minimization bug
-  * icons.xpm: replaced temporary icons and added ownertrust icons
-  * keysmenu.c: added icon to button 'sign' in public keyring editor dialog,
-  added ownertrust icons in keylist of public keyring editor dialog
+	* gtktools.c (gpa_widget_set_centered): fixed minimization bug
+	* icons.xpm: replaced temporary icons and added ownertrust icons
+	* keysmenu.c: added icon to button 'sign' in public keyring editor
+	dialog, added ownertrust icons in keylist of public keyring editor
+	dialog
 
 2000-06-23 16:05:04  Jan-Oliver Wagner (jan at intevation.de)
 
-  * keysmenu.c: added icon to the delete button in the
-  public keyring editor dialog
+	* keysmenu.c: added icon to the delete button in the
+	public keyring editor dialog
 
 2000-06-23 16:00:53  Jan-Oliver Wagner (jan at intevation.de)
 
-  * icons.xpm: added a trashcan (taken from KDE)
+	* icons.xpm: added a trashcan (taken from KDE)
 
 2000-06-23 10:11:02  Jan-Oliver Wagner (jan at intevation.de)
 
-  * icons.xpm: test icons for tool bar added
+	* icons.xpm: test icons for tool bar added
 
 2000-06-23 10:10:44  Jan-Oliver Wagner (jan at intevation.de)
 
-  * gpa.c: test icons for tool bar added, seldom actions removed from toolbar
+	* gpa.c: test icons for tool bar added, seldom actions removed
+	from toolbar
 
 2000-06-22 13:27:35  Jan-Oliver Wagner (jan at intevation.de)
 
-  * icons.xpm: new file, contains icon xpm's. Just tempory until
-  icons are treated in a more convenient way.
+	* icons.xpm: new file, contains icon xpm's. Just tempory until
+	icons are treated in a more convenient way.
 
 2000-06-20 16:45:31  Jan-Oliver Wagner (jan at intevation.de)
 
-  * gpa.c: added toolbar for main window - experimental stage, but functioning
+	* gpa.c: added toolbar for main window - experimental stage, but
+	functioning
 
 2000-05-25 17:54:29  Werner Koch  (wk at habibti.openit.de)
 
-  * gpa.c (main): Add a call to gpapa_init
+	* gpa.c (main): Add a call to gpapa_init
 
-  New option --gpg-program.
+	New option --gpg-program.
 
 2000-05-24 10:01:06  Werner Koch  (wk at habibti.openit.de)
 
-  * gpa.c (gpa_menubar_new): Reformated menu list.
-  * helpmenu.c (help_version): renamed to ...
-  (help_about): .. this and implemented.
+	* gpa.c (gpa_menubar_new): Reformated menu list.
+	* helpmenu.c (help_version): renamed to ...
+	(help_about): .. this and implemented.
 
-  * gpa.c, gpa.h (namesKeyservers): Replaced by ..
-  (main): ... opt.keyserver_names and malloced array.
-  * optionsmenu.c (options_keyserver): Put all keyservers into the list.
+	* gpa.c, gpa.h (namesKeyservers): Replaced by ..
+	(main): ... opt.keyserver_names and malloced array.
+	* optionsmenu.c (options_keyserver): Put all keyservers into the list.
 
-  * gtktools.c (gpa_widget_show): Kludge for Sawmill and Windowmaker.
+	* gtktools.c (gpa_widget_show): Kludge for Sawmill and Windowmaker.
 
 2000-05-16 19:57:28  Werner Koch  (wk at habibti.openit.de)
 
-  Ran "indent -gnu -sc" on all source files.
+	Ran "indent -gnu -sc" on all source files.
 
 2000-05-04 18:40:08  Werner Koch  (wk at habibti.openit.de)
 
-  * *.c: Moved all gpa_widget_set_centered() before the
-  gtk_widget_show_all(), so that the windows are displayed correctly.
+	* *.c: Moved all gpa_widget_set_centered() before the
+	gtk_widget_show_all(), so that the windows are displayed
+	correctly.
 
 2000-05-02 19:57:29  Werner Koch  (wk at habibti.openit.de)
 
-  * gpa.c, keymenu.c, filemenu.c: Removed libiberty header.
-  * gpa.h: Included xmalloc header.
+	* gpa.c, keymenu.c, filemenu.c: Removed libiberty header.
+	* gpa.h: Included xmalloc header.
 
 

Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am	2008-03-06 16:00:47 UTC (rev 836)
+++ trunk/src/Makefile.am	2008-03-06 19:42:46 UTC (rev 837)
@@ -47,6 +47,7 @@
 	      encryptdlg.c encryptdlg.h \
 	      verifydlg.c verifydlg.h \
               recipientdlg.c recipientdlg.h \
+              selectkeydlg.c selectkeydlg.h \
 	      keyring.c keyring.h \
 	      ownertrustdlg.c ownertrustdlg.h \
 	      keysigndlg.c keysigndlg.h \

Modified: trunk/src/gpa.c
===================================================================
--- trunk/src/gpa.c	2008-03-06 16:00:47 UTC (rev 836)
+++ trunk/src/gpa.c	2008-03-06 19:42:46 UTC (rev 837)
@@ -44,7 +44,7 @@
 #endif
 
 
-/* Global variables */
+/* Global variables. */
 
 /* The home directory of GnuPG.  */
 gchar *gnupg_homedir;
@@ -52,6 +52,58 @@
 /* True if CMS hack mode is enabled.  */
 gboolean cms_hack;
 
+
+/* Local variables.  */
+typedef struct
+{
+  gboolean start_keyring_editor;
+  gboolean start_file_manager;
+  gboolean start_only_server;
+  gchar *options_filename;
+} gpa_args_t;
+
+static gpa_args_t args = { FALSE, FALSE, FALSE, NULL };
+
+
+/* The copyright notice.  */
+static const char *copyright = 
+"Copyright (C) 2000-2002 Miguel Coca, G-N-U GmbH, Intevation GmbH.\n"
+"Copyright (C) 2008 g10 Code GmbH.\n"
+"This program comes with ABSOLUTELY NO WARRANTY.\n"
+"This is free software, and you are welcome to redistribute it\n"
+"under certain conditions.  See the file COPYING for details.\n";
+
+
+static GtkWidget *keyringeditor = NULL;
+static GtkWidget *settings_dialog = NULL;
+static GtkWidget *backend_config_dialog = NULL;
+
+
+static void print_version (void);
+
+
+/* All command line options of the main application.  */
+static GOptionEntry option_entries[] =
+  {
+    { "version", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+      (gpointer) &print_version,
+      N_("Output version information and exit"), NULL, },
+    { "keyring", 'k', 0, G_OPTION_ARG_NONE, &args.start_keyring_editor,
+      N_("Open keyring editor (default)"), NULL },
+    { "files", 'f', 0, G_OPTION_ARG_NONE, &args.start_file_manager,
+      N_("Open filemanager"), NULL },
+    { "server", 's', 0, G_OPTION_ARG_NONE, &args.start_only_server,
+      N_("Start only the UI server"), NULL },
+    { "options", 'o', 0, G_OPTION_ARG_FILENAME, &args.options_filename,
+      N_("Read options from file"), "FILE" },
+    { "cms", 'x', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &cms_hack,
+      "Enable CMS hack", NULL },
+    { NULL }
+  };
+
+
+
+
 
 /* Return a malloced string with the locale dir.  Return NULL on
    error. */
@@ -100,18 +152,12 @@
 
 
 /* Manage the two main windows and the settings dialog.  */
-
-static GtkWidget *keyringeditor = NULL;
-static GtkWidget *settings_dialog = NULL;
-static GtkWidget *backend_config_dialog = NULL;
-
-
 static void
 quit_if_no_window (void)
 {
   if (! keyringeditor && ! gpa_file_manager_is_open ()
-      && ! gpa_clipboard_is_open ())
-    gtk_main_quit ();
+      && ! gpa_clipboard_is_open () && !args.start_only_server )
+    gpa_stop_server ();
 }
 
 
@@ -204,26 +250,6 @@
 
 /* Command line options.  */
 
-typedef struct
-{
-  gboolean start_keyring_editor;
-  gboolean start_file_manager;
-  gboolean start_only_server;
-  gchar *options_filename;
-} gpa_args_t;
-
-static gpa_args_t args = { FALSE, FALSE, FALSE, NULL };
-
-
-/* The copyright notice.  */
-static const char *copyright = 
-"Copyright (C) 2000-2002 Miguel Coca, G-N-U GmbH, Intevation GmbH.\n"
-"Copyright (C) 2008 g10 Code GmbH.\n"
-"This program comes with ABSOLUTELY NO WARRANTY.\n"
-"This is free software, and you are welcome to redistribute it\n"
-"under certain conditions.  See the file COPYING for details.\n";
-
-
 /* Print version information and exit.  */
 static void
 print_version (void)
@@ -233,34 +259,16 @@
 }
 
 
-/* All command line options of the main application.  */
-static GOptionEntry option_entries[] =
-  {
-    { "version", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
-      (gpointer) &print_version,
-      N_("Output version information and exit"), NULL, },
-    { "keyring", 'k', 0, G_OPTION_ARG_NONE, &args.start_keyring_editor,
-      N_("Open keyring editor (default)"), NULL },
-    { "files", 'f', 0, G_OPTION_ARG_NONE, &args.start_file_manager,
-      N_("Open filemanager"), NULL },
-    { "server", 's', 0, G_OPTION_ARG_NONE, &args.start_only_server,
-      N_("Start only the UI server"), NULL },
-    { "options", 'o', 0, G_OPTION_ARG_FILENAME, &args.options_filename,
-      N_("Read options from file"), "FILE" },
-    { "cms", 'x', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &cms_hack,
-      "Enable CMS hack", NULL },
-    { NULL }
-  };
-
 
+#ifdef G_OS_WIN32
 static void
 dummy_log_func (const gchar *log_domain, GLogLevelFlags log_level,
                 const gchar *message, gpointer user_data)
 {
   /* Nothing to be done.  */
 }
+#endif /*G_OS_WIN32*/
 
-
 int
 main (int argc, char *argv[])
 {
@@ -295,6 +303,8 @@
 
   /* Disable logging to prevent MS Windows NT from opening a
      console.  */
+
+#ifdef G_OS_WIN32
   g_log_set_handler ("Glib", G_LOG_LEVEL_CRITICAL
                              | G_LOG_LEVEL_WARNING
                              | G_LOG_LEVEL_MESSAGE
@@ -309,6 +319,7 @@
                             | G_LOG_LEVEL_WARNING
                             | G_LOG_LEVEL_MESSAGE
                             | G_LOG_LEVEL_INFO, dummy_log_func, NULL);
+#endif /*G_OS_WIN32*/
 
   gtk_init (&argc, &argv);
 

Modified: trunk/src/gpa.h
===================================================================
--- trunk/src/gpa.h	2008-03-06 16:00:47 UTC (rev 836)
+++ trunk/src/gpa.h	2008-03-06 19:42:46 UTC (rev 837)
@@ -75,6 +75,7 @@
 
 void gpa_run_server_continuation (assuan_context_t ctx, gpg_error_t err);
 void gpa_start_server (void);
+void gpa_stop_server (void);
 
 /*-- utils.c --*/
 /* We are so used to these function thus provide them.  */

Modified: trunk/src/keylist.c
===================================================================
--- trunk/src/keylist.c	2008-03-06 16:00:47 UTC (rev 836)
+++ trunk/src/keylist.c	2008-03-06 19:42:46 UTC (rev 837)
@@ -1,23 +1,23 @@
 /* keylist.c - The GNU Privacy Assistant keylist.
    Copyright (C) 2003 Miguel Coca.
-   Copyright (C) 2005 g10 Code GmbH.
+   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
+   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.
+   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  */
-
+   along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+ 
 #include <config.h>
 
 #include <glib/gstdio.h>
@@ -29,26 +29,51 @@
 #include "keytable.h"
 #include "icons.h"
 
-/* Internal */
-static void add_trustdb_dialog (GpaKeyList * keylist);
-static void remove_trustdb_dialog (GpaKeyList * keylist);
 
-/* Callbacks */
-static void gpa_keylist_next (gpgme_key_t key, gpointer data);
-static void gpa_keylist_end (gpointer data);
-static void gpa_keylist_clear_columns (GpaKeyList *keylist);
-
 /* Properties */
 enum
 {
   PROP_0,
   PROP_WINDOW,
+  PROP_PUBLIC_ONLY
 };
 
 /* GObject */
-
 static GObjectClass *parent_class = NULL;
 
+
+/* Symbols to access the columns.  */
+typedef enum
+{
+  /* These are the displayed columns */
+  GPA_KEYLIST_COLUMN_IMAGE, 
+  GPA_KEYLIST_COLUMN_KEYID,
+  GPA_KEYLIST_COLUMN_EXPIRY,
+  GPA_KEYLIST_COLUMN_OWNERTRUST,
+  GPA_KEYLIST_COLUMN_VALIDITY,
+  GPA_KEYLIST_COLUMN_USERID,
+  /* This column contains the gpgme_key_t */
+  GPA_KEYLIST_COLUMN_KEY,
+  /* These columns are used only internally for sorting */
+  GPA_KEYLIST_COLUMN_HAS_SECRET,
+  GPA_KEYLIST_COLUMN_EXPIRY_TS,
+  GPA_KEYLIST_COLUMN_OWNERTRUST_VALUE,
+  GPA_KEYLIST_COLUMN_VALIDITY_VALUE,
+  GPA_KEYLIST_N_COLUMNS
+} GpaKeyListColumn;
+
+
+
+static void add_trustdb_dialog (GpaKeyList * keylist);
+static void gpa_keylist_next (gpgme_key_t key, gpointer data);
+static void gpa_keylist_end (gpointer data);
+
+
+
+/************************************************************ 
+ ******************  Object Management  *********************
+ ************************************************************/
+
 static void
 gpa_keylist_get_property (GObject     *object,
 			  guint        prop_id,
@@ -62,6 +87,9 @@
     case PROP_WINDOW:
       g_value_set_object (value, list->window);
       break;
+    case PROP_PUBLIC_ONLY:
+      g_value_set_boolean (value, list->public_only);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -71,7 +99,7 @@
 static void
 gpa_keylist_set_property (GObject     *object,
 			  guint        prop_id,
-			  const GValue      *value,
+			  const GValue *value,
 			  GParamSpec  *pspec)
 {
   GpaKeyList *list = GPA_KEYLIST (object);
@@ -81,6 +109,9 @@
     case PROP_WINDOW:
       list->window = (GtkWidget*) g_value_get_object (value);
       break;
+    case PROP_PUBLIC_ONLY:
+      list->public_only = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -99,50 +130,30 @@
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+
 static void
-gpa_keylist_class_init (GpaKeyListClass *klass)
+gpa_keylist_init (GpaKeyList *list)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  
-  parent_class = g_type_class_peek_parent (klass);
 
-  object_class->finalize = gpa_keylist_finalize;
-  object_class->set_property = gpa_keylist_set_property;
-  object_class->get_property = gpa_keylist_get_property;
 }
 
-typedef enum
-{
-  /* These are the displayed columns */
-  GPA_KEYLIST_COLUMN_IMAGE,
-  GPA_KEYLIST_COLUMN_KEYID,
-  GPA_KEYLIST_COLUMN_EXPIRY,
-  GPA_KEYLIST_COLUMN_OWNERTRUST,
-  GPA_KEYLIST_COLUMN_VALIDITY,
-  GPA_KEYLIST_COLUMN_USERID,
-  /* This column contains the gpgme_key_t */
-  GPA_KEYLIST_COLUMN_KEY,
-  /* These columns are used only internally for sorting */
-  GPA_KEYLIST_COLUMN_HAS_SECRET,
-  GPA_KEYLIST_COLUMN_EXPIRY_TS,
-  GPA_KEYLIST_COLUMN_OWNERTRUST_VALUE,
-  GPA_KEYLIST_COLUMN_VALIDITY_VALUE,
-  GPA_KEYLIST_N_COLUMNS
-} GpaKeyListColumn;
 
-static void
-gpa_keylist_init (GpaKeyList *list)
+static GObject*
+gpa_keylist_constructor (GType type,
+                         guint n_construct_properties,
+                         GObjectConstructParam *construct_properties)
 {
+  GObject *object;
+  GpaKeyList *list;
   GtkListStore *store;
-  GtkTreeSelection *selection = 
-    gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
+  GtkTreeSelection *selection; 
 
-  list->secret = FALSE;
-  list->keys = NULL;
-  list->dialog = NULL;
-  list->timeout_id = 0;
-  list->window = NULL;
-  /* Init the model */
+  object = parent_class->constructor (type,
+				      n_construct_properties,
+				      construct_properties);
+  list = GPA_KEYLIST (object);
+
+   /* Init the model */
   store = gtk_list_store_new (GPA_KEYLIST_N_COLUMNS,
 			      GDK_TYPE_PIXBUF,
 			      G_TYPE_STRING,
@@ -160,13 +171,41 @@
   gtk_tree_view_set_model (GTK_TREE_VIEW (list), GTK_TREE_MODEL (store));
   gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (list), TRUE);
   gpa_keylist_set_brief (list);
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
   gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
   /* Load the keyring */
   add_trustdb_dialog (list);
   gpa_keytable_list_keys (gpa_keytable_get_public_instance(),
 			  gpa_keylist_next, gpa_keylist_end, list);
+
+  return object;
 }
 
+
+static void
+gpa_keylist_class_init (GpaKeyListClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  
+  parent_class = g_type_class_peek_parent (klass);
+
+  object_class->constructor = gpa_keylist_constructor;
+  object_class->finalize = gpa_keylist_finalize;
+  object_class->set_property = gpa_keylist_set_property;
+  object_class->get_property = gpa_keylist_get_property;
+
+  g_object_class_install_property 
+    (object_class, PROP_PUBLIC_ONLY,
+     g_param_spec_boolean
+     ("public-only", "Public-only",
+      "A flag indicating that we are only interested in public keys.",
+      FALSE,
+      G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
+
+}
+
+
+
 GType
 gpa_keylist_get_type (void)
 {
@@ -195,30 +234,242 @@
   return keylist_type;
 }
 
-/* API */
 
-GtkWidget *gpa_keylist_new (GtkWidget * window)
+
+/************************************************************ 
+ ******************  Internal Functions  ********************
+ ************************************************************/
+
+static gboolean
+display_dialog (GpaKeyList * keylist)
 {
+  gtk_widget_show_all (keylist->dialog);
+
+  keylist->timeout_id = 0;
+
+  return FALSE;
+}
+
+
+static void
+add_trustdb_dialog (GpaKeyList * keylist)
+{
+  /* Display this warning until the first key is received.  It may be
+     shown at times when it's not needed. But it shouldn't appear for
+     long those times.  */
+  keylist->dialog = gtk_message_dialog_new
+    (GTK_WINDOW (keylist->window), GTK_DIALOG_MODAL, 
+     GTK_MESSAGE_INFO, GTK_BUTTONS_NONE,
+     _("GnuPG is rebuilding the trust database.\n"
+       "This might take a few seconds."));
+
+  /* Wait a second before displaying the dialog. This avoids most
+     "false alarms".  That is the message will not be shown if GnuPG
+     does not run a long check trustdb.  */
+  keylist->timeout_id = g_timeout_add (1000, (GSourceFunc) display_dialog, 
+				       keylist);
+}
+
+
+static void
+remove_trustdb_dialog (GpaKeyList * keylist)
+{
+  if (keylist->timeout_id)
+    {
+      g_source_remove (keylist->timeout_id);
+      keylist->timeout_id = 0;
+    }
+  if (keylist->dialog)
+    {
+      gtk_widget_destroy (keylist->dialog);
+      keylist->dialog = NULL;
+    }
+}
+
+
+static GdkPixbuf*
+get_key_pixbuf (gpgme_key_t key)
+{
+  static gboolean pixmaps_created = FALSE;
+  static GdkPixbuf *secret_pixbuf = NULL;
+  static GdkPixbuf *public_pixbuf = NULL;
+
+  if (!pixmaps_created)
+    {
+      secret_pixbuf = gpa_create_icon_pixbuf ("blue_yellow_key");
+      public_pixbuf = gpa_create_icon_pixbuf ("blue_key");
+      pixmaps_created = TRUE;
+    }
+
+  if (gpa_keytable_lookup_key 
+      (gpa_keytable_get_secret_instance(), 
+       key->subkeys->fpr) != NULL)
+    {
+      return secret_pixbuf;
+    }
+  else
+    {
+      return public_pixbuf;
+    }
+}
+
+
+
+/* For keys, gpg can't cope with, the fingerprint is set to all
+   zero. This helper function returns true for such a FPR. */
+static int
+is_zero_fpr (const char *fpr)
+{
+  for (; *fpr; fpr++)
+    if (*fpr != '0')
+      return 0;
+  return 1;
+}
+
+
+static void 
+gpa_keylist_next (gpgme_key_t key, gpointer data)
+{
+  GpaKeyList *list = data;
+  GtkListStore *store;
+  GtkTreeIter iter;
+  const gchar *keyid, *ownertrust, *validity;
+  gchar *userid, *expiry;
+  gboolean has_secret;
+  long int val_value;
+
+  /* Remove the dialog if it is being displayed */
+  remove_trustdb_dialog (list);
+  
+  list->keys = g_list_append (list->keys, key);
+  store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (list)));
+  /* Get the column values */
+  keyid = gpa_gpgme_key_get_short_keyid (key);
+  expiry = gpa_expiry_date_string (key->subkeys->expires);
+  ownertrust = gpa_key_ownertrust_string (key);
+  validity = gpa_key_validity_string (key);
+  userid = gpa_gpgme_key_get_userid (key->uids);
+  if (list->public_only)
+    has_secret = 0;
+  else
+    has_secret = (!is_zero_fpr (key->subkeys->fpr)
+                  && gpa_keytable_lookup_key 
+                  (gpa_keytable_get_secret_instance(), key->subkeys->fpr));
+
+  /* Append the key to the list */
+  gtk_list_store_append (store, &iter);
+
+  /* Set an appropiate value for sorting revoked and expired keys. This 
+   * includes a hack for forcing a value to a range outside the
+   * usual validity values */
+  if (key->subkeys->revoked)
+      val_value = GPGME_VALIDITY_UNKNOWN-2;
+  else if (key->subkeys->expired)
+      val_value = GPGME_VALIDITY_UNKNOWN-1;
+  else if (key->uids)
+      val_value = key->uids->validity;
+  else
+      val_value = GPGME_VALIDITY_UNKNOWN;
+
+  gtk_list_store_set (store, &iter,
+		      GPA_KEYLIST_COLUMN_KEYID, keyid, 
+		      GPA_KEYLIST_COLUMN_EXPIRY, expiry,
+		      GPA_KEYLIST_COLUMN_OWNERTRUST, ownertrust,
+		      GPA_KEYLIST_COLUMN_VALIDITY, validity,
+		      GPA_KEYLIST_COLUMN_USERID, userid,
+		      GPA_KEYLIST_COLUMN_KEY, key, 
+		      GPA_KEYLIST_COLUMN_HAS_SECRET, has_secret,
+		      /* Set "no expiration" to a large value for sorting */
+		      GPA_KEYLIST_COLUMN_EXPIRY_TS, 
+		      key->subkeys->expires ? 
+		      key->subkeys->expires : G_MAXULONG,
+		      GPA_KEYLIST_COLUMN_OWNERTRUST_VALUE, 
+		      key->owner_trust,
+		      /* Set revoked and expired keys to "never trust" for 
+		       * sorting */
+		      GPA_KEYLIST_COLUMN_VALIDITY_VALUE, val_value,
+                      /* Store the image only if enabled.  */
+		      list->public_only? -1: GPA_KEYLIST_COLUMN_IMAGE,
+                      list->public_only? NULL:get_key_pixbuf (key),
+		      -1);
+  /* Clean up */
+  g_free (userid);
+  g_free (expiry);
+}
+
+
+static void 
+gpa_keylist_end (gpointer data)
+{
+  GpaKeyList *list = data;
+  
+  remove_trustdb_dialog (list);
+}
+
+
+static void 
+gpa_keylist_clear_columns (GpaKeyList *keylist)
+{
+  GList *columns, *i;
+
+  columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (keylist));
+  for (i = columns; i; i = g_list_next (i))
+    {
+      gtk_tree_view_remove_column (GTK_TREE_VIEW (keylist),
+                                   (GtkTreeViewColumn*) i->data);
+    }
+}
+
+
+
+/************************************************************ 
+ **********************  Public API  ************************
+ ************************************************************/
+
+/* Create a new key list widget.  */
+GtkWidget *
+gpa_keylist_new (GtkWidget *window)
+{
   GtkWidget *list = (GtkWidget*) g_object_new (GPA_KEYLIST_TYPE, NULL);
 
   return list;
 }
 
-void gpa_keylist_set_brief (GpaKeyList * keylist)
+
+/* Create a new key list widget in public_only mode. */
+GpaKeyList *
+gpa_keylist_new_public_only (GtkWidget *window)
 {
+  GpaKeyList *list;
+
+  list = g_object_new (GPA_KEYLIST_TYPE,
+                       "public-only", TRUE,
+                       NULL);
+
+  return list;
+}
+
+
+
+/* Set the key list in "brief" mode.  */
+void 
+gpa_keylist_set_brief (GpaKeyList *keylist)
+{
   GtkCellRenderer *renderer;
   GtkTreeViewColumn *column;
 
   gpa_keylist_clear_columns (keylist);
 
-  renderer = gtk_cell_renderer_pixbuf_new ();
-  column = gtk_tree_view_column_new_with_attributes ("", renderer,
-						     "pixbuf",
-						     GPA_KEYLIST_COLUMN_IMAGE,
-						     NULL);
-  gtk_tree_view_append_column (GTK_TREE_VIEW (keylist), column);
-  gtk_tree_view_column_set_sort_column_id (column, GPA_KEYLIST_COLUMN_HAS_SECRET);
-  gtk_tree_view_column_set_sort_indicator (column, TRUE);
+  if (!keylist->public_only)
+    {
+      renderer = gtk_cell_renderer_pixbuf_new ();
+      column = gtk_tree_view_column_new_with_attributes 
+        ("", renderer, "pixbuf", GPA_KEYLIST_COLUMN_IMAGE, NULL);
+      gtk_tree_view_append_column (GTK_TREE_VIEW (keylist), column);
+      gtk_tree_view_column_set_sort_column_id (column, 
+                                               GPA_KEYLIST_COLUMN_HAS_SECRET);
+      gtk_tree_view_column_set_sort_indicator (column, TRUE);
+    }
 
   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new_with_attributes (_("Key ID"), renderer,
@@ -239,21 +490,29 @@
   gtk_tree_view_column_set_sort_indicator (column, TRUE);
 }
 
-void gpa_keylist_set_detailed (GpaKeyList * keylist)
+
+/* Set the key list in "detailed" mode.  */
+void 
+gpa_keylist_set_detailed (GpaKeyList * keylist)
 {
   GtkCellRenderer *renderer;
   GtkTreeViewColumn *column;
 
   gpa_keylist_clear_columns (keylist);
 
-  renderer = gtk_cell_renderer_pixbuf_new ();
-  column = gtk_tree_view_column_new_with_attributes ("", renderer,
-						     "pixbuf",
-						     GPA_KEYLIST_COLUMN_IMAGE,
-						     NULL);
-  gtk_tree_view_append_column (GTK_TREE_VIEW (keylist), column);
-  gtk_tree_view_column_set_sort_column_id (column, GPA_KEYLIST_COLUMN_HAS_SECRET);
-  gtk_tree_view_column_set_sort_indicator (column, TRUE);
+  if (!keylist->public_only)
+    {
+      renderer = gtk_cell_renderer_pixbuf_new ();
+      column = gtk_tree_view_column_new_with_attributes 
+        ("", renderer,
+         "pixbuf",
+         GPA_KEYLIST_COLUMN_IMAGE,
+         NULL);
+      gtk_tree_view_append_column (GTK_TREE_VIEW (keylist), column);
+      gtk_tree_view_column_set_sort_column_id 
+        (column, GPA_KEYLIST_COLUMN_HAS_SECRET);
+      gtk_tree_view_column_set_sort_indicator (column, TRUE);
+    }
 
   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new_with_attributes (_("Key ID"), renderer,
@@ -304,24 +563,37 @@
   gtk_tree_view_column_set_sort_indicator (column, TRUE);
 }
 
-gboolean gpa_keylist_has_selection (GpaKeyList * keylist)
+
+/* Return true if any key is selected in the list.  */
+gboolean 
+gpa_keylist_has_selection (GpaKeyList * keylist)
 {
   GtkTreeSelection *selection = 
     gtk_tree_view_get_selection (GTK_TREE_VIEW (keylist));
   return gtk_tree_selection_count_selected_rows (selection) > 0;
 }
 
-gboolean gpa_keylist_has_single_selection (GpaKeyList * keylist)
+
+/* Return true if one, and only one, key is selected in the list.  */
+gboolean 
+gpa_keylist_has_single_selection (GpaKeyList * keylist)
 {
   GtkTreeSelection *selection = 
     gtk_tree_view_get_selection (GTK_TREE_VIEW (keylist));
   return gtk_tree_selection_count_selected_rows (selection) == 1;
 }
 
-gboolean gpa_keylist_has_single_secret_selection (GpaKeyList * keylist)
+
+/* Return true if one, and only one, secret key is selected in the list.  */
+gboolean 
+gpa_keylist_has_single_secret_selection (GpaKeyList *keylist)
 {
-  GtkTreeSelection *selection = 
-    gtk_tree_view_get_selection (GTK_TREE_VIEW (keylist));
+  GtkTreeSelection *selection;
+
+  if (keylist->public_only)
+    return FALSE;
+  
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (keylist));
   if (gtk_tree_selection_count_selected_rows (selection) == 1)
     {
       GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (keylist));
@@ -348,7 +620,11 @@
     }
 }
 
-GList *gpa_keylist_get_selected_keys (GpaKeyList * keylist)
+
+/* Return a GList of selected keys. The caller must not dereference
+   the keys as they belong to the caller.  */
+GList *
+gpa_keylist_get_selected_keys (GpaKeyList * keylist)
 {
   GtkTreeSelection *selection = 
     gtk_tree_view_get_selection (GTK_TREE_VIEW (keylist));
@@ -379,8 +655,47 @@
   return keys;
 }
 
-void gpa_keylist_start_reload (GpaKeyList * keylist)
+
+/* Return the selected key.  This function returns NULL if no or more
+   than one key has been selected.  */
+gpgme_key_t
+gpa_keylist_get_selected_key (GpaKeyList *keylist)
 {
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GList *list;
+  GtkTreePath *path;
+  GtkTreeIter iter;
+  GValue value = {0};
+  gpgme_key_t key;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (keylist));
+  if (gtk_tree_selection_count_selected_rows (selection) != 1)
+    return NULL;
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (keylist));
+  list = gtk_tree_selection_get_selected_rows (selection, &model);
+  if (!list)
+    return NULL;
+  path = list->data;
+
+  gtk_tree_model_get_iter (model, &iter, path);
+  gtk_tree_model_get_value (model, &iter, GPA_KEYLIST_COLUMN_KEY, &value);
+  key = g_value_get_pointer (&value);
+  g_value_unset (&value);      
+  gpgme_key_ref (key);
+
+  g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
+  g_list_free (list);
+  
+  return key;
+}
+
+
+/* Begin a reload of the keyring. */
+void 
+gpa_keylist_start_reload (GpaKeyList * keylist)
+{
   GtkTreeSelection *selection = 
     gtk_tree_view_get_selection (GTK_TREE_VIEW (keylist));
   gtk_tree_selection_unselect_all (selection);
@@ -395,11 +710,15 @@
 			     gpa_keylist_next, gpa_keylist_end, keylist);
 }
 
+
 /* Let the keylist know that a new key with the given fingerprint is
- * available.
- */
-void gpa_keylist_new_key (GpaKeyList * keylist, const char *fpr)
+   available.  */
+void 
+gpa_keylist_new_key (GpaKeyList * keylist, const char *fpr)
 {
+  /* FIXME: I don't understand the code.  Investigate this and
+     implement public_only.  */
+  
   add_trustdb_dialog (keylist);
   gpa_keytable_load_new (gpa_keytable_get_secret_instance (), fpr,
 			 NULL, (GpaKeyTableEndFunc) gtk_main_quit, NULL);
@@ -413,6 +732,7 @@
 			 gpa_keylist_next, gpa_keylist_end, keylist);
 }
 
+
 /* Let the keylist know that a new sceret key has been imported. */
 void 
 gpa_keylist_imported_secret_key (GpaKeyList *keylist)
@@ -422,242 +742,8 @@
   gpa_keytable_load_new (gpa_keytable_get_secret_instance (), NULL,
 			 NULL, (GpaKeyTableEndFunc) gtk_main_quit, NULL);
   /* Hack. Turn the asynchronous listing into a synchronous one */
+  /* FIXME:  Does that work well with the server shutdown code? */ 
   gtk_main ();
 }
 
 
-/* Internal functions */
-
-static gboolean
-display_dialog (GpaKeyList * keylist)
-{
-  gtk_widget_show_all (keylist->dialog);
-
-  keylist->timeout_id = 0;
-
-  return FALSE;
-}
-
-static void
-add_trustdb_dialog (GpaKeyList * keylist)
-{
-  /* Display this warning until the first key is received.
-   * It may be shown at times when it's not needed. But it shouldn't appear
-   * for long those times.
-   */
-  keylist->dialog = gtk_message_dialog_new (GTK_WINDOW (keylist->window),
-					    GTK_DIALOG_MODAL, 
-					    GTK_MESSAGE_INFO, 
-					    GTK_BUTTONS_NONE,
-					    _("GnuPG is rebuilding the trust "
-					      "database.\nThis might take a "
-					      "few seconds."));
-  /* Wait a second before displaying the dialog. This avoids most 
-   * "false alarms". */
-  keylist->timeout_id = g_timeout_add (1000, (GSourceFunc) display_dialog, 
-				       keylist);
-}
-
-static void
-remove_trustdb_dialog (GpaKeyList * keylist)
-{
-  if (keylist->timeout_id)
-    {
-      g_source_remove (keylist->timeout_id);
-      keylist->timeout_id = 0;
-    }
-  if (keylist->dialog)
-    {
-      gtk_widget_destroy (keylist->dialog);
-      keylist->dialog = NULL;
-    }
-}
-
-static GdkPixbuf*
-get_key_pixbuf (gpgme_key_t key)
-{
-  static gboolean pixmaps_created = FALSE;
-  static GdkPixbuf *secret_pixbuf = NULL;
-  static GdkPixbuf *public_pixbuf = NULL;
-
-  if (!pixmaps_created)
-    {
-      secret_pixbuf = gpa_create_icon_pixbuf ("blue_yellow_key");
-      public_pixbuf = gpa_create_icon_pixbuf ("blue_key");
-      pixmaps_created = TRUE;
-    }
-
-  if (gpa_keytable_lookup_key 
-      (gpa_keytable_get_secret_instance(), 
-       key->subkeys->fpr) != NULL)
-    {
-      return secret_pixbuf;
-    }
-  else
-    {
-      return public_pixbuf;
-    }
-}
-
-static GtkWidget *gpa_keylist_elgamal_dialog (gpgme_key_t key)
-{
-  GtkWidget *window;
-  GtkWidget *hbox, *vbox;
-  GtkWidget *pixmap;
-  GtkWidget *key_info;
-  GtkWidget *label;
-  
-  window = gtk_dialog_new_with_buttons (_("GPA Warning"), NULL,
-					GTK_DIALOG_MODAL,
-					_("_Close"),
-					GTK_RESPONSE_CLOSE,
-					NULL);
-  gtk_container_set_border_width (GTK_CONTAINER (window), 5);
-  gtk_dialog_set_default_response (GTK_DIALOG (window), GTK_RESPONSE_CLOSE);
-
-  hbox = gtk_hbox_new (FALSE, 0);
-  gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (window)->vbox), hbox);
-
-  pixmap = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
-                                     GTK_ICON_SIZE_DIALOG);
-  gtk_box_pack_start (GTK_BOX (hbox), pixmap, TRUE, FALSE, 10);
-
-  vbox = gtk_vbox_new (FALSE, 0);
-  gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, FALSE, 10);
-
-  label = gtk_label_new (_("One of your secret keys contains an ElGamal "
-			   "signing key. Due to a bug in GnuPG, all ElGamal "
-			   "keys used with GnuPG 1.0.2 and later must be "
-			   "considered compromised.\n\nPlease revoke your key "
-			   "as soon as possible.\n\nThe affected key is:"));
-  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
-  gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, FALSE, 2);
-
-  key_info = gpa_key_info_new (key);
-  gtk_box_pack_start (GTK_BOX (vbox), key_info, TRUE, FALSE, 2);
-
-  g_signal_connect (G_OBJECT (window), "response", 
-		    G_CALLBACK (gtk_widget_destroy), NULL);
-
-  return window;
-}
-
-
-/* For keys, gpg can't cope with, the fingerprint is set to all
-   zero. This helper function returns true for such a FPR. */
-static int
-is_zero_fpr (const char *fpr)
-{
-  for (; *fpr; fpr++)
-    if (*fpr != '0')
-      return 0;
-  return 1;
-}
-
-static void gpa_keylist_next (gpgme_key_t key, gpointer data)
-{
-  GpaKeyList *list = data;
-  GtkListStore *store;
-  GtkTreeIter iter;
-  const gchar *keyid, *ownertrust, *validity;
-  gchar *userid, *expiry;
-  gboolean has_secret;
-  long int val_value;
-
-  /* Remove the dialog if it is being displayed */
-  remove_trustdb_dialog (list);
-  
-  list->keys = g_list_append (list->keys, key);
-  store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (list)));
-  /* Get the column values */
-  keyid = gpa_gpgme_key_get_short_keyid (key);
-  expiry = gpa_expiry_date_string (key->subkeys->expires);
-  ownertrust = gpa_key_ownertrust_string (key);
-  validity = gpa_key_validity_string (key);
-  userid = gpa_gpgme_key_get_userid (key->uids);
-  has_secret = (!is_zero_fpr (key->subkeys->fpr)
-                && gpa_keytable_lookup_key (gpa_keytable_get_secret_instance(),
-                                            key->subkeys->fpr));
-
-  /* Check for ElGamal signing keys and warn the user.  See
-   * http://lists.gnupg.org/pipermail/gnupg-announce/2003q4/000276.html
-   * for details. Fixme: We should remove this as current GnuPG
-   * versions dropped all support for theses keys and revoking a key
-   * is not possble anymore.
-   */
-  if (has_secret)
-    {
-      gpgme_subkey_t subkey;
-      gboolean has_elg = FALSE;
-
-      for (subkey = key->subkeys; subkey && !has_elg; subkey = subkey->next)
-	{
-	  if (subkey->pubkey_algo == GPGME_PK_ELG && 
-	      !subkey->revoked && !subkey->expired)
-	    {
-	      has_elg = TRUE;
-	    }
-	}
-      if (has_elg)
-	{
-	  GtkWidget *dialog = gpa_keylist_elgamal_dialog (key);
-	  gtk_widget_show_all (dialog);
-	}
-    }
-  /* Append the key to the list */
-  gtk_list_store_append (store, &iter);
-
-  /* Set an appropiate value for sorting revoked and expired keys. This 
-   * includes a hack for forcing a value to a range outside the
-   * usual validity values */
-  if (key->subkeys->revoked)
-      val_value = GPGME_VALIDITY_UNKNOWN-2;
-  else if (key->subkeys->expired)
-      val_value = GPGME_VALIDITY_UNKNOWN-1;
-  else if (key->uids)
-      val_value = key->uids->validity;
-  else
-      val_value = GPGME_VALIDITY_UNKNOWN;
-
-  gtk_list_store_set (store, &iter,
-		      GPA_KEYLIST_COLUMN_IMAGE, get_key_pixbuf (key),
-		      GPA_KEYLIST_COLUMN_KEYID, keyid, 
-		      GPA_KEYLIST_COLUMN_EXPIRY, expiry,
-		      GPA_KEYLIST_COLUMN_OWNERTRUST, ownertrust,
-		      GPA_KEYLIST_COLUMN_VALIDITY, validity,
-		      GPA_KEYLIST_COLUMN_USERID, userid,
-		      GPA_KEYLIST_COLUMN_KEY, key, 
-		      GPA_KEYLIST_COLUMN_HAS_SECRET, has_secret,
-		      /* Set "no expiration" to a large value for sorting */
-		      GPA_KEYLIST_COLUMN_EXPIRY_TS, 
-		      key->subkeys->expires ? 
-		      key->subkeys->expires : G_MAXULONG,
-		      GPA_KEYLIST_COLUMN_OWNERTRUST_VALUE, 
-		      key->owner_trust,
-		      /* Set revoked and expired keys to "never trust" for 
-		       * sorting */
-		      GPA_KEYLIST_COLUMN_VALIDITY_VALUE, val_value,
-		      -1);
-  /* Clean up */
-  g_free (userid);
-  g_free (expiry);
-}
-
-static void gpa_keylist_end (gpointer data)
-{
-  GpaKeyList *list = data;
-  
-  remove_trustdb_dialog (list);
-}
-
-static void gpa_keylist_clear_columns (GpaKeyList *keylist)
-{
-  GList *columns, *i;
-
-  columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (keylist));
-  for (i = columns; i; i = g_list_next (i))
-    {
-      gtk_tree_view_remove_column (GTK_TREE_VIEW (keylist),
-                                   (GtkTreeViewColumn*) i->data);
-    }
-}

Modified: trunk/src/keylist.h
===================================================================
--- trunk/src/keylist.h	2008-03-06 16:00:47 UTC (rev 836)
+++ trunk/src/keylist.h	2008-03-06 19:42:46 UTC (rev 837)
@@ -1,21 +1,21 @@
 /* keylist.h  -  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 2 of the License, or
+ * 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.
+ * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef GPA_KEYLIST_H
@@ -46,6 +46,10 @@
   GtkWidget *dialog;
   /* ID of the timeout that displays the dialog */
   guint timeout_id;
+
+  /* Private: Do not use!  FIXME: We should hide all instance
+     variables.  */
+  gboolean public_only;
 };
 
 struct _GpaKeyListClass {
@@ -59,45 +63,43 @@
 
 /* API */
 
-/* Create a new key list widget.
- */
+/* Create a new key list widget.  */
 GtkWidget *gpa_keylist_new (GtkWidget * window);
 
-/* Set the key list in "brief" mode.
- */
+/* Create a new key list widget in public only mode.  */
+GpaKeyList *gpa_keylist_new_public_only (GtkWidget *window);
+
+/* Set the key list in "brief" mode.  */
 void gpa_keylist_set_brief (GpaKeyList * keylist);
 
-/* Set the key list in "detailed" mode
- */
+/* Set the key list in "detailed" mode.  */
 void gpa_keylist_set_detailed (GpaKeyList * keylist);
 
-/* Return true if any key is selected in the list.
- */
+/* Return true if any key is selected in the list.  */
 gboolean gpa_keylist_has_selection (GpaKeyList * keylist);
 
-/* Return true if one, and only one, key is selected in the list.
- */
+/* Return true if one, and only one, key is selected in the list.  */
 gboolean gpa_keylist_has_single_selection (GpaKeyList * keylist);
 
-/* Return true if one, and only one, secret key is selected in the list.
- */
+/* Return true if one, and only one, secret key is selected in the list.  */
 gboolean gpa_keylist_has_single_secret_selection (GpaKeyList * keylist);
 
-/* Return a GList of selected keys. The caller must not dereference the keys
- * as they belong to the caller.
- */
+/* Return a GList of selected keys. The caller must not dereference
+   the keys as they belong to the caller.  */
 GList *gpa_keylist_get_selected_keys (GpaKeyList * keylist);
 
-/* Begin a reload of the keyring.
- */
+/* Return the selected key.  This function returns NULL if no or more
+   than one key has been selected.  */
+gpgme_key_t gpa_keylist_get_selected_key (GpaKeyList *keylist);
+
+/* Begin a reload of the keyring. */
 void gpa_keylist_start_reload (GpaKeyList * keylist);
 
 /* Let the keylist know that a new key with the given fingerprint is
- * available.
- */
+   available. */
 void gpa_keylist_new_key (GpaKeyList * keylist, const char *fpr);
 
-/* Let the keylist know that a new sceret key has been imported. */
+/* Let the keylist know that a new sceret key has been imported.  */
 void gpa_keylist_imported_secret_key (GpaKeyList * keylist);
 
 

Modified: trunk/src/recipientdlg.c
===================================================================
--- trunk/src/recipientdlg.c	2008-03-06 16:00:47 UTC (rev 836)
+++ trunk/src/recipientdlg.c	2008-03-06 19:42:46 UTC (rev 837)
@@ -23,7 +23,7 @@
 #include "i18n.h"
 
 #include "gtktools.h"
-#include "gpakeyselector.h"
+#include "selectkeydlg.h"
 #include "recipientdlg.h"
 
 
@@ -37,10 +37,16 @@
   GtkWidget *radio_x509;
   GtkWidget *radio_auto;
 
+  GtkWidget *popup_menu;
+
   /* Flag to disable updates of the status hint.  This is actual a
-     counter with updates allowed if it is zero. */
-  int  disable_update_statushint;
+     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;
@@ -94,6 +100,9 @@
    recipient.  */
 struct userdata_s
 {
+  /* The recipient's address.  */
+  char *mailbox;
+
   /* Information about PGP keys.  */
   struct keyinfo_s pgp;
 
@@ -171,7 +180,7 @@
   /* Define the columns.  */
   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new_with_attributes 
-    (_("Recipient"), renderer, "text", RECPLIST_MAILBOX, NULL);
+    (_("Recipient"), renderer, "markup", RECPLIST_MAILBOX, NULL);
   set_column_title (column, _("Recipient"),
                     _("Shows the recipients of the message."
                       " A key needs to be assigned to each recipient."));
@@ -204,7 +213,26 @@
   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)
@@ -221,7 +249,7 @@
   const char *hint;
   int okay = 0;
 
-  if (dialog->disable_update_statushint)
+  if (dialog->freeze_update_statushint)
     return;
 
   g_debug ("update_statushint called");
@@ -311,12 +339,12 @@
              "a common encryption protocol can't be used. "
              "Please decide on one protocol by clicking one "
              "of the above radio buttons.");
-  else if (sel_protocol == GPGME_PROTOCOL_OpenPGP)
+  else if (n_pgp_keys && sel_protocol == GPGME_PROTOCOL_OpenPGP)
     {
       hint = _("Using OpenPGP for encryption.");
       okay = 1;
     }
-  else if (sel_protocol == GPGME_PROTOCOL_CMS)
+  else if (n_x509_keys && sel_protocol == GPGME_PROTOCOL_CMS)
     {
       hint = _("Using S/MIME for encryption.");
       okay = 1;
@@ -334,7 +362,7 @@
 }
 
 
-/* Add KEY to the keyarray of KEYINFO.  Owvership of KEY is moved to
+/* 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)
@@ -349,8 +377,8 @@
     }
   for (nkeys=0; keyinfo->keys[nkeys]; nkeys++)
     ;
-  /* Note that we silently skip KEY of NULL becuase we can't store
-     them in the array.  */
+  /* 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)
@@ -365,22 +393,102 @@
   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 - click to select]"));
+  else if (any_pgp && info->pgp.keys[1])
+    infostr = g_strdup (_("[ambiguous PGP key - click to select]"));
+  else if (any_x509 && info->x509.keys[1])
+    infostr = g_strdup (_("[ambiguous X.509 key - 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 (_("[click to select]"));
+
+
+  mailbox = g_markup_printf_escaped ("<span strikethrough='%s'>%s</span>",
+                                     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,
-                     const char *mailbox)
+                     struct userdata_s *info)
 {
-  gpgme_key_t key;
-  int any_pgp = 0, any_x509 = 0;
-  char *infostr = NULL;
-  struct userdata_s *info;
+  gpgme_key_t key = NULL;
 
-  key = NULL;
-  info = g_malloc0 (sizeof *info);
+  g_return_if_fail (info);
 
+  clear_keyinfo (&info->pgp);
   gpgme_set_protocol (ctx, GPGME_PROTOCOL_OpenPGP);
-  if (!gpgme_op_keylist_start (ctx, mailbox, 0))
+  if (!gpgme_op_keylist_start (ctx, info->mailbox, 0))
     {
       while (!gpgme_op_keylist_next (ctx, &key))
         {
@@ -398,8 +506,10 @@
         }
     }
   gpgme_op_keylist_end (ctx);
+
+  clear_keyinfo (&info->x509);
   gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
-  if (!gpgme_op_keylist_start (ctx, mailbox, 0))
+  if (!gpgme_op_keylist_start (ctx, info->mailbox, 0))
     {
       while (!gpgme_op_keylist_next (ctx, &key))
         {
@@ -415,40 +525,7 @@
     }
   gpgme_op_keylist_end (ctx);
 
-
-  if (info->pgp.keys && info->pgp.keys[0])
-    any_pgp = 1;
-  if (info->x509.keys && info->x509.keys[0])
-    any_x509 = 1;
-
-  if (any_pgp && any_x509 && info->pgp.keys[1] && info->x509.keys[1])
-    infostr = g_strdup (_("[ambiguous keys - click to select]"));
-  else if (any_pgp && info->pgp.keys[1])
-    infostr = g_strdup (_("[ambiguous PGP key - click to select]"));
-  else if (any_x509 && info->x509.keys[1])
-    infostr = g_strdup (_("[ambiguous X.509 key - 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 (_("[click to select]"));
-  
-  g_print ("   pgp=%d x509=%d infostr=`%s'\n", any_pgp, any_x509, infostr);
-  gtk_list_store_set (store, iter,
-                      RECPLIST_HAS_PGP, any_pgp,
-                      RECPLIST_HAS_X509, any_x509,
-                      RECPLIST_KEYID, infostr,
-                      RECPLIST_USERDATA, info,
-                      -1);
-  g_free (infostr);
+  update_recplist_row (store, iter, info);
 }
 
 
@@ -473,22 +550,23 @@
   if (gtk_tree_model_get_iter_first (model, &iter))
     do
       {
-        char *mailbox;
+        struct userdata_s *info;
         
         gtk_tree_model_get (model, &iter, 
-                            RECPLIST_MAILBOX, &mailbox,
+                            RECPLIST_USERDATA, &info,
                             -1);
         
         /* Do something with the data */
-        g_print ("parsing mailbox `%s'\n", mailbox);
-        parse_one_recipient (ctx, store, &iter, mailbox);
-        g_free (mailbox);
+        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,
@@ -559,6 +637,209 @@
 
 
 
+/* 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_print ("selected key is `%s'\n", uidstr);
+      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)
+        {
+          seldlg = select_key_dlg_new (GTK_WIDGET (dialog));
+          if (protocol == GPGME_PROTOCOL_OpenPGP)
+            select_key_dlg_set_keys (seldlg, info->pgp.keys, protocol);
+          else if (protocol == GPGME_PROTOCOL_CMS)
+            select_key_dlg_set_keys (seldlg, info->x509.keys, protocol);
+          
+          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 (RecipientDlg *dialog)
+{
+  do_select_key (dialog, GPGME_PROTOCOL_OpenPGP);
+}
+
+static void
+recplist_popup_x509 (RecipientDlg *dialog)
+{
+  do_select_key (dialog, GPGME_PROTOCOL_CMS);
+}
+
+static void
+recplist_popup_ignore (RecipientDlg *dialog)
+{
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  struct userdata_s *info;
+
+  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 (menu, NULL, NULL, NULL, NULL, 
+                                event_button->button, event_button->time);
+	    }
+	  return TRUE;
+	}
+    }
+
+  return FALSE;
+}
+
+
+/* Create the popup menu for the recipient list.  */
+static GtkWidget *
+recplist_popup_menu_new (GtkWidget *window, RecipientDlg *dialog)
+{
+  GtkItemFactory *factory;
+  GtkItemFactoryEntry popup_menu[] =
+    {
+      {_("/Select _PGP key..."), NULL, recplist_popup_pgp, 0, NULL},
+      {_("/Select _S\\/MIME key..."), NULL, recplist_popup_x509, 0, NULL},
+      {_("/_Ignore this key"), NULL, recplist_popup_ignore, 0, NULL},
+    };
+  //  GtkWidget *item;
+
+  factory = gtk_item_factory_new (GTK_TYPE_MENU, "<main>", NULL);
+  gtk_item_factory_create_items (factory,
+                                 sizeof (popup_menu) / sizeof (popup_menu[0]),
+                                 popup_menu, dialog);
+
+  /* Only if there is only ONE key selected.  */
+/*   item = gtk_item_factory_get_widget (GTK_ITEM_FACTORY(factory), */
+/*                                       _("/Set Owner Trust...")); */
+/*   if (item) */
+/*     add_selection_sensitive_widget (editor, item, */
+/* 				    keyring_editor_has_single_selection); */
+
+  return gtk_item_factory_get_widget (factory, "<main>");
+}
+
+
 
 /************************************************************ 
  ******************   Object Management  ********************
@@ -605,6 +886,7 @@
 static void
 recipient_dlg_finalize (GObject *object)
 {  
+  /* Fixme:  Release the store.  */
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -612,7 +894,6 @@
 static void
 recipient_dlg_init (RecipientDlg *dialog)
 {
-  dialog->disable_update_statushint = 0;
 }
 
 
@@ -669,6 +950,11 @@
   gpa_connect_by_accelerator (GTK_LABEL (labelKeys), clistKeys, accel_group,
 			      _("_Recipient list"));
 
+  dialog->popup_menu = recplist_popup_menu_new (dialog->clist_keys, dialog);
+  g_signal_connect_swapped (GTK_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 
@@ -801,7 +1087,7 @@
 
   g_return_if_fail (dialog);
 
-  dialog->disable_update_statushint++;
+  dialog->freeze_update_statushint++;
 
   if (protocol == GPGME_PROTOCOL_OpenPGP)
     widget = dialog->radio_pgp;
@@ -827,19 +1113,22 @@
       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, name,
+                              RECPLIST_MAILBOX, g_strdup (""),
                               RECPLIST_HAS_PGP, FALSE,
                               RECPLIST_HAS_X509, FALSE,
-                              RECPLIST_KEYID,  "",
-                              RECPLIST_USERDATA, NULL,
+                              RECPLIST_KEYID,  NULL,
+                              RECPLIST_USERDATA, info,
                               -1);
         }    
     }
 
   parse_recipients (store);
-  dialog->disable_update_statushint--;
+  dialog->freeze_update_statushint--;
   update_statushint (dialog);
 }
 

Added: trunk/src/selectkeydlg.c
===================================================================
--- trunk/src/selectkeydlg.c	2008-03-06 16:00:47 UTC (rev 836)
+++ trunk/src/selectkeydlg.c	2008-03-06 19:42:46 UTC (rev 837)
@@ -0,0 +1,334 @@
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "gpa.h"
+#include "i18n.h"
+
+#include "gtktools.h"
+#include "keylist.h"
+#include "selectkeydlg.h"
+
+
+struct _SelectKeyDlg 
+{
+  GtkDialog parent;
+  
+  GpaKeyList *keylist;
+};
+
+
+struct _SelectKeyDlgClass 
+{
+  GtkDialogClass parent_class;
+
+};
+
+
+/* The parent class.  */
+static GObjectClass *parent_class;
+
+
+/* Indentifiers for our properties. */
+enum 
+  {
+    PROP_0,
+    PROP_WINDOW,
+    PROP_FORCE_ARMOR
+  };
+
+
+
+
+
+
+
+
+/* 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;
+    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;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+static void
+select_key_dlg_finalize (GObject *object)
+{  
+  /* 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;
+  GtkAccelGroup *accel_group;
+  GtkWidget *vbox;
+  GtkWidget *scroller;
+
+  object = parent_class->constructor (type,
+				      n_construct_properties,
+				      construct_properties);
+  dialog = SELECT_KEY_DLG (object);
+
+
+  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+			  GTK_STOCK_OK, GTK_RESPONSE_OK,
+			  _("_Cancel"), GTK_RESPONSE_CANCEL, NULL);
+  gtk_window_set_title (GTK_WINDOW (dialog),
+                        _("Select a key"));
+  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);
+
+  accel_group = gtk_accel_group_new ();
+  gtk_window_add_accel_group (GTK_WINDOW (dialog), accel_group);
+
+  vbox = GTK_DIALOG (dialog)->vbox;
+  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);
+
+  dialog->keylist = gpa_keylist_new_public_only (GTK_WIDGET (dialog));
+  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));
+
+}
+
+
+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;
+}
+
+
+/* Fill the list with KEYS.  PROTOCOL may be used to retsitc the
+   search to one type of keys.  To allow all keys, use
+   GPGME_PROTOCOL_UNKNOWN.  */
+void 
+select_key_dlg_set_keys (SelectKeyDlg *dialog, gpgme_key_t *keys,
+                         gpgme_protocol_t protocol)
+{
+/*   GtkListStore *store; */
+/*   GSList *recp; */
+/*   GtkTreeIter iter; */
+/*   const char *name; */
+/*   GtkWidget *widget; */
+
+/*   g_return_if_fail (dialog); */
+
+/*   if (protocol == GPGME_PROTOCOL_OpenPGP) */
+/*     widget = dialog->radio_pgp; */
+/*   else if (protocol == GPGME_PROTOCOL_CMS) */
+/*     widget = dialog->radio_x509; */
+/*   else */
+/*     widget = NULL; */
+/*   if (widget) */
+/*     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);   */
+/*     } */
+  
+/*   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); */
+          
+/*           gtk_list_store_append (store, &iter); */
+/*           gtk_list_store_set (store, &iter, */
+/*                               RECPLIST_MAILBOX, name, */
+/*                               RECPLIST_HAS_PGP, FALSE, */
+/*                               RECPLIST_HAS_X509, FALSE, */
+/*                               RECPLIST_KEYID,  g_strdup (""), */
+/*                               RECPLIST_USERDATA, info, */
+/*                               -1); */
+/*         }     */
+/*     } */
+
+/*   parse_recipients (store); */
+/*   dialog->disable_update_statushint--; */
+/*   update_statushint (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;
+}
+
+
+

Added: trunk/src/selectkeydlg.h
===================================================================
--- trunk/src/selectkeydlg.h	2008-03-06 16:00:47 UTC (rev 836)
+++ trunk/src/selectkeydlg.h	2008-03-06 19:42:46 UTC (rev 837)
@@ -0,0 +1,113 @@
+/* selectkeydlg.h - 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SELECTKEYDLG_H
+#define SELECTKEYDLG_H
+
+/*
+   This dialog allow the selection of a single public or secret key.
+   The visual layout is:
+
+      +-----------------------+ +------+
+      |                       | |Search|
+      +-----------------------+ +------+
+       (x) PGP  (x) x509  
+      +--------------------------------+
+      | List of keys                   |
+      |                                |
+      |                                |
+      |                                |
+      |                                |
+      |                                |
+      |                                |
+      |                                |
+      +--------------------------------+
+                        +------++------+
+                        |Select||Cancel|
+                        +------++------+
+
+    Initially the search box is empty and the list of keys is filled
+    with the supplied keys.  The caller may choose whether PGP, X.509
+    or both keys are displayed.  The default is both.  If the caller
+    specified one mode, the user is not allowed to override it and the
+    list will be filtered for displaying only supplied keys of the
+    specfied type.  If none are specified, the user may restrict the
+    search to one protocol.
+
+    Usage:
+
+       WORK IN PROGRESS
+
+
+ */
+
+
+
+
+
+
+
+
+/* Definitions to define the object.  */
+#define SELECT_KEY_DLG_TYPE \
+          (select_key_dlg_get_type ())
+
+#define SELECT_KEY_DLG(obj) \
+          (G_TYPE_CHECK_INSTANCE_CAST \
+            ((obj), SELECT_KEY_DLG_TYPE,\
+              SelectKeyDlg))
+
+#define SELECT_KEY_DLG_CLASS(klass) \
+          (G_TYPE_CHECK_CLASS_CAST \
+            ((klass), SELECT_KEY_DLG_TYPE, \
+              SelectKeyDlgClass))
+
+#define IS_SELECT_KEY_DLG(obj) \
+          (G_TYPE_CHECK_INSTANCE_TYPE \
+            ((obj), SELECT_KEY_DLG_TYPE))
+
+#define IS_SELECT_KEY_DLG_CLASS(klass) \
+          (G_TYPE_CHECK_CLASS_TYPE \
+            ((klass), SELECT_KEY_DLG_TYPE))
+
+#define SELECT_KEY_DLG_GET_CLASS(obj) \
+          (G_TYPE_INSTANCE_GET_CLASS \
+            ((obj), SELECT_KEY_DLG_TYPE, \
+              SelectKeyDlgClass))
+
+typedef struct _SelectKeyDlg SelectKeyDlg;
+typedef struct _SelectKeyDlgClass SelectKeyDlgClass;
+
+
+GType select_key_dlg_get_type (void) G_GNUC_CONST;
+
+
+/************************************
+ ************ Public API ************
+ ************************************/
+
+SelectKeyDlg *select_key_dlg_new (GtkWidget *parent);
+void select_key_dlg_set_keys (SelectKeyDlg *dialog,
+                              gpgme_key_t *keys,
+                              gpgme_protocol_t protocol);
+gpgme_key_t select_key_dlg_get_key (SelectKeyDlg *dialog);
+
+
+
+#endif /*SELECTKEYDLG_H*/

Modified: trunk/src/server.c
===================================================================
--- trunk/src/server.c	2008-03-06 16:00:47 UTC (rev 836)
+++ trunk/src/server.c	2008-03-06 19:42:46 UTC (rev 837)
@@ -84,6 +84,13 @@
 };
 
 
+/* The number of active connections.  */
+static int connection_counter;
+
+/* A flag requesting a shutdown.  */
+static gboolean shutdown_pending;
+
+
 /* The nonce used by the server connection.  This nonce is required
    uner Windows to emulate Unix Domain Sockets.  This is managed by
    libassuan but we need to store the nonce in the application.  Under
@@ -835,6 +842,7 @@
   assuan_set_log_stream (ctx, stderr);
   assuan_register_reset_notify (ctx, reset_notify);
 
+  connection_counter++;
   return ctx;
 }
 
@@ -851,6 +859,9 @@
       reset_notify (ctx);
       assuan_deinit_server (ctx);
       g_free (ctrl);
+      connection_counter--;
+      if (!connection_counter && shutdown_pending)
+        gtk_main_quit ();
     }
 }
 
@@ -1089,7 +1100,6 @@
       assuan_sock_close (fd);
       return;
     }
-
 #ifdef HAVE_W32_SYSTEM
   channel = g_io_channel_win32_new_socket (ASSUAN_FD2INT(fd));
 #else
@@ -1114,3 +1124,12 @@
     }
 
 }
+
+/* Set a flag to shutdown the server in a friendly way.  */
+void
+gpa_stop_server (void)
+{
+  shutdown_pending = TRUE;
+  if (!connection_counter)
+    gtk_main_quit ();
+}



More information about the Gpa-commits mailing list