378. How to revert combobox selection - Part 2 - using emit_stop_by_name?

Problem

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

In How to revert combobox selection - Part 1 - using block?, we used GObject::block() to temporarily block the signal while reverting back the combo options to its previous value.

In this part 2, I'll show you the second method that will achieve the same effect as shown below.

How to revert combobox selection - Part 2 - using emit_stop_by_name?


Solution

  • If the user decides not to change the option, instead of blocking the signal as we've done in method 1, we let the signal pass through, but 'gobble' it up with GObject::emit_stop_by_name()
  • Note that we need a flag to know when we should gobble up the signal. Hence the global variable $is_revert.

Important Note: This only works for PHP-GTK2 compliled with gtk+ v2.10 and above. If you are using an older version, for linux, you may follow the step-by-step instructions to recompile php-gtk2 with gtk+ v2.10. For windows, please refer to How to install php gtk2 on windows? You may also want to take a look here to see some of the new exciting PHP-GTK2 Functionalities.


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   
55   
56   
57   
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   
96   
97   
98   
99   
100   
101   
102   
103   
104   
105   
106   
107   
108   
109   
110   
111   
112   
113   
114   
<?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 2 - using emit_stop_by_name()");
$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);
$combobox->connect('changed', 'on_change');
$hbox->pack_start($combobox, 0, 0);

$prev_index = -1;
$is_revert = 0; // note 1

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

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

function on_change($combobox) {
    global $is_revert;
    if ($is_revert) { // note 2
        $combobox->emit_stop_by_name ('changed'); // note 3
        $is_revert = 0;
        return true;
    }
    $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".
    "New selection: $selection\n".
    "Are you sure you want to make the change?");
    echo "You have selected: $selection (index=$selected_index)! ".
        "(response = $response)\n";

    switch($response) {
        case Gtk::RESPONSE_YES:
            echo "yes, change the option\n";
            $prev_index = $selected_index;
            $prev_selection = $selection;
            break;
        case Gtk::RESPONSE_NO: // note 4
            echo "no, revert to the original value\n";
            $is_revert = 1; // note 4
            $combobox->set_active($prev_index);
            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;

    global $response;
    return $response;
    switch($response_id) {
        case Gtk::RESPONSE_YES:
            $response->set_text("$response_id (Yes)");
            break;
        case Gtk::RESPONSE_NO:
            $response->set_text("$response_id (No)");
            break;
    }

}

?>

Output

As shown above.
 

Explanation

We make use of the code from How to revert combobox selection - Part 1 - using block?

What's new here:

  1. We used a global variable $is_revert to keep track of whether we are reverting the combobox option.
  2. Check if we are reverting the option.
  3. If yes, we use emit_stop_by_name to gobble up the 'changed' signal.
  4. If the user selects No, we set the global variable $is_revert to 1.

Related Links

Add comment


Security code
Refresh