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