Removing the bug-fixed entries that were actually resolved as WONTFIX. Removing a...
[hildon] / src / hildon-sort-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, 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-sort-dialog
27  * @short_description: A widget for defining the sorting order of items.
28  * 
29  * HildonSortDialog is used to define an order (ascending/descending)
30  * and a field by which items are sorted in a list. The combo boxes
31  * display the current value when the dialog is opened.
32  *
33  * <example>
34  * <title>An example for using HildonSortDialog</title>
35  * <programlisting>
36  * HildonSortDialog *sort_dialog = HILDON_SORT_DIALOG (hildon_sort_dialog_new (parent));
37  * <!-- -->
38  * gint response_id, add_sort_index;
39  * <!-- -->
40  * sort_by[0] = STR_SORT_BY_DATE;
41  * sort_by[1] = STR_SORT_BY_NAME;
42  * sort_by[2] = STR_SORT_BY_SIZE;
43  * sort_by[3] = NULL;
44  * <!-- -->
45  * sorting_order[0] = STR_SORTING_ORDER_ASCENDING;
46  * sorting_order[1] = STR_SORTING_ORDER_DESCENDING;
47  * sorting_order[2] = NULL;
48  * <!-- -->
49  * add_sort_index = hildon_sort_dialog_add_sort_key (sort_dialog, STR_SORT_BY_DATE);
50  * <!-- -->
51  * hildon_sort_dialog_add_sort_key (sort_dialog, STR_SORT_BY_NAME);
52  * <!-- -->
53  * hildon_sort_dialog_add_sort_key (sort_dialog, STR_SORT_BY_SIZE);
54  * <!-- -->
55  * if (dialog.first_time_clicked == TRUE)
56  * {
57  *      hildon_sort_dialog_set_sort_key (sort_dialog, add_sort_index);
58  * }
59  * <!-- -->
60  * if (dialog.first_time_clicked == FALSE)
61  * {
62  *      hildon_sort_dialog_set_sort_key (sort_dialog, dialog.sort_key);
63  *      hildon_sort_dialog_set_sort_order (sort_dialog, dialog.sort_order);
64  * }
65  * <!-- -->
66  * gtk_widget_show (GTK_WIDGET (sort_dialog));
67  * <!-- -->
68  * response_id = gtk_dialog_run (GTK_DIALOG (sort_dialog));
69  * <!-- -->
70  * if (response_id == GTK_RESPONSE_OK)
71  * {
72  *      dialog.sort_key = hildon_sort_dialog_get_sort_key (sort_dialog);
73  * <!-- -->
74  *      gtk_label_set_text (GTK_LABEL (dialog.label1), sort_by [dialog.sort_key]);
75  * <!-- -->
76  *      dialog.sort_order = hildon_sort_dialog_get_sort_order (sort_dialog);
77  * <!-- -->
78  *      gtk_label_set_text (GTK_LABEL (dialog.label2), sorting_order [dialog.sort_order]);
79  * <!-- -->
80  *      dialog.first_time_clicked = FALSE;
81  * }
82  * </programlisting>
83  * </example>
84  */
85
86 #ifdef                                          HAVE_CONFIG_H
87 #include                                        <config.h>
88 #endif
89
90 #include                                        "hildon-sort-dialog.h"
91 #include                                        <stdio.h>
92 #include                                        <libintl.h>
93 #include                                        <gtk/gtkcombobox.h>
94 #include                                        <gtk/gtkbox.h>
95 #include                                        "hildon-caption.h"
96 #include                                        "hildon-sort-dialog-private.h"
97
98 #define                                         _(String) \
99                                                 dgettext("hildon-libs", String)
100
101 static GtkDialogClass*                          parent_class;
102
103 static void 
104 hildon_sort_dialog_class_init                   (HildonSortDialogClass *class);
105
106 static void
107 hildon_sort_dialog_init                         (HildonSortDialog *widget);
108
109 static void 
110 hildon_sort_dialog_set_property                 (GObject * object,
111                                                  guint prop_id,
112                                                  const GValue *value,
113                                                  GParamSpec * pspec);
114
115 static void 
116 hildon_sort_dialog_get_property                 (GObject *object,
117                                                  guint prop_id,
118                                                  GValue * value, 
119                                                  GParamSpec * pspec);
120
121 static void 
122 reconstruct_combo                               (HildonSortDialog *dialog, 
123                                                  gboolean remove, 
124                                                  gboolean reversed);
125
126 static void
127 sort_key_changed                                (GtkWidget *widget, 
128                                                  HildonSortDialog *dialog);
129
130 static void 
131 hildon_sort_dialog_finalize                     (GObject *object);
132
133 static gint 
134 hildon_sort_dialog_add_sort_key_with_sorting    (HildonSortDialog *dialog, 
135                                                  const gchar *sort_key, 
136                                                  gboolean sorting);
137
138 enum 
139 {
140     PROP_0,
141     PROP_SORT_KEY,
142     PROP_SORT_ORDER
143 };
144
145 static void 
146 sort_key_changed                                (GtkWidget *widget, 
147                                                  HildonSortDialog *dialog)
148 {
149     g_return_if_fail (HILDON_IS_SORT_DIALOG (dialog));
150
151     HildonSortDialogPrivate *priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog);
152     g_assert (priv);
153
154     gint index = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
155
156     if (priv->key_reversed [index] != priv->reversed) {
157         reconstruct_combo (dialog, TRUE, priv->key_reversed [index]);
158         gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combo_order), 0);
159     }
160
161     priv->reversed = priv->key_reversed [index];
162 }
163
164 /* Initialises the sort dialog class. */
165 static void
166 hildon_sort_dialog_class_init                   (HildonSortDialogClass *class)
167 {
168     GObjectClass *gobject_class = G_OBJECT_CLASS (class);
169     parent_class = g_type_class_peek_parent (class);
170     g_type_class_add_private (class, sizeof (HildonSortDialogPrivate));
171     
172     gobject_class->set_property = hildon_sort_dialog_set_property;
173     gobject_class->get_property = hildon_sort_dialog_get_property;
174     gobject_class->finalize     = (gpointer) hildon_sort_dialog_finalize;
175
176     /**
177      * HildonSortDialog:sort-key:
178      *
179      * The currently active sort key.
180      */
181     g_object_class_install_property (gobject_class, PROP_SORT_KEY,
182         g_param_spec_int ("sort-key",
183                           "Sort Key",
184                           "The currently active sort key",
185                           G_MININT,
186                           G_MAXINT,
187                           0, G_PARAM_READWRITE));
188    
189     /**
190      * HildonSortDialog:sort-order:
191      *
192      * The sort order for the currently active sort key.
193      */
194     g_object_class_install_property (gobject_class, PROP_SORT_ORDER,
195         g_param_spec_enum ("sort-order",
196                           "Sort Order",
197                           "The current sorting order",
198                           GTK_TYPE_SORT_TYPE,
199                           GTK_SORT_ASCENDING,
200                           G_PARAM_READWRITE));
201 }
202
203 static gint 
204 hildon_sort_dialog_add_sort_key_with_sorting    (HildonSortDialog *dialog, 
205                                                  const gchar *sort_key, 
206                                                  gboolean sorting)
207 {
208     HildonSortDialogPrivate *priv;
209
210     g_return_val_if_fail (HILDON_IS_SORT_DIALOG (dialog), -1);
211
212     priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog);
213     g_assert (priv);
214
215     gboolean *new_array = g_malloc (sizeof (gboolean) * (priv->index_counter + 1));
216
217     /* Rewrite the old values */
218     int i = 0;
219     for (i = 0; i < priv->index_counter; i++) 
220         new_array [i] = priv->key_reversed [i];
221
222     new_array [priv->index_counter] = sorting;
223     gtk_combo_box_append_text (GTK_COMBO_BOX (priv->combo_key), sort_key);
224
225     /* Free the old one and reassign */
226     if (priv->key_reversed != NULL)
227         g_free (priv->key_reversed);
228     priv->key_reversed = new_array;
229
230     return priv->index_counter++;
231 }
232
233 static void 
234 reconstruct_combo                               (HildonSortDialog *dialog, 
235                                                  gboolean remove, 
236                                                  gboolean reversed)
237 {
238     HildonSortDialogPrivate *priv;
239     priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog);
240     g_assert (priv);
241
242     if (remove) {
243         gtk_combo_box_remove_text (GTK_COMBO_BOX (priv->combo_order), 1);
244         gtk_combo_box_remove_text (GTK_COMBO_BOX (priv->combo_order), 0);
245     }
246
247     if (reversed) {
248         gtk_combo_box_append_text (GTK_COMBO_BOX (priv->combo_order), _("ckdg_va_sort_descending"));
249         gtk_combo_box_append_text (GTK_COMBO_BOX (priv->combo_order), _("ckdg_va_sort_ascending"));
250     } else  {
251         gtk_combo_box_append_text (GTK_COMBO_BOX (priv->combo_order), _("ckdg_va_sort_ascending"));
252         gtk_combo_box_append_text (GTK_COMBO_BOX (priv->combo_order), _("ckdg_va_sort_descending"));
253     }
254 }
255
256 static void
257 hildon_sort_dialog_init                         (HildonSortDialog * dialog)
258 {
259     HildonSortDialogPrivate *priv;
260     GtkSizeGroup *group;
261
262     g_assert(HILDON_IS_SORT_DIALOG (dialog));
263
264     priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog);
265     g_assert (priv);
266
267     priv->index_counter = 0;
268     priv->reversed = FALSE;
269     priv->key_reversed = NULL;
270
271     group = GTK_SIZE_GROUP (gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL));
272
273     gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
274     gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
275     gtk_window_set_title (GTK_WINDOW (dialog), _("ckdg_ti_sort"));
276
277     /* Tab one */
278     priv->combo_key = gtk_combo_box_new_text ();
279     priv->caption_key = hildon_caption_new(group, _("ckdg_fi_sort_field"), priv->combo_key,
280             NULL, HILDON_CAPTION_OPTIONAL);
281     hildon_caption_set_separator(HILDON_CAPTION (priv->caption_key), "");
282     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
283             priv->caption_key, FALSE, FALSE, 0);
284
285     /* Tab two */
286     priv->combo_order = gtk_combo_box_new_text ();
287     reconstruct_combo (dialog, FALSE, FALSE);
288
289     priv->caption_order = hildon_caption_new (group, _("ckdg_fi_sort_order"),
290             priv->combo_order,
291             NULL, HILDON_CAPTION_OPTIONAL);
292     hildon_caption_set_separator(HILDON_CAPTION(priv->caption_order), "");
293     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
294             priv->caption_order, FALSE, FALSE, 0);
295
296     gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combo_key), 0);
297     gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combo_order), 0);
298     g_signal_connect (G_OBJECT (priv->combo_key), "changed", (gpointer) sort_key_changed, dialog);
299
300     /* Create the OK/CANCEL buttons */
301     (void) gtk_dialog_add_button (GTK_DIALOG(dialog),
302             _("ckdg_bd_sort_dialog_ok"),
303             GTK_RESPONSE_OK);
304     (void) gtk_dialog_add_button (GTK_DIALOG(dialog),
305             _("ckdg_bd_sort_dialog_cancel"),
306             GTK_RESPONSE_CANCEL);
307     /* FIXME: Hardcoded sizes are bad */
308     gtk_window_resize (GTK_WINDOW (dialog), 370, 100);
309     gtk_widget_show_all (GTK_DIALOG (dialog)->vbox);
310
311     g_object_unref (group); /* Captions now own their references to sizegroup */
312 }
313
314 /**
315  * hildon_sort_dialog_get_type:
316  *
317  * Returns GType for HildonSortDialog as produced by 
318  * g_type_register_static().
319  *
320  * Returns: HildonSortDialog type
321  */
322 GType G_GNUC_CONST
323 hildon_sort_dialog_get_type                     (void)
324 {
325     static GType dialog_type = 0;
326
327     if (!dialog_type) {
328         static const GTypeInfo dialog_info = {
329             sizeof (HildonSortDialogClass),
330             NULL,       /* base_init */
331             NULL,       /* base_finalize */
332             (GClassInitFunc) hildon_sort_dialog_class_init,
333             NULL,       /* class_finalize */
334             NULL,       /* class_data */
335             sizeof (HildonSortDialog),
336             0,  /* n_preallocs */
337             (GInstanceInitFunc) hildon_sort_dialog_init
338         };
339
340         dialog_type = g_type_register_static (GTK_TYPE_DIALOG,
341                 "HildonSortDialog",
342                 &dialog_info, 0);
343     }
344     return dialog_type;
345 }
346
347 /**
348  * hildon_sort_dialog_new:
349  * @parent: widget to be transient for, or NULL if none
350  *
351  * HildonSortDialog contains two HildonCaptions with combo boxes. 
352  *
353  * Returns: pointer to a new @HildonSortDialog widget
354  */
355 GtkWidget*
356 hildon_sort_dialog_new                          (GtkWindow * parent)
357 {
358     GtkWidget *sort_dialog = g_object_new (HILDON_TYPE_SORT_DIALOG, NULL);
359
360     if (parent)
361         gtk_window_set_transient_for (GTK_WINDOW (sort_dialog), parent);
362
363     return sort_dialog;
364 }
365
366 /**
367  * hildon_sort_dialog_get_sort_key:
368  * @dialog: the #HildonSortDialog widget
369  *
370  * Gets index to currently active sort key.
371  * 
372  * Returns: an integer which is the index value of the "Sort by" 
373  * field 
374  */
375 gint
376 hildon_sort_dialog_get_sort_key                 (HildonSortDialog *dialog)
377 {
378     GtkWidget *combo_key;
379     HildonSortDialogPrivate *priv;
380
381     g_return_val_if_fail (HILDON_IS_SORT_DIALOG (dialog), -1);
382
383     priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog);
384     g_assert (priv);
385
386     combo_key = gtk_bin_get_child (GTK_BIN (priv->caption_key));
387
388     return gtk_combo_box_get_active (GTK_COMBO_BOX (combo_key));
389 }
390
391 /**
392  * hildon_sort_dialog_get_sort_order:
393  * @dialog: the #HildonSortDialog widget
394  *
395  * Gets current sorting order from "Sort order" field.
396  *
397  * Returns: current sorting order as #GtkSortType
398  */
399 GtkSortType 
400 hildon_sort_dialog_get_sort_order               (HildonSortDialog *dialog)
401 {
402     GtkWidget *combo_order;
403     HildonSortDialogPrivate *priv;
404
405     g_return_val_if_fail (HILDON_IS_SORT_DIALOG (dialog), 0);
406
407     priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog);
408     g_assert (priv);
409
410     combo_order = gtk_bin_get_child (GTK_BIN (priv->caption_order));
411
412     gint sort_order = gtk_combo_box_get_active (GTK_COMBO_BOX (combo_order));
413
414     if (priv->reversed)
415         return (sort_order == 0) ? 1 : 0;
416     else
417         return sort_order;
418 }
419
420 /**
421  * hildon_sort_dialog_set_sort_key:
422  * @dialog: the #HildonSortDialog widget
423  * @key: combo box's index value
424  *
425  * Sets the index value of the #HildonSortDialog widget.
426  */
427 void
428 hildon_sort_dialog_set_sort_key                 (HildonSortDialog * dialog, 
429                                                  gint key)
430 {
431     GtkWidget *combo_key;
432     HildonSortDialogPrivate *priv;
433
434     g_return_if_fail (HILDON_IS_SORT_DIALOG (dialog));
435
436     priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog);
437     g_assert (priv);
438
439     combo_key = gtk_bin_get_child (GTK_BIN (priv->caption_key));
440     gtk_combo_box_set_active (GTK_COMBO_BOX (combo_key), key);
441
442     g_object_notify (G_OBJECT (dialog), "sort-key");
443 }
444
445 /**
446  * hildon_sort_dialog_set_sort_order:
447  * @dialog: the #HildonSortDialog widget
448  * @order: combo box's index value
449  *
450  * Sets the index value of the #HildonSortDialog widget.
451  */
452 void
453 hildon_sort_dialog_set_sort_order               (HildonSortDialog *dialog,
454                                                  GtkSortType order)
455 {
456     GtkWidget *combo_order;
457     HildonSortDialogPrivate *priv;
458
459     g_return_if_fail (HILDON_IS_SORT_DIALOG (dialog));
460
461     priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog);
462     g_assert (priv);
463
464     combo_order = gtk_bin_get_child (GTK_BIN (priv->caption_order));
465
466     if (priv->reversed) 
467         order = (order == 0) ? 1 : 0;
468
469     gtk_combo_box_set_active (GTK_COMBO_BOX (combo_order), order);
470
471     g_object_notify (G_OBJECT (dialog), "sort-order");
472 }
473
474 /**
475  * hildon_sort_dialog_add_sort_key:
476  * @dialog: the #HildonSortDialog widget
477  * @sort_key: combo box's index value
478  *
479  * Adds a new sort key and returns the respective index in
480  * sort key combobox.
481  *
482  * Returns: an integer which is the index of the added combo box's
483  * item
484  */
485 gint
486 hildon_sort_dialog_add_sort_key                 (HildonSortDialog *dialog,
487                                                  const gchar *sort_key)
488 {
489     return hildon_sort_dialog_add_sort_key_with_sorting (dialog, sort_key, FALSE);
490 }
491
492 /**
493  * hildon_sort_dialog_add_sort_key_reversed:
494  * @dialog: the #HildonSortDialog widget
495  * @sort_key: combo box's index value
496  *
497  * Adds a new sort key and returns the respective index in
498  * sort key combobox. The default sort order for this key is reversed (Descending first).
499  *
500  * Returns: an integer which is the index of the added combo box's
501  * item
502  *
503  */
504 gint
505 hildon_sort_dialog_add_sort_key_reversed        (HildonSortDialog *dialog,
506                                                  const gchar *sort_key)
507 {
508     return hildon_sort_dialog_add_sort_key_with_sorting (dialog, sort_key, TRUE);
509 }
510
511 static void
512 hildon_sort_dialog_set_property                 (GObject *object,
513                                                  guint prop_id,
514                                                  const GValue *value, 
515                                                  GParamSpec *pspec)
516 {
517     HildonSortDialog *dialog;
518
519     dialog = HILDON_SORT_DIALOG(object);
520
521     switch (prop_id) {
522
523         case PROP_SORT_KEY:
524             hildon_sort_dialog_set_sort_key (dialog, g_value_get_int (value));
525             break;
526
527         case PROP_SORT_ORDER:
528             hildon_sort_dialog_set_sort_order (dialog, g_value_get_enum (value));
529             break;
530
531         default:
532             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
533             break;
534     }
535 }
536
537 static void
538 hildon_sort_dialog_get_property                 (GObject *object,
539                                                  guint prop_id, 
540                                                  GValue *value, 
541                                                  GParamSpec *pspec)
542 {
543     HildonSortDialog *dialog;
544
545     dialog = HILDON_SORT_DIALOG (object);
546
547     switch (prop_id) {
548
549         case PROP_SORT_KEY:
550             g_value_set_int (value, hildon_sort_dialog_get_sort_key (dialog));
551             break;
552
553         case PROP_SORT_ORDER:
554             g_value_set_enum (value, hildon_sort_dialog_get_sort_order (dialog));
555             break;
556
557         default:
558             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
559             break;
560
561     }
562 }
563
564 static void 
565 hildon_sort_dialog_finalize                     (GObject *object)
566 {
567     HildonSortDialogPrivate *priv;
568     HildonSortDialog *dialog;
569
570     dialog = HILDON_SORT_DIALOG (object);
571     priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog);
572     g_assert (priv);
573
574     if (priv != NULL && priv->key_reversed != NULL)
575         g_free (priv->key_reversed);
576
577     if (G_OBJECT_CLASS (parent_class)->finalize)
578         G_OBJECT_CLASS (parent_class)->finalize(object);
579 }
580
581