New API to change format policy on HildonTimeSelector
authorAlejandro Piñeiro <apinheiro@igalia.com>
Tue, 28 Apr 2009 17:42:11 +0000 (19:42 +0200)
committerAlejandro Piñeiro <apinheiro@igalia.com>
Tue, 28 Apr 2009 18:20:10 +0000 (20:20 +0200)
* src/hildon-time-selector.h:
Added HildonTimeSelectorFormatPolicy
* src/hildon-time-selector.c:
Added PROP_TIME_FORMAT_POLICY
(_check_ampm_format): renamed to check_automatic_ampm_format
(update_format_policy), (update_format_dependant_columns): new functions
(hildon_time_selector_class_init)
(hildon_time_selector_contructor)
(hildon_time_selector_init)
(hildon_time_selector_get_property)
(hildon_time_selector_set_property)
(hildon_time_selector_get_time)
(hildon_time_selector_set_time)
* src/hildon-touch-selector.h: new file
* src/hildon-touch-selector.c
(hildon_touch_selector_emit_changed)
(hildon_touch_selector_block_changed)
(hildon_touch_selector_unblock_changed)
Added functions to allow to block the emission of the "changed" signal
* src/hildon-picker-dialog.c
(hildon_picker_dialog_show): call the parent show before the custom code
* examples/hildon-time-button-example.c
Modified, so now you can configure the time format using the new property

Added a new property "time-format-policy" that allow to choose the time
format: AM/PM, 24H or AUTOMATIC. AUTOMATIC is the default one. In this
case it uses gconf in order to check if the time selector must use
AM/PM or 24H.

Fixes: NB#111606 (HildonTimeSelector should expose API to set/unset am/pm mode)

ChangeLog
examples/hildon-time-button-example.c
src/Makefile.am
src/hildon-picker-dialog.c
src/hildon-time-selector.c
src/hildon-time-selector.h
src/hildon-touch-selector-private.h [new file with mode: 0644]
src/hildon-touch-selector.c

index f6ac15b..52b0721 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2009-04-28  Alejandro Pinheiro  <apinheiro@igalia.com>
+
+       * src/hildon-time-selector.h:
+       Added HildonTimeSelectorFormatPolicy
+       * src/hildon-time-selector.c:
+       Added PROP_TIME_FORMAT_POLICY
+       (_check_ampm_format): renamed to check_automatic_ampm_format
+       (update_format_policy), (update_format_dependant_columns): new functions
+       (hildon_time_selector_class_init)
+       (hildon_time_selector_contructor)
+       (hildon_time_selector_init)
+       (hildon_time_selector_get_property)
+       (hildon_time_selector_set_property)
+       (hildon_time_selector_get_time)
+       (hildon_time_selector_set_time)
+       * src/hildon-touch-selector.h: new file
+       * src/hildon-touch-selector.c
+       (hildon_touch_selector_emit_changed)
+       (hildon_touch_selector_block_changed)
+       (hildon_touch_selector_unblock_changed)
+       Added functions to allow to block the emission of the "changed" signal
+       * src/hildon-picker-dialog.c
+       (hildon_picker_dialog_show): call the parent show before the custom code
+       * examples/hildon-time-button-example.c
+       Modified, so now you can configure the time format using the new property
+
+       Added a new property "time-format-policy" that allow to choose the time
+       format: AM/PM, 24H or AUTOMATIC. AUTOMATIC is the default one. In this
+       case it uses gconf in order to check if the time selector must use
+       AM/PM or 24H.
+
+       Fixes: NB#111606 (HildonTimeSelector should expose API to set/unset am/pm
+       mode)
+
 2009-04-28  Alberto Garcia  <agarcia@igalia.com>
 
        * src/hildon-note.c (hildon_note_init):
index 531706a..ef2ea4e 100644 (file)
@@ -9,12 +9,47 @@ on_picker_value_changed (HildonPickerButton * button, gpointer data)
            hildon_button_get_value (HILDON_BUTTON (button)));
 }
 
+static void
+on_change_policy_clicked (GtkButton *button,
+                          gpointer data)
+{
+  static HildonTimeSelectorFormatPolicy policy = HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC;
+  HildonPickerButton *time_button = NULL;
+  HildonTouchSelector *selector = NULL;
+
+  policy = (policy + 1)%3;
+
+  switch (policy)
+    {
+    case HILDON_TIME_SELECTOR_FORMAT_POLICY_AMPM:
+      hildon_button_set_value (HILDON_BUTTON (button),
+                               "AMPM");
+      break;
+    case HILDON_TIME_SELECTOR_FORMAT_POLICY_24H:
+      hildon_button_set_value (HILDON_BUTTON (button),
+                               "24H");
+      break;
+    case HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC:
+      hildon_button_set_value (HILDON_BUTTON (button),
+                               "Automatic");
+      break;
+    }
+
+  time_button = HILDON_PICKER_BUTTON (data);
+  selector = hildon_picker_button_get_selector (time_button);
+
+  g_object_set (G_OBJECT (selector),
+                "time-format-policy", policy, NULL);
+}
+
 int
 main (int argc, char **argv)
 {
   HildonProgram *program = NULL;
   GtkWidget *window = NULL;
   GtkWidget *button;
+  GtkWidget *hbox;
+  GtkWidget *button2;
 
   hildon_gtk_init (&argc, &argv);
 
@@ -29,9 +64,21 @@ main (int argc, char **argv)
   g_signal_connect (G_OBJECT (button), "value-changed",
                     G_CALLBACK (on_picker_value_changed), NULL);
 
-  gtk_container_add (GTK_CONTAINER (window), button);
+  button2 = hildon_button_new_with_text (HILDON_SIZE_AUTO_WIDTH |
+                                         HILDON_SIZE_AUTO_HEIGHT,
+                                         HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
+                                         "Change Policy", "Automatic");
+
+  g_signal_connect (G_OBJECT (button2), "clicked",
+                    G_CALLBACK (on_change_policy_clicked), button);
+
+  hbox = gtk_hbox_new (FALSE, 10);
+
+  gtk_container_add (GTK_CONTAINER (hbox), button);
+  gtk_container_add (GTK_CONTAINER (hbox), button2);
+  gtk_container_add (GTK_CONTAINER (window), hbox);
 
-  g_signal_connect (G_OBJECT (window), "delete-event", 
+  g_signal_connect (G_OBJECT (window), "delete-event",
                     G_CALLBACK (gtk_main_quit), NULL);
 
   gtk_widget_show_all (window);
index 10187f0..a38c868 100644 (file)
@@ -196,7 +196,8 @@ noinst_HEADERS = hildon-banner-private.h            \
                hildon-wizard-dialog-private.h          \
                hildon-calendar-private.h               \
                hildon-app-menu-private.h               \
-               hildon-bread-crumb-widget.h
+               hildon-bread-crumb-widget.h             \
+               hildon-touch-selector-private.h
 
 # Don't build the library until we have built the header that it needs:
 $(OBJECTS) $(libhildon_$(API_VERSION_MAJOR)_la_OBJECTS): hildon-enum-types.h hildon-marshalers.c hildon-marshalers.h
index 3fa11b3..5539c99 100644 (file)
@@ -283,6 +283,8 @@ hildon_picker_dialog_show                       (GtkWidget *widget)
   HildonPickerDialog *dialog = HILDON_PICKER_DIALOG (widget);
   HildonTouchSelector *selector;
 
+  GTK_WIDGET_CLASS (hildon_picker_dialog_parent_class)->show (widget);
+
   if (dialog->priv->center_on_show) {
     selector = hildon_picker_dialog_get_selector (dialog);
     hildon_touch_selector_center_on_selected (selector);
@@ -291,7 +293,6 @@ hildon_picker_dialog_show                       (GtkWidget *widget)
   _save_current_selection (dialog);
   prepare_action_area (dialog);
 
-  GTK_WIDGET_CLASS (hildon_picker_dialog_parent_class)->show (widget);
 }
 
 static void
index ad8f5cf..e605d40 100644 (file)
@@ -47,7 +47,9 @@
 #include <locale.h>
 #include <gconf/gconf-client.h>
 
+#include "hildon-enum-types.h"
 #include "hildon-time-selector.h"
+#include "hildon-touch-selector-private.h"
 
 #define HILDON_TIME_SELECTOR_GET_PRIVATE(obj)                           \
   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_TIME_SELECTOR, HildonTimeSelectorPrivate))
@@ -81,7 +83,8 @@ enum {
 enum
 {
   PROP_0,
-  PROP_MINUTES_STEP
+  PROP_MINUTES_STEP,
+  PROP_TIME_FORMAT_POLICY
 };
 
 struct _HildonTimeSelectorPrivate
@@ -91,6 +94,7 @@ struct _HildonTimeSelectorPrivate
   GtkTreeModel *ampm_model;
 
   guint minutes_step;
+  HildonTimeSelectorFormatPolicy format_policy;
   gboolean ampm_format;         /* if using am/pm format or 24 h one */
 
   gboolean pm;                  /* if we are on pm (only useful if ampm_format == TRUE) */
@@ -120,13 +124,23 @@ static GtkTreeModel *_create_ampm_model (HildonTimeSelector * selector);
 static void _get_real_time (gint * hours, gint * minutes);
 static void _manage_ampm_selection_cb (HildonTouchSelector * selector,
                                        gint num_column, gpointer data);
-static void _check_ampm_format (HildonTimeSelector * selector);
 static void _set_pm (HildonTimeSelector * selector, gboolean pm);
 
 static gchar *_custom_print_func (HildonTouchSelector * selector,
                                   gpointer user_data);
 
 static void
+check_automatic_ampm_format                     (HildonTimeSelector * selector);
+
+static void
+update_format_policy                            (HildonTimeSelector *selector,
+                                                 HildonTimeSelectorFormatPolicy new_policy);
+static void
+update_format_dependant_columns                 (HildonTimeSelector *selector,
+                                                 guint hours,
+                                                 guint minutes);
+
+static void
 hildon_time_selector_class_init (HildonTimeSelectorClass * class)
 {
   GObjectClass *gobject_class;
@@ -154,6 +168,22 @@ hildon_time_selector_class_init (HildonTimeSelectorClass * class)
                                                       1, 30, 1,
                                                       G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
 
+  /**
+   * HildonTimeSelector:time-format-policy:
+   *
+   * The visual policy of the time format
+   *
+   * Since: 2.2
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_TIME_FORMAT_POLICY,
+                                   g_param_spec_enum ("time_format_policy",
+                                                      "time format policy",
+                                                      "Visual policy of the time format",
+                                                      HILDON_TYPE_TIME_SELECTOR_FORMAT_POLICY,
+                                                      HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC,
+                                                      G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+
   /* GtkWidget */
 
   /* GtkContainer */
@@ -163,6 +193,9 @@ hildon_time_selector_class_init (HildonTimeSelectorClass * class)
   g_type_class_add_private (object_class, sizeof (HildonTimeSelectorPrivate));
 }
 
+/* FIXME: the constructor was required because as we need the initial values
+   of the properties passed on g_object_new. But, probably use the method
+   constructed could be easier */
 static GObject*
 hildon_time_selector_constructor (GType type,
                                   guint n_construct_properties,
@@ -225,11 +258,12 @@ hildon_time_selector_init (HildonTimeSelector * selector)
   hildon_touch_selector_set_print_func (HILDON_TOUCH_SELECTOR (selector),
                                         _custom_print_func);
 
+  /* By default we use the automatic ampm format */
+  selector->priv->pm = TRUE;
+  check_automatic_ampm_format (selector);
+
   _get_real_time (&selector->priv->creation_hours,
                   &selector->priv->creation_minutes);
-
-  _check_ampm_format (selector);
-
 }
 
 static void
@@ -245,7 +279,9 @@ hildon_time_selector_get_property (GObject *object,
     case PROP_MINUTES_STEP:
       g_value_set_uint (value, priv->minutes_step);
       break;
-
+    case PROP_TIME_FORMAT_POLICY:
+      g_value_set_enum (value, priv->format_policy);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
@@ -265,7 +301,10 @@ hildon_time_selector_set_property (GObject *object,
     case PROP_MINUTES_STEP:
       priv->minutes_step = g_value_get_uint (value);
       break;
-
+    case PROP_TIME_FORMAT_POLICY:
+      update_format_policy (HILDON_TIME_SELECTOR (object),
+                            g_value_get_enum (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
@@ -275,7 +314,10 @@ hildon_time_selector_set_property (GObject *object,
 static void
 hildon_time_selector_finalize (GObject * object)
 {
-  /* FIXME: FILL ME !! */
+  /* Note: we don't require to free the models. We don't manage it using own
+     references, so will be freed on the hildon-touch-selector finalize code.
+     See the implementation notes related to that on the touch selector
+     code. */
 
   (*G_OBJECT_CLASS (hildon_time_selector_parent_class)->finalize) (object);
 }
@@ -439,7 +481,7 @@ _manage_ampm_selection_cb (HildonTouchSelector * touch_selector,
 }
 
 static void
-_check_ampm_format (HildonTimeSelector * selector)
+check_automatic_ampm_format (HildonTimeSelector * selector)
 {
   GConfClient *client = NULL;
   gboolean value = TRUE;
@@ -455,7 +497,6 @@ _check_ampm_format (HildonTimeSelector * selector)
   }
 
   selector->priv->ampm_format = !value;
-  selector->priv->pm = TRUE;
 }
 
 static void
@@ -465,12 +506,102 @@ _set_pm (HildonTimeSelector * selector, gboolean pm)
 
   selector->priv->pm = pm;
 
-  gtk_tree_model_iter_nth_child (selector->priv->ampm_model, &iter, NULL, pm);
+  if (selector->priv->ampm_model != NULL) {
+    gtk_tree_model_iter_nth_child (selector->priv->ampm_model, &iter, NULL, pm);
 
-  hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector),
-                                     COLUMN_AMPM, &iter, FALSE);
+    hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector),
+                                       COLUMN_AMPM, &iter, FALSE);
+  }
 }
 
+static void
+update_format_policy                            (HildonTimeSelector *selector,
+                                                 HildonTimeSelectorFormatPolicy new_policy)
+{
+  gboolean prev_ampm_format = FALSE;
+  guint hours;
+  guint minutes;
+  gint num_columns = -1;
+
+  num_columns = hildon_touch_selector_get_num_columns (HILDON_TOUCH_SELECTOR (selector));
+  prev_ampm_format = selector->priv->ampm_format;
+
+  if (new_policy != selector->priv->format_policy) {
+    selector->priv->format_policy = new_policy;
+
+    /* We get the hour previous all the changes, to avoid problems with the
+       changing widget structure */
+    if (num_columns >= 2) {/* we are on the object construction */
+      hildon_time_selector_get_time (selector, &hours, &minutes);
+    }
+
+    switch (new_policy)
+      {
+      case HILDON_TIME_SELECTOR_FORMAT_POLICY_AMPM:
+        selector->priv->ampm_format = TRUE;
+        break;
+      case HILDON_TIME_SELECTOR_FORMAT_POLICY_24H:
+        selector->priv->ampm_format = FALSE;
+        break;
+      case HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC:
+        check_automatic_ampm_format (selector);
+        break;
+      }
+  }
+
+  if (prev_ampm_format != selector->priv->ampm_format) {
+    update_format_dependant_columns (selector, hours, minutes);
+  }
+}
+
+static void
+update_format_dependant_columns                 (HildonTimeSelector *selector,
+                                                 guint hours,
+                                                 guint minutes)
+{
+  gint num_columns = -1;
+
+  num_columns = hildon_touch_selector_get_num_columns (HILDON_TOUCH_SELECTOR (selector));
+  if (num_columns < 2) {/* we are on the object construction */
+    return;
+  }
+
+  /* To avoid an extra and wrong VALUE_CHANGED signal on the model update */
+  hildon_touch_selector_block_changed (HILDON_TOUCH_SELECTOR(selector));
+
+  selector->priv->hours_model = _create_hours_model (selector);
+  hildon_touch_selector_set_model (HILDON_TOUCH_SELECTOR (selector),
+                                   0,
+                                   selector->priv->hours_model);
+
+  /* We need to set NOW the correct hour on the hours column, because the number of
+     columns will be updated too, so a signal COLUMNS_CHANGED will be emitted. Some
+     other widget could have connected to this signal and ask for the hour, so this
+     emission could have a wrong hour. We could use a custom func to only modify the
+     hours selection, but hildon_time_selector_time manage yet all the ampm issues
+     to select the correct one */
+  hildon_time_selector_set_time (selector, hours, minutes);
+
+  /* if we are at this function, we are sure that a change on the number of columns
+     will happen, so check the column number is not required */
+  if (selector->priv->ampm_format) {
+    selector->priv->ampm_model = _create_ampm_model (selector);
+
+    hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
+                                              selector->priv->ampm_model, TRUE);
+
+    g_signal_connect (G_OBJECT (selector),
+                      "changed", G_CALLBACK (_manage_ampm_selection_cb),
+                      NULL);
+  } else {
+    selector->priv->ampm_model = NULL;
+    hildon_touch_selector_remove_column (HILDON_TOUCH_SELECTOR (selector), 2);
+  }
+
+  _set_pm (selector, hours >= 12);
+
+  hildon_touch_selector_unblock_changed (HILDON_TOUCH_SELECTOR (selector));
+}
 /* ------------------------------ PUBLIC METHODS ---------------------------- */
 
 /**
@@ -529,12 +660,13 @@ hildon_time_selector_set_time (HildonTimeSelector * selector,
   GtkTreeIter iter;
   gint hours_item = 0;
 
+  g_return_val_if_fail (HILDON_IS_TIME_SELECTOR (selector), FALSE);
   g_return_val_if_fail (hours <= 23, FALSE);
   g_return_val_if_fail (minutes <= 59, FALSE);
 
-  if (selector->priv->ampm_format) {
-    _set_pm (selector, hours >= 12);
+  _set_pm (selector, hours >= 12);
 
+  if (selector->priv->ampm_format) {
     hours_item = hours - selector->priv->pm * 12;
   } else {
     hours_item = hours;
@@ -574,11 +706,15 @@ hildon_time_selector_get_time (HildonTimeSelector * selector,
 {
   GtkTreeIter iter;
 
+  g_return_if_fail (HILDON_IS_TIME_SELECTOR (selector));
+
   if (hours != NULL) {
-    hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector),
-                                        COLUMN_HOURS, &iter);
-    gtk_tree_model_get (selector->priv->hours_model,
-                        &iter, COLUMN_INT, hours, -1);
+    if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector),
+                                            COLUMN_HOURS, &iter)) {
+
+      gtk_tree_model_get (selector->priv->hours_model,
+                          &iter, COLUMN_INT, hours, -1);
+    }
     if (selector->priv->ampm_format) {
       *hours %= 12;
       *hours += selector->priv->pm * 12;
@@ -586,9 +722,10 @@ hildon_time_selector_get_time (HildonTimeSelector * selector,
   }
 
   if (minutes != NULL) {
-    hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector),
-                                        COLUMN_MINUTES, &iter);
-    gtk_tree_model_get (selector->priv->minutes_model,
-                        &iter, COLUMN_INT, minutes, -1);
+    if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector),
+                                            COLUMN_MINUTES, &iter)) {
+      gtk_tree_model_get (selector->priv->minutes_model,
+                          &iter, COLUMN_INT, minutes, -1);
+    }
   }
 }
index 21dcb91..f01b704 100644 (file)
@@ -66,6 +66,21 @@ struct                                          _HildonTimeSelectorClass
 };
 
 
+/**
+ * HildonTimeSelectorFormatPolicy:
+ * @HILDON_TIME_SELECTOR_FORMAT_POLICY_AMPM: The time selector will use a AMPM time format
+ * @HILDON_TIME_SELECTOR_FORMAT_POLICY_24H: The time selector will use a 24H time format
+ * @HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC: The time selector will use AMPM or 24H depending
+ *  on the current environment
+ *
+ * Describes the time format used at #HildonTimeSelector
+ **/
+typedef enum {
+  HILDON_TIME_SELECTOR_FORMAT_POLICY_AMPM,
+  HILDON_TIME_SELECTOR_FORMAT_POLICY_24H,
+  HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC
+}                                               HildonTimeSelectorFormatPolicy;
+
 /* construction */
 GType
 hildon_time_selector_get_type                   (void) G_GNUC_CONST;
diff --git a/src/hildon-touch-selector-private.h b/src/hildon-touch-selector-private.h
new file mode 100644 (file)
index 0000000..eeee475
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * This file is a part of hildon
+ *
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Contact: Rodrigo Novo <rodrigo.novo@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version. or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef                                         __HILDON_TOUCH_SELECTOR_PRIVATE_H__
+#define                                         __HILDON_TOUCH_SELECTOR_PRIVATE_H__
+
+
+G_BEGIN_DECLS
+
+void G_GNUC_INTERNAL
+hildon_touch_selector_block_changed             (HildonTouchSelector *selector);
+
+void G_GNUC_INTERNAL
+hildon_touch_selector_unblock_changed           (HildonTouchSelector *selector);
+
+G_END_DECLS
+
+#endif
index c8d90df..4ab005d 100644 (file)
 
 #include "hildon-pannable-area.h"
 #include "hildon-touch-selector.h"
+#include "hildon-touch-selector-private.h"
 
 #define HILDON_TOUCH_SELECTOR_GET_PRIVATE(obj)                          \
   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelectorPrivate))
@@ -204,6 +205,8 @@ struct _HildonTouchSelectorPrivate
   GtkWidget *hbox;              /* the container for the selector's columns */
   gboolean initial_scroll;      /* whether initial fancy scrolling to selection */
 
+  gboolean changed_blocked;
+
   HildonTouchSelectorPrintFunc print_func;
   gpointer print_user_data;
   GDestroyNotify print_destroy_func;
@@ -271,6 +274,10 @@ _hildon_touch_selector_set_model                (HildonTouchSelector * selector,
 static gboolean
 _hildon_touch_selector_has_multiple_selection   (HildonTouchSelector * selector);
 
+static void
+hildon_touch_selector_emit_value_changed        (HildonTouchSelector *selector,
+                                                 gint column);
+
 /* GtkCellLayout implementation (HildonTouchSelectorColumn)*/
 static void hildon_touch_selector_column_cell_layout_init         (GtkCellLayoutIface      *iface);
 
@@ -451,6 +458,8 @@ hildon_touch_selector_init (HildonTouchSelector * selector)
   selector->priv->initial_scroll = TRUE;
   selector->priv->hbox = gtk_hbox_new (FALSE, 0);
 
+  selector->priv->changed_blocked = FALSE;
+
   gtk_box_pack_end (GTK_BOX (selector), selector->priv->hbox,
                     TRUE, TRUE, 0);
   gtk_widget_show (selector->priv->hbox);
@@ -515,6 +524,27 @@ hildon_touch_selector_remove (GtkContainer * container, GtkWidget * widget)
 }
 
 /* ------------------------------ PRIVATE METHODS ---------------------------- */
+void
+hildon_touch_selector_block_changed             (HildonTouchSelector *selector)
+{
+  selector->priv->changed_blocked = TRUE;
+}
+
+void
+hildon_touch_selector_unblock_changed           (HildonTouchSelector *selector)
+{
+  selector->priv->changed_blocked = FALSE;
+}
+
+static void
+hildon_touch_selector_emit_value_changed        (HildonTouchSelector *selector,
+                                                 gint column)
+{
+  if (!selector->priv->changed_blocked) {
+    g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
+  }
+}
+
 /**
  * default_print_func:
  * @selector: a #HildonTouchSelector
@@ -637,7 +667,7 @@ _row_tapped_cb (GtkTreeView * tree_view, GtkTreePath * path, gpointer user_data)
 
   num_column = g_slist_index (selector->priv->columns, column);
 
-  g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, num_column);
+  hildon_touch_selector_emit_value_changed (selector, num_column);
 }
 
 
@@ -1172,7 +1202,7 @@ hildon_touch_selector_append_column (HildonTouchSelector * selector,
   g_signal_emit (selector, hildon_touch_selector_signals[COLUMNS_CHANGED], 0);
   if (emit_changed) {
     colnum = g_slist_length (selector->priv->columns);
-    g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, colnum);
+    hildon_touch_selector_emit_value_changed (selector, colnum);
   }
 
   return new_column;
@@ -1410,7 +1440,8 @@ hildon_touch_selector_set_column_selection_mode (HildonTouchSelector * selector,
     gtk_tree_selection_unselect_all (selection);
     gtk_tree_selection_select_iter (selection, &iter);
 
-    g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
+    /* the column changed was the first one */
+    hildon_touch_selector_emit_value_changed (selector, 0);
   }
 
 }
@@ -1528,7 +1559,7 @@ hildon_touch_selector_set_active                (HildonTouchSelector *selector,
   if (index != -1)
     gtk_tree_selection_select_path (selection, path);
 
-  g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
+  hildon_touch_selector_emit_value_changed (selector, column);
 
   gtk_tree_path_free (path);
 }
@@ -1663,7 +1694,7 @@ hildon_touch_selector_select_iter (HildonTouchSelector * selector,
     hildon_touch_selector_scroll_to (current_column, tv, path);
   }
 
-  g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
+  hildon_touch_selector_emit_value_changed (selector, column);
 
   gtk_tree_path_free (path);
 }
@@ -1693,7 +1724,7 @@ void hildon_touch_selector_unselect_iter (HildonTouchSelector * selector,
   selection = gtk_tree_view_get_selection (current_column->priv->tree_view);
   gtk_tree_selection_unselect_iter (selection, iter);
 
-  g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
+  hildon_touch_selector_emit_value_changed (selector, column);
 }
 
 /**
@@ -1719,7 +1750,7 @@ hildon_touch_selector_unselect_all (HildonTouchSelector * selector,
   selection = gtk_tree_view_get_selection (current_column->priv->tree_view);
   gtk_tree_selection_unselect_all (selection);
 
-  g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
+  hildon_touch_selector_emit_value_changed (selector, column);
 }
 
 /**