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