[Gpa-commits] r952 - trunk/src
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Fri Feb 20 19:41:54 CET 2009
Author: werner
Date: 2009-02-20 19:41:46 +0100 (Fri, 20 Feb 2009)
New Revision: 952
Modified:
trunk/src/ChangeLog
trunk/src/cm-openpgp.c
Log:
Implement an edit framework.
Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog 2009-02-20 12:28:09 UTC (rev 951)
+++ trunk/src/ChangeLog 2009-02-20 18:41:46 UTC (rev 952)
@@ -1,3 +1,7 @@
+2009-02-20 Werner Koch <wk at g10code.com>
+
+ * cm-openpgp.c: Implemented an entry edit framework.
+
2009-02-19 Werner Koch <wk at g10code.com>
* cm-object.h (struct _GpaCMObject): Add field agent_ctx.
Modified: trunk/src/cm-openpgp.c
===================================================================
--- trunk/src/cm-openpgp.c 2009-02-20 12:28:09 UTC (rev 951)
+++ trunk/src/cm-openpgp.c 2009-02-20 18:41:46 UTC (rev 952)
@@ -77,6 +77,7 @@
GtkWidget *pin_frame;
GtkWidget *entries[ENTRY_LAST];
+ gboolean changed[ENTRY_LAST];
};
/* The parent class. */
@@ -126,6 +127,30 @@
}
+static void
+clear_changed_flags (GpaCMOpenpgp *card)
+{
+ int idx;
+
+ for (idx=0; idx < ENTRY_LAST; idx++)
+ card->changed[idx] = 0;
+}
+
+
+/* Show the error string TEXT in the status bar. With TEXT of NULL
+ clear the edit error message. */
+static void
+show_edit_error (GpaCMOpenpgp *card, const char *text)
+{
+ /* FIXME: We need a mechnism to update the status bar of the card
+ manager. A signal may be useful for this. */
+ if (text)
+ g_debug ("Edit error: %s", text);
+ else
+ g_debug ("Clear edit error");
+}
+
+
/* Update the the serialno field. This also updates the version and
the manufacturer field. */
static void
@@ -303,6 +328,8 @@
struct scd_getattr_parm parm;
gpgme_ctx_t gpgagent;
+ show_edit_error (card, NULL);
+
gpgagent = GPA_CM_OBJECT (card)->agent_ctx;
g_return_if_fail (gpgagent);
@@ -337,136 +364,148 @@
}
}
+ clear_changed_flags (card);
}
-static GtkDialog *
-create_edit_dialog (GpaCMOpenpgp *card, const char *title)
+/* Check the constraints for NAME and return a string with an error
+ description or NULL if the name is fine. */
+static const char *
+check_one_name (const char *name)
{
- GtkDialog *dialog;
+ int i;
- dialog = GTK_DIALOG (gtk_dialog_new_with_buttons
- (title,
- GTK_WINDOW (card),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK,
- NULL));
- gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
- gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
- GTK_RESPONSE_OK,
- GTK_RESPONSE_CANCEL,
- -1);
- return dialog;
+ for (i=0; name[i] && name[i] >= ' ' && name[i] <= 126; i++)
+ ;
+
+ /* The name must be in Latin-1 and not UTF-8 - lacking the code to
+ ensure this we restrict it to ASCII. */
+ if (name[i])
+ return _("Only plain ASCII is currently allowed.");
+ else if (strchr (name, '<'))
+ return _("The \"<\" character may not be used.");
+ else if (strstr (name, " "))
+ return _("Double spaces are not allowed.");
+ else
+ return NULL;
}
-/* Run the dialog and return true if the user affirmed the change. */
-static int
-run_edit_dialog (GtkDialog *dialog)
+/* Save the first and last name fields. Returns true on error. */
+static gboolean
+save_entry_name (GpaCMOpenpgp *card)
{
- gtk_widget_show_all (GTK_WIDGET (dialog));
- return (gtk_dialog_run (dialog) == GTK_RESPONSE_OK);
+ const char *first, *last;
+ const char *errstr;
+
+ first = gtk_entry_get_text (GTK_ENTRY (card->entries[ENTRY_FIRST_NAME]));
+ last = gtk_entry_get_text (GTK_ENTRY (card->entries[ENTRY_LAST_NAME]));
+ errstr = check_one_name (first);
+ if (!errstr)
+ errstr = check_one_name (last);
+ if (!errstr)
+ {
+ char *buffer, *p;
+
+ buffer = g_strdup_printf ("%s<<%s", last, first);
+ for (p=buffer; *p; p++)
+ if (*p == ' ')
+ *p = '<';
+ if (strlen (buffer) > 39)
+ errstr = _("Total length of first and last name "
+ "may not be longer than 39 characters.");
+ else
+ {
+ g_debug ("Saving name `%s'", buffer);
+ }
+ g_free (buffer);
+ }
+
+ if (errstr)
+ show_edit_error (card, errstr);
+
+ return !!errstr;
}
-
-static void
-destroy_edit_dialog (GtkDialog *dialog)
+static gpg_error_t
+save_entry_sex (GpaCMOpenpgp *card)
{
- gtk_widget_destroy (GTK_WIDGET (dialog));
+ return 0;
}
-/* Action for the Edit Name button. Display a new dialog through
- which the user can change the name (firstname + lastname) stored on
- the card.*/
+/* Callback for the "changed" signal connected to entry fields. We
+ figure out the entry field for which this signal has been emitted
+ and set a flag to know ehether we have unsaved data. */
static void
-edit_name_cb (GtkWidget *widget, void *opaque)
+edit_changed_cb (GtkEditable *editable, void *opaque)
{
GpaCMOpenpgp *card = opaque;
- GtkDialog *dialog;
- GtkWidget *first_name, *last_name;
- GtkWidget *content_area;
- GtkWidget *table;
-
- dialog = create_edit_dialog (card, _("Change Name"));
+ int idx;
- content_area = GTK_DIALOG (dialog)->vbox;
-
- table = gtk_table_new (3, 3, FALSE);
- gtk_container_set_border_width (GTK_CONTAINER (table), 10);
-
- gtk_table_attach (GTK_TABLE (table),
- gtk_label_new ("Current Value:"),
- 0, 1, 1, 2, GTK_FILL, GTK_SHRINK, 0, 0);
- gtk_table_attach (GTK_TABLE (table),
- gtk_label_new ("New Value:"),
- 0, 1, 2, 3, GTK_FILL, GTK_SHRINK, 0, 0);
-
- gtk_table_attach (GTK_TABLE (table),
- gtk_label_new ("First Name"),
- 1, 2, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0);
- gtk_table_attach (GTK_TABLE (table),
- gtk_label_new ("Last Name"),
- 2, 3, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0);
-
- gtk_table_attach (GTK_TABLE (table),
- gtk_label_new
- (gtk_entry_get_text
- (GTK_ENTRY (card->entries[ENTRY_FIRST_NAME]))),
- 1, 2, 1, 2, GTK_FILL, GTK_SHRINK, 0, 0);
- gtk_table_attach (GTK_TABLE (table),
- gtk_label_new
- (gtk_entry_get_text
- (GTK_ENTRY (card->entries[ENTRY_LAST_NAME]))),
- 2, 3, 1, 2, GTK_FILL, GTK_SHRINK, 0, 0);
-
- first_name = gtk_entry_new ();
- last_name = gtk_entry_new ();
-
- gtk_table_attach (GTK_TABLE (table), first_name,
- 1, 2, 2, 3, GTK_FILL, GTK_SHRINK, 0, 0);
- gtk_table_attach (GTK_TABLE (table), last_name,
- 2, 3, 2, 3, GTK_FILL, GTK_SHRINK, 0, 0);
+ for (idx=0; idx < ENTRY_LAST; idx++)
+ if (GTK_EDITABLE (card->entries[idx]) == editable)
+ break;
+ if (!(idx < ENTRY_LAST))
+ return;
- gtk_container_add (GTK_CONTAINER (content_area), table);
-
-
- if (run_edit_dialog (dialog))
+ if (!card->changed[idx])
{
-
-
-
+ card->changed[idx] = TRUE;
+ g_debug ("changed signal for entry %d", idx);
}
-
- destroy_edit_dialog (dialog);
}
-
-static void
-edit_sex_cb (GtkWidget *widget, void *opaque)
+/* Callback for the "focus" signal connected to entry fields. We
+ figure out the entry field for which this signal has been emitted
+ and whether we are receiving or losing focus. If a the change flag
+ has been set and we are losing focus we call the save function to
+ store the data on the card. If the change function returns true,
+ an error occurred and we keep the focus at the current field. */
+static gboolean
+edit_focus_cb (GtkWidget *widget, GtkDirectionType direction, void *opaque)
{
-}
+ GpaCMOpenpgp *card = opaque;
+ int idx;
+ int result = FALSE; /* Continue calling other handlers. */
+
+ for (idx=0; idx < ENTRY_LAST; idx++)
+ if (card->entries[idx] == widget)
+ break;
+ if (!(idx < ENTRY_LAST))
+ return FALSE;
+ if (gtk_widget_is_focus (widget))
+ {
+ /* Entry IDX is about to lose the focus. */
+ if (card->changed[idx])
+ {
+ switch (idx)
+ {
+ case ENTRY_FIRST_NAME:
+ case ENTRY_LAST_NAME:
+ result = save_entry_name (card);
+ break;
+ case ENTRY_SEX:
+ result = save_entry_sex (card);
+ break;
+ }
-
-static void
-edit_language_cb (GtkWidget *widget, void *opaque)
-{
+ if (!result)
+ {
+ card->changed[idx] = 0;
+ show_edit_error (card, NULL);
+ }
+ }
+ }
+ else
+ {
+ /* Entry IDX is about to receive the focus. */
+ }
+ return result;
}
-static void
-edit_login_cb (GtkWidget *widget, void *opaque)
-{
-}
-
-static void
-edit_url_cb (GtkWidget *widget, void *opaque)
-{
-}
-
-
/* Helper for construct_data_widget. */
static void
@@ -481,7 +520,6 @@
gtk_table_attach (GTK_TABLE (table), label, 0, 1,
*rowidx, *rowidx + 1, GTK_FILL, GTK_SHRINK, 0, 0);
- gtk_editable_set_editable (GTK_EDITABLE (widget), FALSE);
gtk_entry_set_has_frame (GTK_ENTRY (widget), FALSE);
gtk_table_attach (GTK_TABLE (table), widget, 1, 2,
@@ -507,8 +545,8 @@
GtkWidget *keys_table;
GtkWidget *pin_frame;
GtkWidget *pin_table;
- GtkWidget *button;
int rowidx;
+ int idx;
/* Create frames and tables. */
@@ -576,41 +614,21 @@
"Last Name:",
card->entries[ENTRY_LAST_NAME], NULL);
- button = gtk_button_new_from_stock (GTK_STOCK_EDIT);
- gtk_table_attach (GTK_TABLE (personal_table), button,
- 2, 3, rowidx-2, rowidx,
- GTK_SHRINK, GTK_FILL, 0, 0);
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (edit_name_cb), card);
-
-
card->entries[ENTRY_SEX] = gtk_entry_new ();
- button = gtk_button_new_from_stock (GTK_STOCK_EDIT);
add_table_row (personal_table, &rowidx,
- "Sex:", card->entries[ENTRY_SEX], button);
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (edit_sex_cb), card);
+ "Sex:", card->entries[ENTRY_SEX], NULL);
card->entries[ENTRY_LANGUAGE] = gtk_entry_new ();
- button = gtk_button_new_from_stock (GTK_STOCK_EDIT);
add_table_row (personal_table, &rowidx,
- "Language: ", card->entries[ENTRY_LANGUAGE], button);
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (edit_language_cb), card);
+ "Language: ", card->entries[ENTRY_LANGUAGE], NULL);
card->entries[ENTRY_LOGIN] = gtk_entry_new ();
- button = gtk_button_new_from_stock (GTK_STOCK_EDIT);
add_table_row (personal_table, &rowidx,
- "Login Data: ", card->entries[ENTRY_LOGIN], button);
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (edit_login_cb), card);
+ "Login Data: ", card->entries[ENTRY_LOGIN], NULL);
card->entries[ENTRY_PUBKEY_URL] = gtk_entry_new ();
- button = gtk_button_new_from_stock (GTK_STOCK_EDIT);
add_table_row (personal_table, &rowidx,
- "Public key URL: ", card->entries[ENTRY_PUBKEY_URL], button);
- g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (edit_url_cb), card);
+ "Public key URL: ", card->entries[ENTRY_PUBKEY_URL], NULL);
gtk_container_add (GTK_CONTAINER (personal_frame), personal_table);
@@ -665,6 +683,16 @@
gtk_box_pack_start (GTK_BOX (card), keys_frame, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (card), pin_frame, FALSE, TRUE, 0);
+ /* Setup signals */
+ for (idx=0; idx < ENTRY_LAST; idx++)
+ if (card->entries[idx] && GTK_IS_EDITABLE (card->entries[idx]))
+ {
+ g_signal_connect (G_OBJECT (card->entries[idx]), "changed",
+ G_CALLBACK (edit_changed_cb), card);
+ g_signal_connect (G_OBJECT (card->entries[idx]), "focus",
+ G_CALLBACK (edit_focus_cb), card);
+ }
+
}
More information about the Gpa-commits
mailing list