Reply
Thread Tools
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).
 
Posts: 726 | Thanked: 345 times | Joined on Apr 2010 @ Sweden
#2
Isn't the typical wisdom that if you're going to change the backing store, detach it from the display part first, do the change and then re-connect it?

This is what I've seen recommended for GtkTreeViews, for example.
 
Posts: 166 | Thanked: 106 times | Joined on Dec 2007 @ Finland
#3
Originally Posted by Joorin View Post
Isn't the typical wisdom that if you're going to change the backing store, detach it from the display part first, do the change and then re-connect it?

This is what I've seen recommended for GtkTreeViews, for example.
Thanks for your suggestion. However, with my limited knowledge of GTK+, I don't know how to do that.

Anyway, I solved the problem with g_signal_handlers_block_by_func. In the example above, the first argument to g_signal_handlers_block_by_func should be GTK_WIDGET(user_data) which is a pointer pointing to the picker button. I my bigger program I also missed to notice that you must have both the function name and the user argument right.
 
nicolai's Avatar
Posts: 1,637 | Thanked: 4,424 times | Joined on Apr 2009 @ Germany
#4
I had the same problem since PR 1.2
(But I do not have much experience with gtk,
so this may be in fact another problem or just my fault).
I tried to detach the selector from the liststore
by setting the current model to NULL, and then clear the
liststore.
But this gives some warning from the touch selector
(invalid iterator). Finally I got it working by deselecting
any touch selector row. (set selected row to -1).

Maybe this helps

nicolai
 

The Following User Says Thank You to nicolai For This Useful Post:
Posts: 166 | Thanked: 106 times | Joined on Dec 2007 @ Finland
#5
Originally Posted by nicolai View Post
Finally I got it working by deselecting
any touch selector row. (set selected row to -1)
I thought also that the problem could be handled that way, but as I wrote above, I solved the problem with blocking the callback.
 
No!No!No!Yes!'s Avatar
Posts: 700 | Thanked: 846 times | Joined on Nov 2009
#6
Originally Posted by nicolai View Post
I had the same problem since PR 1.2
(But I do not have much experience with gtk,
so this may be in fact another problem or just my fault).
I tried to detach the selector from the liststore
by setting the current model to NULL, and then clear the
liststore.
But this gives some warning from the touch selector
(invalid iterator). Finally I got it working by deselecting
any touch selector row. (set selected row to -1).

Maybe this helps

nicolai
10x, nicolai ... your tip saved me hours cussing QBW!!!
__________________
Have a look at Queen BeeCon Widget (WIKI) Customizable and flexible widget-based multi-instance monitoring, alerting and interactive tool for the N900
Please provide comments and feedback for having QBW supported and enhanced further - (DONATE) - v1.3.3devel / v1.3.3testing / v1.3.3extras
 
Reply


 
Forum Jump


All times are GMT. The time now is 09:26.