099. How to display and hide a background process?

Problem

You have set up a process in the background. When F3 is pressed, you would like to view the progress of the background process. Press F3 again, the background process is hidden again, as shown below.

How to display and hide a background process?


Solution


Sample Code

Note: If you have installed php-gtk2 using Gnope Installer on Windows, and if running the sample code below gives you warning that the Symbolic names for keys (e.g. Gdk::KEY_Return) is not defined, you might want to update your php-gtk2 with the latest php-gtk2.dll available here. Simply download the php-gtk2.dll and replace the copy in the folder php-gtk2xt. The latest compilation has put in the Symbolic names for keys listed here.

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   
40   
41   
42   
43   
44   
45   
46   
47   
48   
50   
51   
52   
54   
55   
56   
57   
58   
59   
60   
61   
62   
63   
64   
65   
66   
67   
68   
69   
70   
71   
72   
73   
74   
76   
77   
78   
79   
81   
82   
83   
84   
85   
86   
87   
88   
89   
90   
91   
92   
95   
96   
97   
98   
99   
100   
101   
102   
103   
104   
105   
106   
107   
108   
109   
110   
111   
112   
113   
114   
115   
116   
117   
118   
119   
120   
121   
125   
126   
127   
128   
129   
130   
131   
132   
133   
134   
135   
136   
137   
138   
140   
141   
142   
143   
144   
145   
146   
148   
150   
151   
152   
153   
154   
155   
<?php
$window = new GtkWindow();
$window->set_size_request(400, 175);
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->add($vbox = new GtkVBox());

// display title
$title = new GtkLabel("Display/hide a background process");
$title->modify_font(new PangoFontDescription("Times New Roman Italic 10"));
$title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff"));
$title->set_size_request(-1, 40);
$vbox->pack_start($title, 0, 0);
$vbox->pack_start(new GtkLabel(), 0, 0); // add a small gap

$label = new GtkLabel('Press the button below to start the background process');
$vbox->pack_start($label, 0, 0);
$vbox->pack_start(new GtkLabel(), 0, 0); // add a small gap

$vbox->pack_start($hbox = new GtkHBox(), 0, 0);
$hbox->pack_start($button = new GtkButton('Start processing'), 1, 0);
$vbox->pack_start(new GtkLabel()); // add a small gap
$button->connect('clicked', 'start_processing');

$do_long_task = 0;
$window->connect('key-press-event', 'on_keypress'); // note 1

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

function start_processing($button) {
    global $task_started, $do_long_task, $button, $label;
    if (!$task_started) {
        $do_long_task = new DoLongTask();
        $button->child->set_text('Stop processing');
        $label->set_text('Press F3 to show the background process');
        $task_started = 1;
        $do_long_task->idle_ID = Gtk::idle_add(array(&$do_long_task, 'process_task'));
    } else {
        $do_long_task->dialog->destroy();
        Gtk::idle_remove($do_long_task->idle_ID);
        $task_started = 0;
        $button->child->set_text('Start processing');
        $label->set_text('Press the button below to start the background process');
    }
}

function on_keypress($widget, $event) {
    global $task_started, $do_long_task;
    if (!$task_started) return;
    if ($event->keyval==Gdk::KEY_F3) {
        $do_long_task->dialog->show_all(); // note 4
    }
}

class DoLongTask {

    var $progress_bar, $progress_bar2;
    var $dialog;
    var $subtask_count = 0;
    var $max_task_count = 10;
    var $subtask_count2 = 0;
    var $max_task_count2 = 100;
    var $idle_ID;

    function DoLongTask() {
        // setup a dialog containing progress bar
        $dialog = new GtkDialog('Work in progress...', null, Gtk::DIALOG_MODAL); // create a new dialog
        $dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);
        $top_area = $dialog->vbox;
        $top_area->pack_start(new GtkLabel('Please hold on while processing data...'));

        $this->progress_bar = new GtkProgressBar();
        $this->progress_bar->set_orientation(Gtk::PROGRESS_LEFT_TO_RIGHT);
        $top_area->pack_start($this->progress_bar, 0, 0);

        $this->progress_bar2 = new GtkProgressBar();
        $this->progress_bar2->set_orientation(Gtk::PROGRESS_LEFT_TO_RIGHT);
        $top_area->pack_start($this->progress_bar2, 0, 0);

           $top_area->pack_start(new GtkLabel('Press F3 to hide the background process'), 0, 0);

        $dialog->set_has_separator(false);
        $dialog->show_all(); // show the dialog
        $this->dialog = $dialog; // keep a copy of the dialog ID

        $dialog->connect('delete-event', array( &$this, "on_delete_event"));
        $dialog->connect('key-press-event', array( &$this, "on_keypress_dialog")); // note 2
    }

    // this is where you process your task
    function process_task() {
        echo "processing subtask $this->subtask_count2.$this->subtask_count: ";
        for ($i=0; $i<10; ++$i) {
            usleep(50000); // sleep for half a second
            echo ".";
        }
        echo "\n";

        ++$this->subtask_count;
        $percent_complete = $this->subtask_count/$this->max_task_count;
        $this->progress_bar->set_fraction($percent_complete);
        $percent_complete = number_format($percent_complete*100,0);
        $this->progress_bar->set_text($percent_complete.'% Complete');

        $percent_complete2 = $this->subtask_count2/$this->max_task_count2;
        $this->progress_bar2->set_fraction($percent_complete2);
        $percent_complete2 = number_format($percent_complete2*100,0);
        $this->progress_bar2->set_text($percent_complete2.'% Complete');

        while (Gtk::events_pending()) {Gtk::main_iteration();}

        if ($this->subtask_count < $this->max_task_count) { // task completed?
            return true; // not yet!
        } else {
            $this->subtask_count = 0;
            ++$this->subtask_count2;
            return true;
        }

        if ($this->subtask_count2 >= $this->max_task_count2) { // task completed?
            $this->dialog->destroy();
            Gtk::idle_remove($this->idle_ID);
            return false; // done
        }
    }

    // function that is called when user closes the progress bar dialog
    function on_delete_event($widget, $event) {
        $this->dialog->destroy();
        Gtk::idle_remove($this->idle_ID);
        // any other clean-up that you may want to do
        return true;
    }

    function on_keypress_dialog($widget, $event) {
        if ($event->keyval==Gdk::KEY_F3) {
            $this->dialog->hide(); // note 3
        }
    }
}

?>

Output

As shown above.
 

Explanation

We make use of the code in How to display progress bar while processing long task - Part 2 using_idle_add? to setup the background process.

What's new here:

  1. Capture F3 for main window.
  2. Capture F3 for the popup dialog.
  3. Hide the dialog.
  4. Show the dialog again.

Related Links

Add comment


Security code
Refresh