377. How to revert combobox selection - Part 1 - using block?

Problem

This is in response to vlada's post titled Block/revert combobox selection.

He would like to be able to allow users to confirm change of options in combobox. If the user decide not to change the option, we will revert the option back to the original one as shown below.

There are several ways to accomplish this. We will show you the first method in this article — by blocking the signal temporarily.

How to revert combobox selection - Part 1 - using block?


Solution

  • If the user decides not to change the option, before reverting the option back to the orignal option, we need to use GObject::block() to temporariy block the signal GtkComboBox:changed. Otherwise you will find your application going into a continuous loop.
  • When you have reverted the combobox option back to the original, don't forget to use GObject::unblock() to unblock the signal.

Sample Code

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
14   
15   
16   
17   
18   
19   
20   
21   
22   
23   
24   
25   
26   
27   
28   
29   
30   
31   
32   
33   
34   
35   
36   
37   
38   
39   
40   
41   
42   
43   
44   
45   
46   
47   
48   
49   
50   
51   
52   
53   
54   
55   
56   
58   
59   
60   
61   
62   
63   
64   
65   
66   
67   
68   
69   
70   
71   
72   
73   
74   
75   
76   
77   
78   
79   
80   
81   
82   
83   
84   
85   
86   
87   
88   
89   
90   
91   
92   
93   
94   
95   
<?php
$window = new GtkWindow();
$window->set_title($argv[0]);
$window->connect_simple('destroy', array( 'Gtk', 'main_quit'));
$window->set_size_request(400,150);
$window->add($vbox = new GtkVBox());

// display title
$title = new GtkLabel("Revert combobox selection\n".
"     Part 1 - using block()");
$title->modify_font(new PangoFontDescription("Times New Roman Italic 10"));
$title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff"));
$title->set_size_request(-1, 60);
$vbox->pack_start($title, 0, 0);

// the selection
$list = array('item 1', 'item 2', 'item 3', 'item 4');

$vbox->pack_start($hbox=new GtkHBox(), 0, 0);
$hbox->pack_start(new GtkLabel('Select: '), 0, 0);

// Create a combobox
$combobox = new GtkComboBox();

// Create a model
if (defined("GObject::TYPE_STRING")) {
    $model = new GtkListStore(GObject::TYPE_STRING);
} else {
    $model = new GtkListStore(Gtk::TYPE_STRING);
}

// Set up the combobox
$combobox->set_model($model);
$cellRenderer = new GtkCellRendererText();
$combobox->pack_start($cellRenderer);
$combobox->set_attributes($cellRenderer, 'text', 0);
$signal_id = $combobox->connect('changed', 'on_change'); // note 1
$hbox->pack_start($combobox, 0, 0);
$prev_index = -1;

// Stuff the choices in the model
foreach($list as $choice) {
    $model->append(array($choice));
}

$window->show_all();
Gtk::main();

function on_change($combobox) {
    $model = $combobox->get_model();
    $selection = $combobox->get_active_text();
    global $prev_index, $prev_selection;
    $selected_index = $combobox->get_active();
    $response = yes_no_dialog("Previous selection: $prev_selection\n". // note 2
    "New selection: $selection\n".
    "Are you sure you want to make the change?");
    echo "You have selected: $selection (index=$selected_index)!\n";

    switch($response) {
        case Gtk::RESPONSE_YES:
            echo "yes, change the option\n";
            $prev_index = $selected_index; // note 3
            $prev_selection = $selection; // note 3
            break;
        case Gtk::RESPONSE_NO: // note 4
            echo "no, revert to the original value\n";
            global $signal_id;
            $combobox->block($signal_id); // note 5
            $combobox->set_active($prev_index); // note 6
            $combobox->unblock($signal_id); // note 7
            break;
    }
}

function yes_no_dialog($msg) {

    $dialog = new GtkDialog();
    $dialog->set_title('Yes/No Dialog');
    $label = new GtkLabel($msg);
    $dialog->vbox->pack_start($label);

    $dialog->add_buttons(array(
        Gtk::STOCK_YES, Gtk::RESPONSE_YES,
        Gtk::STOCK_NO, Gtk::RESPONSE_NO
    ));

    $dialog->show_all();
    $response_id = $dialog->run();
    $dialog->destroy();

    return $response_id;
}

?>

Output

As shown above.
 

Explanation

We make use of the code from How to setup and process GtkComboBox? to set up the combobox.

We also make use of the technique as outlined in How to setup a dialog box - Part 2 - simple yes no dialog? to set up the yes-no dialog prompt.

What's new here:

  1. Note that we need this $signal_id when we want to block/unblock this signal later.
  2. Pop up a yes-no dialog box to ask the user for confirmation of change of option.
  3. Make a copy of the previous selection in case the user wants to revert to the original option..
  4. The user has selected No.
  5. Block the signal 'changed'.
  6. Revert back the previous selection.
  7. Unblock the signal 'changed'.

Related Links

Add comment


Security code
Refresh