]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormForks.C
Yet more dialog tweaking from Rob.
[lyx.git] / src / frontends / xforms / FormForks.C
1 /**
2  * \file FormForks.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming 
7  *
8  * Full author contact details are available in file CREDITS
9  * \date 2001-10-22
10  */
11
12 #include <config.h>
13
14 #ifdef __GNUG__
15 #pragma implementation
16 #endif
17
18 #include "xformsBC.h"
19 #include "FormForks.h"
20 #include "ControlForks.h"
21 #include "forms/form_forks.h"
22 #include "Tooltips.h"
23 #include "helper_funcs.h"
24 #include "xforms_helpers.h"
25 #include "gettext.h"
26 #include "support/lstrings.h"
27 #include FORMS_H_LOCATION
28
29 using std::vector;
30 using std::find;
31 using std::find_if;
32
33 typedef FormCB<ControlForks, FormDB<FD_forks> > base_class;
34
35 FormForks::FormForks()
36         : base_class(_("Child processes"))
37 {}
38
39
40 void FormForks::build() {
41         dialog_.reset(build_forks(this));
42
43         // It appears that the browsers aren't initialised properly.
44         // This fudge fixes tings.
45         fl_add_browser_line(dialog_->browser_children, " ");
46         fl_add_browser_line(dialog_->browser_kill, " ");
47         fl_clear_browser(dialog_->browser_children);
48         fl_clear_browser(dialog_->browser_kill);
49
50         // Manage the ok, apply, restore and cancel/close buttons
51         bc().setOK(dialog_->button_ok);
52         bc().setApply(dialog_->button_apply);
53         bc().setCancel(dialog_->button_close);
54         bc().invalid();
55
56         // Set up the tooltip mechanism
57         string str = _("All currently running child processes forked by LyX.");
58         tooltips().init(dialog_->browser_children, str);
59
60         str = _("A list of all child processes to kill.");
61         tooltips().init(dialog_->browser_kill, str);
62
63         str = _("Add all processes to the list of processes to kill.");
64         tooltips().init(dialog_->button_all, str);
65
66         str = _("Add the currently selected child process to the list of processes to kill.");
67         tooltips().init(dialog_->button_add, str);
68
69         str = _("Remove the currently selected item from the list of processes to kill.");
70         tooltips().init(dialog_->button_remove, str);
71 }
72
73
74 void FormForks::update()
75 {
76         if (!form())
77                 return;
78
79         string const current_pid_str =
80                 getString(dialog_->browser_kill);
81         pid_t const current_pid = strToInt(current_pid_str);
82
83         vector<pid_t> pids = controller().getPIDs();
84
85         // No child processes.
86         if (pids.empty()) {
87                 if (fl_get_browser_maxline(dialog_->browser_kill) > 0)
88                         fl_clear_browser(dialog_->browser_kill);
89                 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
90                         fl_clear_browser(dialog_->browser_children);
91
92                 setEnabled(dialog_->browser_children, false);
93                 setEnabled(dialog_->browser_kill,     false);
94                 setEnabled(dialog_->button_all,       false);
95                 setEnabled(dialog_->button_add,       false);
96                 setEnabled(dialog_->button_remove,    false);
97
98                 return;
99         }
100
101         // Remove any processes from the kill browser that aren't in the
102         // vector of existing PIDs.
103         for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_kill);
104              ++i) {
105                 string const pid_str =
106                         getString(dialog_->browser_kill, i);
107                 pid_t const pid = strToInt(pid_str);
108                 vector<pid_t>::const_iterator it =
109                         find(pids.begin(), pids.end(), pid);
110                 if (it == pids.end())
111                         fl_delete_browser_line(dialog_->browser_kill, i);
112         }
113
114         // Build the children browser from scratch.
115         if (fl_get_browser_maxline(dialog_->browser_children) > 0)
116                 fl_clear_browser(dialog_->browser_children);
117         int i = 1;
118         for (vector<pid_t>::const_iterator it = pids.begin();
119              it != pids.end(); ++it) {
120                 string const pid_str = tostr(*it);
121                 string const command = controller().getCommand(*it);
122                 string const line = pid_str + '\t' + command;
123
124                 fl_add_browser_line(dialog_->browser_children, line.c_str());
125
126                 if (*it == current_pid)
127                         fl_select_browser_line(dialog_->browser_children, i);
128                 ++i;
129         }
130
131         setEnabled(dialog_->browser_children, true);
132         setEnabled(dialog_->button_all,       true);
133         setEnabled(dialog_->button_add,       true);
134 }
135
136
137 void FormForks::apply()
138 {
139         // Get the list of all processes to kill.
140         vector<string> const kill_vec =
141                 getVector(dialog_->browser_kill);
142
143         if (kill_vec.empty())
144                 return;
145
146         // Remove these items from the vector of child processes.
147         for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_children);
148              ++i) {
149                 string const selection =
150                         getString(dialog_->browser_children, i);
151                 string pid_str;
152                 split(selection, pid_str, '\t');
153
154                 vector<string>::const_iterator it =
155                         find(kill_vec.begin(), kill_vec.end(), pid_str);
156
157                 if (it != kill_vec.end())
158                         fl_delete_browser_line(dialog_->browser_children, i);
159         }
160
161         // Clear the kill browser and deactivate appropriately.
162         fl_clear_browser(dialog_->browser_kill);
163         setEnabled(dialog_->browser_kill,  false);
164         setEnabled(dialog_->button_remove, false);
165
166         // Pass these pids to the controller for destruction.
167         for (vector<string>::const_iterator it = kill_vec.begin();
168              it != kill_vec.end(); ++it) {
169                 pid_t const pid = strToInt(*it);
170                 controller().kill(pid);
171         }
172
173 }
174
175
176 ButtonPolicy::SMInput FormForks::input(FL_OBJECT * ob, long)
177 {
178         ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
179
180         if (ob == dialog_->browser_children) {
181                 activate = input_browser_children();
182
183         } else if (ob == dialog_->browser_kill) {
184                 activate = input_browser_kill();
185
186         } else if (ob == dialog_->button_all) {
187                 activate = input_button_all();
188
189         } else if (ob == dialog_->button_add) {
190                 activate = input_button_add();
191
192         } else if (ob == dialog_->button_remove) {
193                 activate = input_button_remove();
194         }
195
196         return activate;
197 }
198
199 ButtonPolicy::SMInput FormForks::input_browser_children()
200 {
201         // Selected an item in the browser containing a list of all child
202         // processes.
203
204         // 1. Highlight this item in the browser of processes to kill
205         //    if it is already there.
206
207         // 2. If it is there, enable the remove button so that it can
208         //    be removed from this list, if so desired.
209
210         // 3. If it isn't there, activate the add button so that it can
211         //    be added to this list if so desired.
212
213         string const selection =
214                 getString(dialog_->browser_children);
215         string pid_str;
216         split(selection, pid_str, '\t');
217
218         vector<string> const kill_vec =
219                 getVector(dialog_->browser_kill);
220
221         vector<string>::const_iterator it =
222                 find(kill_vec.begin(), kill_vec.end(), pid_str);
223
224         fl_deselect_browser(dialog_->browser_kill);
225         if (it != kill_vec.end()) {
226                 int const n = int(it - kill_vec.begin());
227                 fl_select_browser_line(dialog_->browser_kill, n+1);
228                 fl_set_browser_topline(dialog_->browser_kill, n+1);
229         }
230
231         setEnabled(dialog_->button_remove, it != kill_vec.end());
232         setEnabled(dialog_->button_add,    it == kill_vec.end());
233
234         return ButtonPolicy::SMI_NOOP;
235 }
236
237
238 namespace {
239
240 class FindPID {
241 public:
242         FindPID(string const & pid) : pid_(pid) {}
243         bool operator()(string const & line)
244         {
245                 if (line.empty())
246                         return false;
247
248                 string pid_str;
249                 split(line, pid_str, '\t');
250                 return pid_str == pid_;
251         }
252
253 private:
254         string pid_;
255 };
256
257 } // namespace anon
258
259
260 ButtonPolicy::SMInput FormForks::input_browser_kill()
261 {
262         // Selected an item in the browser containing a list of processes
263         // to kill.
264
265         // 1. Highlight this item in the browser of all child processes.
266
267         // 2. Enable the remove button so that it can removed from this list,
268         //    if so desired.
269
270         // 3. Disable the add button.
271
272         string const pid_str =
273                 getString(dialog_->browser_kill);
274
275         // Find this string in the list of all child processes
276         vector<string> const child_vec =
277                 getVector(dialog_->browser_children);
278
279         vector<string>::const_iterator it =
280                 find_if(child_vec.begin(), child_vec.end(), FindPID(pid_str));
281
282         fl_deselect_browser(dialog_->browser_children);
283         if (it != child_vec.end()) {
284                 int const n = int(it - child_vec.begin());
285                 fl_select_browser_line(dialog_->browser_children, n+1);
286                 fl_set_browser_topline(dialog_->browser_children, n+1);
287         }
288
289         setEnabled(dialog_->button_remove, true);
290         setEnabled(dialog_->button_add,    false);
291
292         return ButtonPolicy::SMI_NOOP;
293 }
294
295
296 namespace {
297
298 vector<string> const getPIDvector(FL_OBJECT * ob)
299 {
300         vector<string> vec = getVector(ob);
301         if (vec.empty())
302                 return vec;
303
304         for (vector<string>::iterator it = vec.begin(); it != vec.end(); ++it) {
305                 string pid_str;
306                 split(*it, pid_str, '\t');
307                 *it = pid_str;
308         }
309
310         return vec;
311 }
312
313 } // namespace anon
314
315
316 ButtonPolicy::SMInput FormForks::input_button_all()
317 {
318         // Pressed the "All" button.
319
320         // 1. Check that the browser of processes to kill doesn't already
321         //    contain the entire list.
322
323         // 2. If it doesn't, copy the PIDs of all child processes into the
324         //    browser of processes to kill.
325
326         // 3. Deactivate the "children" browser and the "add" and "all" buttons
327
328         // 4. Activate the "kill" browser and the "remove" button"
329
330         ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
331
332         vector<string> const pid_vec = getPIDvector(dialog_->browser_children);
333
334         // to resolve a warning about comparison between signed and unsigned.
335         int const pid_vec_size = int(pid_vec.size());
336
337         if (fl_get_browser_maxline(dialog_->browser_kill) != pid_vec_size) {
338                 activate = ButtonPolicy::SMI_VALID;
339
340                 fl_clear_browser(dialog_->browser_kill);
341                 for (vector<string>::const_iterator it = pid_vec.begin();
342                      it != pid_vec.end(); ++it) {
343                         fl_add_browser_line(dialog_->browser_kill, it->c_str());
344                 }
345
346                 if (fl_get_browser_maxline(dialog_->browser_kill) >= 1)
347                         fl_set_browser_topline(dialog_->browser_kill, 1);
348         }
349
350         setEnabled(dialog_->browser_children, false);
351         setEnabled(dialog_->button_add,       false);
352         setEnabled(dialog_->button_all,       false);
353         setEnabled(dialog_->browser_kill,     true);
354         setEnabled(dialog_->button_remove,    true);
355
356         return activate;
357 }
358
359
360 ButtonPolicy::SMInput FormForks::input_button_add()
361 {
362         // Pressed the "Add" button.
363
364         // 1. Copy the PID of the selected item in the browser of all child
365         //    processes over into the browser of processes to kill.
366
367         // 2. Activate the "kill" browser and the "remove" button.
368
369         // 3. Deactivate the "add" button.
370
371         string const selection = getString(dialog_->browser_children);
372         string pid_str;
373         split(selection, pid_str, '\t');
374
375         vector<string> const kill_vec =
376                 getVector(dialog_->browser_kill);
377
378         vector<string>::const_iterator it =
379                 find(kill_vec.begin(), kill_vec.end(), pid_str);
380
381         if (it == kill_vec.end()) {
382                 fl_add_browser_line(dialog_->browser_kill, pid_str.c_str());
383                 int const n = fl_get_browser_maxline(dialog_->browser_kill);
384                 fl_select_browser_line(dialog_->browser_kill, n);
385         }
386
387         setEnabled(dialog_->browser_kill,  true);
388         setEnabled(dialog_->button_remove, true);
389         setEnabled(dialog_->button_add,    false);
390
391         return ButtonPolicy::SMI_VALID;
392 }
393
394
395 ButtonPolicy::SMInput FormForks::input_button_remove()
396 {
397         // Pressed the "Remove" button.
398
399         // 1. Remove the selected item in the browser of processes to kill.
400
401         // 2. Activate the "add" button and "all" buttons.
402
403         // 3. Deactivate the "remove" button.
404
405         int const sel = fl_get_browser(dialog_->browser_kill);
406         fl_delete_browser_line(dialog_->browser_kill, sel);
407
408         setEnabled(dialog_->button_add,    true);
409         setEnabled(dialog_->button_all,    true);
410         setEnabled(dialog_->button_remove, false);
411
412         return ButtonPolicy::SMI_VALID;
413 }