For the time being changing the tranlslation package from PACKAGE (hildon) to hildon...
[hildon] / src / hildon-get-password-dialog.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
5  *
6  * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
7  *
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
11  * the License.
12  *
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.
17  *
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
21  * 02110-1301 USA
22  *
23  */
24
25 /**
26  * SECTION:hildon-get-password-dialog
27  * @short_description: A widget used to get a password
28  * @see_also: #HildonSetPasswordDialog
29  * 
30  * HildonGetPasswordDialog prompts the user for a password.  It allows
31  * inputting password, with an optional configurable label eg. for
32  * showing a custom message. The maximum length of the password can be set.
33  */
34
35 #ifdef                                          HAVE_CONFIG_H
36 #include                                        <config.h>
37 #endif
38
39 #include                                        "hildon-get-password-dialog.h"
40 #include                                        <glib.h>
41 #include                                        <errno.h>
42 #include                                        <string.h>
43 #include                                        <strings.h>
44 #include                                        <unistd.h>
45 #include                                        <stdio.h>
46 #include                                        <gtk/gtk.h>
47 #include                                        "hildon-input-mode-hint.h"
48 #include                                        "hildon-caption.h"
49 #include                                        "hildon-banner.h"
50 #include                                        <libintl.h>
51 #include                                        "hildon-get-password-dialog-private.h"
52
53 #define                                         _(String) dgettext("hildon-libs", String)
54
55 #define                                         HILDON_GET_PASSWORD_DIALOG_TITLE "ecdg_ti_get_old_password"
56
57 #define                                         HILDON_GET_PASSWORD_DIALOG_PASSWORD "ecdg_fi_get_old_pwd_enter_pwd"
58
59 #define                                         HILDON_GET_PASSWORD_DIALOG_OK "ecdg_bd_get_old_password_dialog_ok"
60
61 #define                                         HILDON_GET_PASSWORD_DIALOG_CANCEL "ecdg_bd_get_old_password_dialog_cancel"
62
63 #define                                         HILDON_GET_PASSWORD_VERIFY_DIALOG_TITLE "ecdg_ti_verify_password"
64
65 #define                                         HILDON_GET_PASSWORD_VERIFY_DIALOG_PASSWORD "ecdg_fi_verify_pwd_enter_pwd"
66
67 #define                                         HILDON_GET_PASSWORD_VERIFY_DIALOG_OK "ecdg_bd_verify_password_dialog_ok"
68
69 #define                                         HILDON_GET_PASSWORD_VERIFY_DIALOG_CANCEL "ecdg_bd_verify_password_dialog_cancel"
70
71 #define                                         HILDON_GET_PASSWORD_DIALOG_MAX_CHARS "ckdg_ib_maximum_characters_reached"
72
73 static GtkDialogClass*                          parent_class;
74
75 static void
76 hildon_get_password_dialog_class_init           (HildonGetPasswordDialogClass *class);
77
78 static void
79 hildon_get_password_dialog_init                 (HildonGetPasswordDialog *widget);
80
81 static void
82 hildon_get_password_set_property                (GObject *object,
83                                                  guint prop_id,
84                                                  const GValue *value,
85                                                  GParamSpec *pspec);
86
87 static void
88 hildon_get_password_get_property                (GObject *object,
89                                                  guint prop_id, 
90                                                  GValue *value,
91                                                  GParamSpec *pspec);
92
93 static void 
94 create_contents                                 (HildonGetPasswordDialog *dialog);
95
96 static void 
97 invalid_input                                   (GtkWidget *widget, 
98                                                  GtkInvalidInputType reason, 
99                                                  gpointer unused);
100
101 enum
102 {
103     PROP_0,
104     PROP_MESSAGE,
105     PROP_PASSWORD,
106     PROP_NUMBERS_ONLY,
107     PROP_CAPTION_LABEL,
108     PROP_MAX_CHARS,
109     PROP_GET_OLD
110 };
111
112 /* Private functions */
113 static void
114 hildon_get_password_set_property                (GObject *object,
115                                                  guint prop_id,
116                                                  const GValue *value, 
117                                                  GParamSpec *pspec)
118 {
119     HildonGetPasswordDialog *dialog = HILDON_GET_PASSWORD_DIALOG (object);
120     HildonGetPasswordDialogPrivate *priv;
121
122     priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (object);
123     g_assert (priv);
124
125     switch (prop_id) {
126
127         case PROP_MESSAGE:
128             /* Set label text representing password domain */
129             gtk_label_set_text (priv->message_label, g_value_get_string (value));
130             break;
131
132         case PROP_PASSWORD:
133             gtk_entry_set_text(GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->password_entry))), 
134                     g_value_get_string(value));
135             break;
136
137         case PROP_NUMBERS_ONLY:
138             /* Set input mode for the password entry */
139             g_object_set(G_OBJECT (gtk_bin_get_child GTK_BIN ((priv->password_entry))),
140                     "input-mode",
141                     (g_value_get_boolean (value)
142                      ? HILDON_INPUT_MODE_HINT_NUMERIC
143                      : HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL),
144                     NULL);
145             break;
146
147         case PROP_CAPTION_LABEL:
148             hildon_get_password_dialog_set_caption (dialog, g_value_get_string (value));
149             break;
150
151         case PROP_MAX_CHARS:
152             hildon_get_password_dialog_set_max_characters (dialog, g_value_get_int (value));
153             break;
154
155         case PROP_GET_OLD:
156             priv->get_old = g_value_get_boolean (value);
157             create_contents (dialog);
158             break;
159
160         default:
161             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
162             break;
163     }
164 }
165
166 static void
167 hildon_get_password_get_property                (GObject *object,
168                                                  guint prop_id,
169                                                  GValue *value, 
170                                                  GParamSpec *pspec)
171 {
172     HildonGetPasswordDialog *dialog = HILDON_GET_PASSWORD_DIALOG (object);
173     HildonGetPasswordDialogPrivate *priv;
174     const gchar *string;
175     gint max_length;
176     gint input_mode;
177
178     priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (dialog);
179     g_assert (priv);
180
181     switch (prop_id) {
182
183         case PROP_MESSAGE:
184             string = gtk_label_get_text (priv->message_label);
185             g_value_set_string (value, string);
186             break;
187
188         case PROP_PASSWORD:
189             string = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->password_entry))));
190             g_value_set_string (value, string);
191             break;
192
193         case PROP_NUMBERS_ONLY:
194             /* This property is set if and only if the input mode
195                of the password entry has been set to numeric only */
196             g_object_get (G_OBJECT (gtk_bin_get_child (GTK_BIN (priv->password_entry))),
197                     "input-mode", &input_mode, NULL);
198             g_value_set_boolean (value,
199                     (input_mode == HILDON_INPUT_MODE_HINT_NUMERIC));
200             break;
201
202         case PROP_CAPTION_LABEL:
203             string = hildon_caption_get_label (priv->password_entry);
204             g_value_set_string (value, string);
205             break;
206
207         case PROP_MAX_CHARS:
208             max_length = gtk_entry_get_max_length 
209                     (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->password_entry))));
210             g_value_set_int (value, max_length);
211             break;
212
213         case PROP_GET_OLD:
214             g_value_set_boolean (value, priv->get_old);
215             break;
216
217         default:
218             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
219             break;
220     }
221 }
222
223 static void
224 hildon_get_password_dialog_class_init           (HildonGetPasswordDialogClass *class)
225 {
226     GObjectClass *object_class = G_OBJECT_CLASS (class);
227
228     parent_class = g_type_class_peek_parent (class);
229
230     /* Override virtual functions */
231     object_class->set_property = hildon_get_password_set_property;
232     object_class->get_property = hildon_get_password_get_property;
233
234     /* Install new properties */
235     g_object_class_install_property 
236         (object_class, 
237          PROP_MESSAGE, 
238          g_param_spec_string ("message",
239              "Message",
240              "Set optional message",
241              NULL,
242              G_PARAM_READWRITE));
243
244     g_object_class_install_property
245         (object_class, 
246          PROP_PASSWORD,
247          g_param_spec_string ("password",
248              "Password",
249              "Password field",
250              "DEFAULT",
251              G_PARAM_READWRITE));
252
253     g_object_class_install_property
254         (object_class, 
255          PROP_NUMBERS_ONLY,
256          g_param_spec_boolean ("numbers_only",
257              "NumbersOnly",
258              "Set entry to accept only numeric values",
259              FALSE,
260              G_PARAM_READWRITE));
261
262     g_object_class_install_property
263         (object_class, 
264          PROP_CAPTION_LABEL,
265          g_param_spec_string ("caption-label",
266              "Caption Label",
267              "The text to be set as the caption label",
268              NULL,
269              G_PARAM_READWRITE));
270
271     g_object_class_install_property
272         (object_class, 
273          PROP_MAX_CHARS,
274          g_param_spec_int ("max-characters",
275              "Maximum Characters",
276              "The maximum number of characters the password"
277              " dialog accepts",
278              G_MININT,
279              G_MAXINT,
280              0,
281              G_PARAM_READWRITE));
282
283     g_object_class_install_property
284         (object_class,
285          PROP_GET_OLD,
286          g_param_spec_boolean ("get-old",
287              "Get Old Password",
288              "TRUE if dialog is a get old password dialog, "
289              "FALSE if dialog is a get password dialog",
290              FALSE,
291              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
292
293     /* Install private structure */
294     g_type_class_add_private (class, sizeof (HildonGetPasswordDialogPrivate));
295 }
296
297 static void
298 hildon_get_password_dialog_init                 (HildonGetPasswordDialog *dialog)
299 {
300     /* Set initial properties for the dialog; the actual contents are
301        created once the 'get-old' property is set with g_object_new */
302
303     gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
304     gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
305     gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
306 }
307
308 static void
309 create_contents                                 (HildonGetPasswordDialog *dialog)
310 {
311     HildonGetPasswordDialogPrivate *priv;
312     GtkSizeGroup * group;
313     GtkWidget *control;
314
315     /* Cache private pointer for faster member access */
316     priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (dialog);
317     g_assert (priv);
318
319     /* Sizegroup for captions */
320     group = GTK_SIZE_GROUP (gtk_size_group_new
321             (GTK_SIZE_GROUP_HORIZONTAL));
322
323     /* Dialog title */
324     gtk_window_set_title (GTK_WINDOW (dialog),
325             priv->get_old
326             ? _(HILDON_GET_PASSWORD_DIALOG_TITLE)
327             : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_TITLE));
328
329     /* Optional password domain label */
330     priv->message_label = GTK_LABEL (gtk_label_new (NULL));
331
332     /* Create buttons */
333     gtk_dialog_add_button (GTK_DIALOG (dialog),
334                     (priv->get_old
335                      ? _(HILDON_GET_PASSWORD_DIALOG_OK)
336                      : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_OK)),
337                     GTK_RESPONSE_OK);
338
339     gtk_dialog_add_button (GTK_DIALOG (dialog),
340                     (priv->get_old
341                      ? _(HILDON_GET_PASSWORD_DIALOG_CANCEL)
342                      : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_CANCEL)),
343                     GTK_RESPONSE_CANCEL);
344
345     /* Create password text entry */
346     control = gtk_entry_new ();
347     gtk_entry_set_width_chars (GTK_ENTRY (control), 20);
348
349     g_object_set (control, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL);
350
351     gtk_entry_set_visibility (GTK_ENTRY(control), FALSE);
352     priv->password_entry = HILDON_CAPTION
353         (hildon_caption_new(group,
354                             (priv->get_old
355                              ? _(HILDON_GET_PASSWORD_DIALOG_PASSWORD)
356                              : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_PASSWORD)),
357                             control, NULL,
358                             HILDON_CAPTION_OPTIONAL));
359     hildon_caption_set_separator (HILDON_CAPTION (priv->password_entry), "");
360
361     /* Do the basic layout */
362     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
363             GTK_WIDGET (priv->message_label), FALSE, FALSE, 0);
364     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
365             GTK_WIDGET (priv->password_entry), FALSE, FALSE, 0);
366     gtk_widget_show_all (GTK_DIALOG (dialog)->vbox);
367
368     /* Ensure group is freed when all its contents have been removed */
369     g_object_unref (group);
370 }
371
372 /**
373  * hildon_get_password_dialog_get_type:
374  *
375  * Returns GType for HildonGetPasswordDialog as produced by
376  * g_type_register_static().
377  *
378  * Returns: HildonGetPasswordDialog type
379  */
380 GType G_GNUC_CONST
381 hildon_get_password_dialog_get_type             (void)
382 {
383     static GType dialog_type = 0;
384
385     if (! dialog_type) {
386         static const GTypeInfo dialog_info = {
387             sizeof (HildonGetPasswordDialogClass),
388             NULL,       /* base_init */
389             NULL,       /* base_finalize */
390             (GClassInitFunc) hildon_get_password_dialog_class_init,
391             NULL,       /* class_finalize */
392             NULL,       /* class_data */
393             sizeof (HildonGetPasswordDialog),
394             0,  /* n_preallocs */
395             (GInstanceInitFunc) hildon_get_password_dialog_init
396         };
397
398         dialog_type = g_type_register_static (GTK_TYPE_DIALOG,
399                 "HildonGetPasswordDialog",
400                 &dialog_info, 0);
401     }
402     return dialog_type;
403 }
404
405 /**
406  * hildon_get_password_dialog_new:
407  * @parent: parent window; can be NULL
408  * @get_old: FALSE creates a new get password dialog and
409  *           TRUE creates a new get old password dialog. That is,
410  *           if the password to be obtained is the old password, 
411  *           this parameter is specified TRUE.  
412  * 
413  * Construct a new HildonGetPasswordDialog.
414  *
415  * Returns: a new #GtkWidget of type HildonGetPasswordDialog
416  */
417 GtkWidget*
418 hildon_get_password_dialog_new                  (GtkWindow *parent,
419                                                  gboolean get_old)
420 {
421     HildonGetPasswordDialog *dialog = g_object_new
422         (HILDON_TYPE_GET_PASSWORD_DIALOG,
423          "get-old", get_old, NULL);
424
425     if (parent != NULL) {
426         gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
427     }
428
429     return (GtkWidget *) dialog;
430 }
431
432 /**
433  * hildon_get_password_dialog_new_with_default:
434  * @parent: parent window; can be NULL
435  * @password: a default password to be shown in password field
436  * @get_old: FALSE creates a new get password dialog and
437  *           TRUE creates a new get old password dialog.That is,
438  *           if the password to be obtained is the old password,
439  *           this parameter is specified TRUE.
440  *                        
441  * 
442  * Same as #hildon_get_password_dialog_new but with a default password
443  * in password field.
444  *
445  * Returns: a new #GtkWidget of type HildonGetPasswordDialog
446  */
447 GtkWidget*
448 hildon_get_password_dialog_new_with_default     (GtkWindow *parent,
449                                                  const gchar *password,
450                                                  gboolean get_old)
451 {
452     GtkWidget *dialog;
453
454     dialog = hildon_get_password_dialog_new (parent, get_old);
455
456     if (password != NULL)
457         g_object_set (G_OBJECT (dialog), "password", password, NULL);
458
459     return GTK_WIDGET (dialog);
460 }
461
462 /**
463  * hildon_get_password_dialog_get_password:
464  * @dialog: pointer to HildonSetPasswordDialog
465  * 
466  * Gets the currently entered password.
467  *
468  * Returns: current password entered by the user.
469  */
470 const gchar*
471 hildon_get_password_dialog_get_password         (HildonGetPasswordDialog *dialog)
472 {
473     GtkEntry *entry1;
474     gchar *text1;
475
476     HildonGetPasswordDialogPrivate *priv;
477
478     g_return_val_if_fail (HILDON_IS_GET_PASSWORD_DIALOG (dialog), NULL);
479     priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (dialog);
480     g_assert (priv);
481
482     /* Retrieve the password entry widget */
483     entry1 = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->password_entry)));
484     text1 = GTK_ENTRY (entry1)->text;
485
486     return text1;
487 }
488
489 /**
490  * hildon_get_password_dialog_set_message
491  * @dialog: the dialog
492  * @message: a custom message or some other descriptive text to be set
493  * 
494  * Sets the optional descriptive text.
495  */
496 void 
497 hildon_get_password_dialog_set_message          (HildonGetPasswordDialog *dialog, 
498                                                  const gchar *message)
499 {
500     HildonGetPasswordDialogPrivate *priv;
501
502     g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG (dialog));
503
504     priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (dialog);
505     g_assert (priv);
506
507     gtk_label_set_text (priv->message_label, message);
508
509 }
510
511 /**
512  * hildon_get_password_dialog_set_caption:
513  * @dialog: the dialog
514  * @new_caption: the text to be set as the caption label
515  * 
516  * Sets the password entry field's neigbouring label.
517  */
518 void 
519 hildon_get_password_dialog_set_caption          (HildonGetPasswordDialog *dialog,
520                                                  const gchar *new_caption)
521 {
522     HildonGetPasswordDialogPrivate *priv;
523
524     g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG (dialog));
525     g_return_if_fail (new_caption != NULL);
526
527     priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (dialog);
528     g_assert (priv);
529
530     hildon_caption_set_label (priv->password_entry, new_caption);
531 }
532
533 /**
534  * hildon_get_password_dialog_set_max_characters:
535  * @dialog: the dialog
536  * @max_characters: the maximum number of characters the password dialog
537  * accepts
538  * @new_caption: the text to be set as the caption label
539  * 
540  * sets the maximum number of characters allowed as the password
541  */
542 void 
543 hildon_get_password_dialog_set_max_characters   (HildonGetPasswordDialog *dialog, 
544                                                  gint max_characters)
545 {
546     HildonGetPasswordDialogPrivate *priv;
547
548     g_return_if_fail (max_characters > 0);
549     g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG (dialog));
550
551     priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (dialog);
552     g_assert (priv);
553
554     /* Apply the given length to password entry */
555     gtk_entry_set_max_length (GTK_ENTRY
556             (gtk_bin_get_child
557              GTK_BIN ((priv->password_entry))),
558              max_characters);
559
560     /* FIXME There is a bug here -- the prev. signal needs to be
561      * disconnected before connecting the new signal. Besides, this 
562      * should go into the constructor */
563
564     /* Connect callback to show error banner if the limit is exceeded */
565     g_signal_connect (GTK_ENTRY
566             (gtk_bin_get_child
567              GTK_BIN ((priv->password_entry))),
568             "invalid_input",
569             G_CALLBACK (invalid_input),
570             NULL
571             );
572 }
573
574 /* Callback that gets called when maximum chars is reached in the entry */
575 static void 
576 invalid_input                                   (GtkWidget *widget, 
577                                                  GtkInvalidInputType reason, 
578                                                  gpointer unused) 
579 {
580     if (reason == GTK_INVALID_INPUT_MAX_CHARS_REACHED) 
581     {
582         hildon_banner_show_information (widget, NULL, _(HILDON_GET_PASSWORD_DIALOG_MAX_CHARS));
583     }
584 }