View Single Post
Posts: 166 | Thanked: 106 times | Joined on Dec 2007 @ Finland
#1
I noticed a behavior that I believe was introduced in the recent updates of SDK to PR1.2. I have used gtk_list_store_clear to clear a list store associated with a touch selector. Now it seems that gtk_list_store_clear emits several times the "value-changed" signal for the picker button of the touch selector. I tried to block the signal by using g_signal_handlers_block_by_func/g_signal_handlers_unblock_by_func around gtk_list_store_clear but the signal is still emitted.

Here is a simple example which should demonstrate the behaviour.

Code:
/*
 * This file is adapted from Hildon Tutorial Examples
 *
 * Copyright (C) 2009 Nokia Corporation. All rights reserved.
 *
 * This maemo code example is licensed under a MIT-style license,
 * that can be found in the file called "COPYING" in the package
 * root directory.
 *
 */

#include                                        <hildon/hildon.h>

void value_changed (GtkWidget *widget, gpointer user_data)
{
  gint current_selection;
  HildonTouchSelector *selector;

  g_printerr("%s() start\n",__PRETTY_FUNCTION__);

  selector = hildon_picker_button_get_selector(HILDON_PICKER_BUTTON(widget));
  current_selection = hildon_touch_selector_get_active (selector, 0);
  g_printerr ("Current selection : %d\n", current_selection);

  g_printerr("%s() end\n",__PRETTY_FUNCTION__);
}

void fill_simple_selector(GtkWidget *selector)
{
  gint i;

  for (i = 1; i <= 5 ; i++) {
    gchar *label = g_strdup_printf ("Item %d", i);

    /* Add item to the column */
    hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector),
                                       label);

    g_free (label);
  }
}

static GtkWidget *create_simple_selector (void)
{
  GtkWidget *selector = NULL;

  /* Create a HildonTouchSelector with a single text column */
  selector = hildon_touch_selector_new_text();

  /* Populate selector */
  fill_simple_selector(selector);

  return selector;
}

void button_clicked( GtkWidget *widget,  gpointer user_data)
{
  GtkTreeModel *model;
  HildonTouchSelector *selector;

  g_printerr("%s() start\n",__PRETTY_FUNCTION__);

  selector = hildon_picker_button_get_selector(HILDON_PICKER_BUTTON(user_data));

  /* The following should inhibit the value_changed callback to be called ... */
  g_signal_handlers_block_by_func(selector, G_CALLBACK(value_changed), NULL);

  model = hildon_touch_selector_get_model(HILDON_TOUCH_SELECTOR(selector), 0);
  gtk_list_store_clear(GTK_LIST_STORE(model));
  fill_simple_selector(GTK_WIDGET(selector));

  /* ...until unblocked here*/
  g_signal_handlers_unblock_by_func(selector, G_CALLBACK(value_changed), NULL);

  g_printerr("%s() end\n",__PRETTY_FUNCTION__);
}

int main (int argc, char **argv)
{
  HildonProgram *program = NULL;
  GtkWidget *window = NULL;
  GtkWidget *selector = NULL;
  GtkWidget *box = NULL;
  GtkWidget *picker_button = NULL;
  GtkWidget *button = NULL;

  hildon_gtk_init (&argc, &argv);

  program = hildon_program_get_instance ();
  g_set_application_name
    ("hildon-touch-selector example program");

  window = hildon_stackable_window_new ();
  hildon_program_add_window (program, HILDON_WINDOW (window));

  box = gtk_vbox_new(FALSE, 5);
  gtk_container_add (GTK_CONTAINER (window), box);

  /* Create touch selector */
  selector = create_simple_selector ();

  /* Create a picker button */
  picker_button = hildon_picker_button_new (HILDON_SIZE_AUTO,
                                            HILDON_BUTTON_ARRANGEMENT_VERTICAL);

  /* Set a title to the button*/
  hildon_button_set_title (HILDON_BUTTON (picker_button), "Select an item");

  /* Attach touch selector to the picker button*/
  hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (picker_button),
                                     HILDON_TOUCH_SELECTOR (selector));

  g_signal_connect(G_OBJECT(picker_button), "value-changed",
		   G_CALLBACK(value_changed), NULL);

  /* Add button to main window */
  gtk_box_pack_start (GTK_BOX (box), picker_button, TRUE, TRUE, 0);

  button = hildon_button_new_with_text (HILDON_SIZE_AUTO, 
					HILDON_BUTTON_ARRANGEMENT_VERTICAL,
					"Refill touch selector",
					NULL);
  g_signal_connect(G_OBJECT(button), "clicked",
		   G_CALLBACK(button_clicked), picker_button);
  gtk_box_pack_start (GTK_BOX (box), button, TRUE, TRUE, 0);

  g_signal_connect (G_OBJECT (window), "destroy",
                    G_CALLBACK (gtk_main_quit), NULL);

  gtk_widget_show_all (GTK_WIDGET (window));

  gtk_main ();

  return 0;
}
Compile the code with
Code:
gcc -o hildon-touch-selector-example hildon-touch-selector-example.c `pkg-config gtk+-2.0 hildon-1 --cflags --libs` -Wall
Pressing the "Refill touch selector" button should first clear the touch selector list store and then refill it with the same date. As seen, the value-changed callback (function value_changed()) is called while the button_clicked() callback is running.

Have I understood something wrong? I wouldn't like to use the "changed" callback for the touch selector since it created some problems in my code (not the simple example above).