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