2 * This file is part of hildon-libs
4 * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
6 * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; version 2.1 of
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * SECTION:hildon-set-password-dialog
27 * @short_description: A dialog used to set, change or remove a password
28 * @see_also: #HildonGetPasswordDialog
30 * HildonSetPasswordDialog allows setting and changing a password.
32 * In Change mode: Dialog is used to change or remove an existing
33 * password. Unselecting the check box dims the password fields below
34 * it. If the dialog is accepted with 'OK' while the check box is
35 * unselected, a Confirmation Note is shown. If the Confirmation Note
36 * Dialog is accepted with 'Remove', the password protection is removed.
38 * In Set mode: Set Password Dialog is used to define a password, or
39 * change a password that cannot be removed.
47 #include <gdk/gdkkeysyms.h>
57 #include <hildon-widgets/hildon-caption.h>
58 #include <hildon-widgets/gtk-infoprint.h>
59 #include <hildon-widgets/hildon-set-password-dialog.h>
60 #include <hildon-widgets/hildon-note.h>
61 #include <hildon-widgets/hildon-defines.h>
64 #define _(String) dgettext(PACKAGE, String)
65 #define c_(String) dgettext("hildon-common-strings", String)
67 static GtkDialogClass *parent_class;
69 #define HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(obj)\
70 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
71 HILDON_TYPE_SET_PASSWORD_DIALOG, HildonSetPasswordDialogPrivate));
74 _HildonSetPasswordDialogPrivate HildonSetPasswordDialogPrivate;
77 hildon_set_password_dialog_class_init(HildonSetPasswordDialogClass *
79 static void hildon_set_password_dialog_init(HildonSetPasswordDialog *
81 static void hildon_checkbox_toggled(GtkWidget * widget, gpointer dialog);
84 hildon_set_password_response_change(GtkDialog * d, gint arg1, gpointer unused);
86 hildon_set_password_response_set(GtkDialog * d, gint arg1, gpointer unused);
88 static void create_contents(HildonSetPasswordDialog *dialog);
89 static void hildon_set_password_set_property(GObject * object,
93 static void hildon_set_password_get_property(GObject * object,
94 guint prop_id, GValue * value,
98 struct _HildonSetPasswordDialogPrivate {
99 GtkWidget *checkboxCaption;
102 GtkLabel *domainLabel;
104 GtkWidget *pwd1stEntry;
105 GtkWidget *pwd1stCaption;
106 gchar *pwd1stCaption_string;
108 GtkWidget *pwd2ndEntry;
109 GtkWidget *pwd2ndCaption;
110 gchar *pwd2ndCaption_string;
113 GtkWidget *cancelButton;
122 PROP_HILDON_PASSWORD_DIALOG
125 /* Private functions */
127 hildon_set_password_set_property(GObject * object,
129 const GValue * value, GParamSpec * pspec)
131 HildonSetPasswordDialog *dialog = HILDON_SET_PASSWORD_DIALOG(object);
132 HildonSetPasswordDialogPrivate *priv;
134 priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog);
138 /* Update domain label to display new value */
139 gtk_label_set_text(priv->domainLabel, g_value_get_string(value));
142 /* Update password entry to display new value */
143 gtk_entry_set_text(GTK_ENTRY(priv->pwd1stEntry), g_value_get_string(value));
145 case PROP_HILDON_PASSWORD_DIALOG:
146 /* Note this is a G_PARAM_CONSTRUCT_ONLY type property */
147 priv->protection = g_value_get_boolean(value);
149 /* We now have the necessary information to populate the dialog */
150 create_contents(dialog);
153 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
159 hildon_set_password_get_property(GObject * object,
164 HildonSetPasswordDialogPrivate *priv = NULL;
166 priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(object);
170 g_value_set_string(value, gtk_label_get_text(priv->domainLabel));
173 g_value_set_string(value,
174 gtk_entry_get_text(GTK_ENTRY(priv->pwd1stEntry)));
176 case PROP_HILDON_PASSWORD_DIALOG:
177 g_value_set_boolean(value, priv->protection);
180 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
187 create_contents(HildonSetPasswordDialog *dialog)
189 HildonSetPasswordDialogPrivate *priv = NULL;
193 priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog);
194 priv->checkbox = NULL;
196 /* Size group for labels */
197 group = GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL));
199 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
201 /* Setup and pack domain label */
202 priv->domainLabel = GTK_LABEL(gtk_label_new(NULL));
203 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
204 GTK_WIDGET(priv->domainLabel), FALSE, FALSE, 0);
205 gtk_widget_show(GTK_WIDGET(priv->domainLabel));
207 if (priv->protection == TRUE) {
208 /* Use Change Password Dialog strings */
209 priv->pwd1stCaption_string = _(HILDON_SET_MODIFY_PASSWORD_DIALOG_PASSWORD);
210 priv->pwd2ndCaption_string = _(HILDON_SET_MODIFY_PASSWORD_DIALOG_VERIFY_PASSWORD);
212 /* Setup checkbox to enable/disable password protection */
213 priv->checkbox = gtk_check_button_new();
214 gtk_widget_show(priv->checkbox);
215 priv->checkboxCaption = hildon_caption_new
217 _(HILDON_SET_MODIFY_PASSWORD_DIALOG_LABEL),
219 NULL, HILDON_CAPTION_OPTIONAL);
220 hildon_caption_set_separator(HILDON_CAPTION(priv->checkboxCaption), "");
221 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
222 priv->checkboxCaption, TRUE, TRUE, 0);
223 gtk_widget_show(priv->checkboxCaption);
224 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbox),
226 gtk_signal_connect(GTK_OBJECT(priv->checkbox), "toggled",
227 G_CALLBACK(hildon_checkbox_toggled), dialog);
229 /* Setup appropriate response handler */
230 g_signal_connect(G_OBJECT(dialog), "response",
231 G_CALLBACK(hildon_set_password_response_change),
234 /* Use Set Password Dialog strings */
235 priv->pwd1stCaption_string = _(HILDON_SET_PASSWORD_DIALOG_PASSWORD);
236 priv->pwd2ndCaption_string = _(HILDON_SET_PASSWORD_DIALOG_VERIFY_PASSWORD);
238 /* Setup appropriate response handler */
239 g_signal_connect(G_OBJECT(dialog), "response",
240 G_CALLBACK(hildon_set_password_response_set),
244 /* Create the password field */
245 priv->pwd1stEntry = gtk_entry_new();
246 g_object_set (priv->pwd1stEntry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL);
247 gtk_entry_set_visibility(GTK_ENTRY(priv->pwd1stEntry), FALSE);
248 gtk_widget_show(priv->pwd1stEntry);
249 priv->pwd1stCaption = hildon_caption_new(group,
250 priv->pwd1stCaption_string,
252 NULL, HILDON_CAPTION_OPTIONAL);
253 hildon_caption_set_separator(HILDON_CAPTION(priv->pwd1stCaption), "");
254 gtk_entry_set_visibility(GTK_ENTRY(priv->pwd1stEntry), FALSE);
255 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
256 priv->pwd1stCaption, TRUE, TRUE, 0);
257 gtk_widget_show(priv->pwd1stCaption);
259 /* Create the password verify field */
260 priv->pwd2ndEntry = gtk_entry_new();
261 g_object_set (priv->pwd2ndEntry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL);
262 gtk_widget_show(priv->pwd2ndEntry);
263 priv->pwd2ndCaption = hildon_caption_new(group,
264 priv->pwd2ndCaption_string,
266 NULL, HILDON_CAPTION_OPTIONAL);
267 hildon_caption_set_separator(HILDON_CAPTION(priv->pwd2ndCaption), "");
268 gtk_entry_set_visibility(GTK_ENTRY(priv->pwd2ndEntry), FALSE);
269 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
270 priv->pwd2ndCaption, TRUE, TRUE, 0);
271 gtk_widget_show(priv->pwd2ndCaption);
273 /* Set dialog title */
274 gtk_window_set_title(GTK_WINDOW(dialog),
276 ? HILDON_SET_MODIFY_PASSWORD_DIALOG_TITLE
277 : HILDON_SET_PASSWORD_DIALOG_TITLE));
279 /* Create the OK/CANCEL buttons */
280 priv->okButton = gtk_dialog_add_button
281 (GTK_DIALOG(dialog), _(priv->protection
282 ? HILDON_SET_MODIFY_PASSWORD_DIALOG_OK
283 : HILDON_SET_PASSWORD_DIALOG_OK),
285 priv->cancelButton = gtk_dialog_add_button
286 (GTK_DIALOG(dialog), _(priv->protection
287 ? HILDON_SET_MODIFY_PASSWORD_DIALOG_CANCEL
288 : HILDON_SET_PASSWORD_DIALOG_CANCEL),
289 GTK_RESPONSE_CANCEL);
291 gtk_widget_show(priv->okButton);
292 gtk_widget_show(priv->cancelButton);
294 /* Ensure group is freed when all its contents have been removed */
295 g_object_unref(group);
299 hildon_set_password_dialog_class_init(HildonSetPasswordDialogClass * class)
301 GObjectClass *object_class = G_OBJECT_CLASS(class);
303 parent_class = g_type_class_peek_parent(class);
305 /* Override virtual methods */
306 object_class->set_property = hildon_set_password_set_property;
307 object_class->get_property = hildon_set_password_get_property;
309 /* Install new properties */
310 g_object_class_install_property(object_class,
312 g_param_spec_string ("domain",
314 "Set Domain (content) for domain label.",
318 g_object_class_install_property(object_class,
319 PROP_HILDON_PASSWORD_DIALOG,
320 g_param_spec_boolean ("modify_protection",
322 "Set type to dialog",
324 G_PARAM_CONSTRUCT_ONLY |
327 g_object_class_install_property(object_class,
329 g_param_spec_string ("password",
331 "Set content to dialog",
335 /* Install private structure */
336 g_type_class_add_private(class,
337 sizeof(HildonSetPasswordDialogPrivate));
341 hildon_set_password_dialog_init(HildonSetPasswordDialog * dialog)
343 /* Most of the initializations are done in create_contents()
344 after the 'modify_protection' property has been set */
346 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
350 /* We come here when response button is clicked and dialog
351 is used to change existing password. */
353 hildon_set_password_response_change(GtkDialog * dialog, gint arg1,
356 GtkEntry *pwd1stEntry;
357 GtkEntry *pwd2ndEntry;
362 HildonSetPasswordDialogPrivate *priv;
364 priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog);
366 /* Password and verification */
367 pwd1stEntry = GTK_ENTRY(gtk_bin_get_child
368 (GTK_BIN(priv->pwd1stCaption)));
369 pwd2ndEntry = GTK_ENTRY(gtk_bin_get_child
370 (GTK_BIN(priv->pwd2ndCaption)));
371 text1 = GTK_ENTRY(pwd1stEntry)->text;
372 text2 = GTK_ENTRY(pwd2ndEntry)->text;
374 /* User accepted the dialog */
375 if (arg1 == GTK_RESPONSE_OK){
376 /* Is the checkbox marked, so password protection is still in use? */
377 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->checkbox))){
378 /* Yes, Something is given as password as well? */
379 if (text1[0] != '\0') {
380 if (strcmp (text1, text2) == 0) {
381 /* Passwords match, so accept change password */
382 priv->protection = TRUE;
383 } else if (text2[0] == '\0') {
384 /* Second field is empty, so show error, but don't clear fields */
385 g_signal_stop_emission_by_name(G_OBJECT(dialog),
388 c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH));
389 gtk_widget_grab_focus(GTK_WIDGET(pwd2ndEntry));
391 /* Error: Passwords don't match, so start over */
392 g_signal_stop_emission_by_name(G_OBJECT(dialog),
394 gtk_entry_set_text(pwd1stEntry, "");
395 gtk_entry_set_text(pwd2ndEntry, "");
397 c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH));
398 gtk_widget_grab_focus(GTK_WIDGET(pwd1stEntry));
401 /* No, the password is empty */
402 g_signal_stop_emission_by_name(G_OBJECT(dialog), "response");
403 if (text2[0] == '\0') {
404 /* Error: Both fields are empty */
405 gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_EMPTY));
407 /* Error: Second field doesn't match
408 the empty first field, so start over */
409 gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH));
410 gtk_entry_set_text(pwd2ndEntry, "");
412 gtk_widget_grab_focus(GTK_WIDGET(pwd1stEntry));
415 /* No, user wants to remove password protection.
416 Confirm remove password protection */
417 note = HILDON_NOTE(hildon_note_new_confirmation
419 c_(HILDON_SET_PASSWORD_DIALOG_REMOVE_PROTECTION
422 hildon_note_set_button_texts
424 c_(HILDON_REMOVE_PROTECTION_CONFIRMATION_REMOVE),
425 c_(HILDON_REMOVE_PROTECTION_CONFIRMATION_CANCEL));
427 /* Display confirmation note */
428 i = gtk_dialog_run(GTK_DIALOG(note));
430 gtk_widget_destroy(GTK_WIDGET(note));
432 if (i == GTK_RESPONSE_OK)
433 /* Remove password protection */
434 priv->protection = FALSE;
436 /* Remove password protection cancelled */
437 priv->protection = TRUE;
438 g_signal_stop_emission_by_name(G_OBJECT(dialog), "response");
443 /* Watch out for fading boolean values */
444 priv->protection = TRUE;
448 /* We come here when response button is clicked and dialog
449 is used to set new password. */
451 hildon_set_password_response_set(GtkDialog * dialog, gint arg1,
454 GtkEntry *pwd1stEntry;
455 GtkEntry *pwd2ndEntry;
459 HildonSetPasswordDialogPrivate *priv;
461 priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog);
463 /* Password and confirmation */
464 pwd1stEntry = GTK_ENTRY(gtk_bin_get_child
465 (GTK_BIN(priv->pwd1stCaption)));
466 pwd2ndEntry = GTK_ENTRY(gtk_bin_get_child
467 (GTK_BIN(priv->pwd2ndCaption)));
468 text1 = GTK_ENTRY(pwd1stEntry)->text;
469 text2 = GTK_ENTRY(pwd2ndEntry)->text;
471 if (arg1 == GTK_RESPONSE_OK) {
472 /* User provided something for password? */
473 if (text1[0] != '\0') {
474 if (strcmp (text1, text2) == 0) {
475 /* Passwords match, so accept set password */
476 priv->protection = TRUE;
477 } else if (text2[0] == '\0') {
478 /* Second field is empty, so show error,
479 but don't clear the fields */
480 g_signal_stop_emission_by_name(G_OBJECT(dialog), "response");
481 gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH));
482 gtk_widget_grab_focus (GTK_WIDGET (priv->pwd2ndEntry));
484 /* Error: Passwords don't match, so start over */
485 g_signal_stop_emission_by_name(G_OBJECT(dialog), "response");
486 gtk_entry_set_text(pwd1stEntry, "");
487 gtk_entry_set_text(pwd2ndEntry, "");
488 gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH));
489 gtk_widget_grab_focus(GTK_WIDGET(priv->pwd1stEntry));
492 /* First field is empty */
493 g_signal_stop_emission_by_name(G_OBJECT(dialog), "response");
494 if (text2[0] == '\0') {
495 /* Error: Both fields are empty */
496 gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_EMPTY));
498 /* Error: Second field doesn't match
499 the empty first field, so start over */
500 gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH));
501 gtk_entry_set_text(pwd2ndEntry, "");
503 gtk_widget_grab_focus(GTK_WIDGET(pwd1stEntry));
506 /* Watch out for fading boolean values */
507 priv->protection = FALSE;
511 static void hildon_checkbox_toggled(GtkWidget * widget, gpointer dialog)
513 HildonSetPasswordDialogPrivate *priv =
514 HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog);
517 /* If the user enabled/disabled the password protection feature
518 we enable/disable password entries accordingly */
519 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
520 gtk_widget_set_sensitive(GTK_WIDGET(priv->pwd1stEntry), active);
521 gtk_widget_set_sensitive(GTK_WIDGET(priv->pwd2ndEntry), active);
524 /* Public functions */
527 * hildon_set_password_dialog_get_type:
529 * Returns GType for HildonPasswordDialog as produced by
530 * g_type_register_static().
532 * Returns: HildonSetPasswordDialog type
534 GType hildon_set_password_dialog_get_type(void)
536 static GType dialog_type = 0;
539 static const GTypeInfo dialog_info = {
540 sizeof(HildonSetPasswordDialogClass),
541 NULL, /* base_init */
542 NULL, /* base_finalize */
543 (GClassInitFunc) hildon_set_password_dialog_class_init,
544 NULL, /* class_finalize */
545 NULL, /* class_data */
546 sizeof(HildonSetPasswordDialog),
548 (GInstanceInitFunc) hildon_set_password_dialog_init
551 dialog_type = g_type_register_static(GTK_TYPE_DIALOG,
552 "HildonSetPasswordDialog",
559 * hildon_set_password_dialog_new:
560 * @parent: parent window; can be NULL
561 * @modify_protection: TRUE creates a new change password dialog and FALSE
562 * creates a new set password dialog
564 * Constructs a new HildonSetPasswordDialog.
566 * Returns: a new #GtkWidget of type HildonSetPasswordDialog
569 GtkWidget *hildon_set_password_dialog_new(GtkWindow * parent,
570 gboolean modify_protection)
572 return hildon_set_password_dialog_new_with_default(parent, "",
577 * hildon_set_password_dialog_new_with_default:
578 * @parent: parent window; can be NULL
579 * @password: a default password to be shown in password field
580 * @modify_protection: TRUE creates a new change password dialog and FALSE
581 * creates a new set password dialog
583 * Same as #hildon_set_password_dialog_new, but with a default password
586 * Returns: a new #GtkWidget of type HildonSetPasswordDialog
589 GtkWidget *hildon_set_password_dialog_new_with_default
591 const gchar *password,
592 gboolean modify_protection)
594 GtkWidget *dialog = g_object_new(HILDON_TYPE_SET_PASSWORD_DIALOG,
595 "modify_protection", modify_protection,
596 "password", password, NULL);
598 if (parent != NULL) {
599 gtk_window_set_transient_for(GTK_WINDOW(dialog), parent);
606 * hildon_set_password_dialog_get_password:
607 * @dialog: pointer to HildonSetPasswordDialog
609 * Returns current password.
611 * Returns: changed password ( if the dialog is successfully
612 * accepted with 'OK' ( and when the check box is 'ON' ( in Change Password
616 *hildon_set_password_dialog_get_password(HildonSetPasswordDialog *
619 HildonSetPasswordDialogPrivate *priv;
621 g_return_val_if_fail(HILDON_IS_SET_PASSWORD_DIALOG(dialog), NULL);
623 priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog);
625 return GTK_ENTRY(priv->pwd1stEntry)->text;
629 * hildon_set_password_dialog_get_protected:
630 * @dialog: pointer to HildonSetPasswordDialog
632 * Returns the protection mode.
634 * Returns: password protection mode ( TRUE when the protection is
635 * 'ON' and FALSE when the protection is 'OFF' )
638 hildon_set_password_dialog_get_protected(HildonSetPasswordDialog * dialog)
640 HildonSetPasswordDialogPrivate *priv;
642 g_return_val_if_fail(HILDON_IS_SET_PASSWORD_DIALOG(dialog), FALSE);
644 priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog);
646 return priv->protection;
650 * hildon_set_password_dialog_set_domain(GtkWidget *dialog,
651 * @dialog: the dialog
652 * @domain: the domain or some other descriptive text to be set
654 * Sets the optional descriptive text.
657 void hildon_set_password_dialog_set_domain(HildonSetPasswordDialog *dialog,
660 HildonSetPasswordDialogPrivate *priv = NULL;
662 g_return_if_fail(HILDON_IS_SET_PASSWORD_DIALOG(dialog));
664 priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog);
665 gtk_label_set_text(priv->domainLabel, domain);