3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
8 * Full author contact details are available in file CREDITS
16 #include "ButtonController.h"
17 #include "FormForks.h"
18 #include "ControlForks.h"
19 #include "forms/form_forks.h"
21 #include "helper_funcs.h"
22 #include "xforms_helpers.h"
24 #include "support/lstrings.h"
25 #include FORMS_H_LOCATION
31 typedef FormCB<ControlForks, FormDB<FD_forks> > base_class;
33 FormForks::FormForks()
34 : base_class(_("Child processes"))
38 void FormForks::build() {
39 dialog_.reset(build_forks(this));
41 // It appears that the browsers aren't initialised properly.
42 // This fudge fixes tings.
43 fl_add_browser_line(dialog_->browser_children, " ");
44 fl_add_browser_line(dialog_->browser_kill, " ");
45 fl_clear_browser(dialog_->browser_children);
46 fl_clear_browser(dialog_->browser_kill);
48 // Manage the ok, apply, restore and cancel/close buttons
49 bcview().setOK(dialog_->button_ok);
50 bcview().setApply(dialog_->button_apply);
51 bcview().setCancel(dialog_->button_close);
54 // Set up the tooltip mechanism
55 string str = _("All currently running child processes forked by LyX.");
56 tooltips().init(dialog_->browser_children, str);
57 // Work-around xforms' bug; enable tooltips for browser widgets.
58 setPrehandler(dialog_->browser_children);
60 str = _("A list of all child processes to kill.");
61 tooltips().init(dialog_->browser_kill, str);
62 // Work-around xforms' bug; enable tooltips for browser widgets.
63 setPrehandler(dialog_->browser_kill);
65 str = _("Add all processes to the list of processes to kill.");
66 tooltips().init(dialog_->button_all, str);
68 str = _("Add the currently selected child process to the list of processes to kill.");
69 tooltips().init(dialog_->button_add, str);
71 str = _("Remove the currently selected item from the list of processes to kill.");
72 tooltips().init(dialog_->button_remove, str);
76 void FormForks::update()
81 string const current_pid_str =
82 getString(dialog_->browser_kill);
83 pid_t const current_pid = strToInt(current_pid_str);
85 vector<pid_t> pids = controller().getPIDs();
87 // No child processes.
89 if (fl_get_browser_maxline(dialog_->browser_kill) > 0)
90 fl_clear_browser(dialog_->browser_kill);
91 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
92 fl_clear_browser(dialog_->browser_children);
94 setEnabled(dialog_->browser_children, false);
95 setEnabled(dialog_->browser_kill, false);
96 setEnabled(dialog_->button_all, false);
97 setEnabled(dialog_->button_add, false);
98 setEnabled(dialog_->button_remove, false);
103 // Remove any processes from the kill browser that aren't in the
104 // vector of existing PIDs.
105 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_kill);
107 string const pid_str =
108 getString(dialog_->browser_kill, i);
109 pid_t const pid = strToInt(pid_str);
110 vector<pid_t>::const_iterator it =
111 find(pids.begin(), pids.end(), pid);
112 if (it == pids.end())
113 fl_delete_browser_line(dialog_->browser_kill, i);
116 // Build the children browser from scratch.
117 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
118 fl_clear_browser(dialog_->browser_children);
120 for (vector<pid_t>::const_iterator it = pids.begin();
121 it != pids.end(); ++it) {
122 string const pid_str = tostr(*it);
123 string const command = controller().getCommand(*it);
124 string const line = pid_str + '\t' + command;
126 fl_add_browser_line(dialog_->browser_children, line.c_str());
128 if (*it == current_pid)
129 fl_select_browser_line(dialog_->browser_children, i);
133 setEnabled(dialog_->browser_children, true);
134 setEnabled(dialog_->button_all, true);
135 setEnabled(dialog_->button_add, true);
139 void FormForks::apply()
141 // Get the list of all processes to kill.
142 vector<string> const kill_vec =
143 getVector(dialog_->browser_kill);
145 if (kill_vec.empty())
148 // Remove these items from the vector of child processes.
149 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_children);
151 string const selection =
152 getString(dialog_->browser_children, i);
154 split(selection, pid_str, '\t');
156 vector<string>::const_iterator it =
157 find(kill_vec.begin(), kill_vec.end(), pid_str);
159 if (it != kill_vec.end())
160 fl_delete_browser_line(dialog_->browser_children, i);
163 // Clear the kill browser and deactivate appropriately.
164 fl_clear_browser(dialog_->browser_kill);
165 setEnabled(dialog_->browser_kill, false);
166 setEnabled(dialog_->button_remove, false);
168 // Pass these pids to the controller for destruction.
169 for (vector<string>::const_iterator it = kill_vec.begin();
170 it != kill_vec.end(); ++it) {
171 pid_t const pid = strToInt(*it);
172 controller().kill(pid);
178 ButtonPolicy::SMInput FormForks::input(FL_OBJECT * ob, long)
180 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
182 if (ob == dialog_->browser_children) {
183 activate = input_browser_children();
185 } else if (ob == dialog_->browser_kill) {
186 activate = input_browser_kill();
188 } else if (ob == dialog_->button_all) {
189 activate = input_button_all();
191 } else if (ob == dialog_->button_add) {
192 activate = input_button_add();
194 } else if (ob == dialog_->button_remove) {
195 activate = input_button_remove();
201 ButtonPolicy::SMInput FormForks::input_browser_children()
203 // Selected an item in the browser containing a list of all child
206 // 1. Highlight this item in the browser of processes to kill
207 // if it is already there.
209 // 2. If it is there, enable the remove button so that it can
210 // be removed from this list, if so desired.
212 // 3. If it isn't there, activate the add button so that it can
213 // be added to this list if so desired.
215 string const selection =
216 getString(dialog_->browser_children);
218 split(selection, pid_str, '\t');
220 vector<string> const kill_vec =
221 getVector(dialog_->browser_kill);
223 vector<string>::const_iterator it =
224 find(kill_vec.begin(), kill_vec.end(), pid_str);
226 fl_deselect_browser(dialog_->browser_kill);
227 if (it != kill_vec.end()) {
228 int const n = int(it - kill_vec.begin());
229 fl_select_browser_line(dialog_->browser_kill, n+1);
230 fl_set_browser_topline(dialog_->browser_kill, n+1);
233 setEnabled(dialog_->button_remove, it != kill_vec.end());
234 setEnabled(dialog_->button_add, it == kill_vec.end());
236 return ButtonPolicy::SMI_NOOP;
244 FindPID(string const & pid) : pid_(pid) {}
245 bool operator()(string const & line)
251 split(line, pid_str, '\t');
252 return pid_str == pid_;
262 ButtonPolicy::SMInput FormForks::input_browser_kill()
264 // Selected an item in the browser containing a list of processes
267 // 1. Highlight this item in the browser of all child processes.
269 // 2. Enable the remove button so that it can removed from this list,
272 // 3. Disable the add button.
274 string const pid_str =
275 getString(dialog_->browser_kill);
277 // Find this string in the list of all child processes
278 vector<string> const child_vec =
279 getVector(dialog_->browser_children);
281 vector<string>::const_iterator it =
282 find_if(child_vec.begin(), child_vec.end(), FindPID(pid_str));
284 fl_deselect_browser(dialog_->browser_children);
285 if (it != child_vec.end()) {
286 int const n = int(it - child_vec.begin());
287 fl_select_browser_line(dialog_->browser_children, n+1);
288 fl_set_browser_topline(dialog_->browser_children, n+1);
291 setEnabled(dialog_->button_remove, true);
292 setEnabled(dialog_->button_add, false);
294 return ButtonPolicy::SMI_NOOP;
300 vector<string> const getPIDvector(FL_OBJECT * ob)
302 vector<string> vec = getVector(ob);
306 for (vector<string>::iterator it = vec.begin(); it != vec.end(); ++it) {
308 split(*it, pid_str, '\t');
318 ButtonPolicy::SMInput FormForks::input_button_all()
320 // Pressed the "All" button.
322 // 1. Check that the browser of processes to kill doesn't already
323 // contain the entire list.
325 // 2. If it doesn't, copy the PIDs of all child processes into the
326 // browser of processes to kill.
328 // 3. Deactivate the "children" browser and the "add" and "all" buttons
330 // 4. Activate the "kill" browser and the "remove" button"
332 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
334 vector<string> const pid_vec = getPIDvector(dialog_->browser_children);
336 // to resolve a warning about comparison between signed and unsigned.
337 int const pid_vec_size = int(pid_vec.size());
339 if (fl_get_browser_maxline(dialog_->browser_kill) != pid_vec_size) {
340 activate = ButtonPolicy::SMI_VALID;
342 fl_clear_browser(dialog_->browser_kill);
343 for (vector<string>::const_iterator it = pid_vec.begin();
344 it != pid_vec.end(); ++it) {
345 fl_add_browser_line(dialog_->browser_kill, it->c_str());
348 if (fl_get_browser_maxline(dialog_->browser_kill) >= 1)
349 fl_set_browser_topline(dialog_->browser_kill, 1);
352 setEnabled(dialog_->browser_children, false);
353 setEnabled(dialog_->button_add, false);
354 setEnabled(dialog_->button_all, false);
355 setEnabled(dialog_->browser_kill, true);
356 setEnabled(dialog_->button_remove, true);
362 ButtonPolicy::SMInput FormForks::input_button_add()
364 // Pressed the "Add" button.
366 // 1. Copy the PID of the selected item in the browser of all child
367 // processes over into the browser of processes to kill.
369 // 2. Activate the "kill" browser and the "remove" button.
371 // 3. Deactivate the "add" button.
373 string const selection = getString(dialog_->browser_children);
375 split(selection, pid_str, '\t');
377 vector<string> const kill_vec =
378 getVector(dialog_->browser_kill);
380 vector<string>::const_iterator it =
381 find(kill_vec.begin(), kill_vec.end(), pid_str);
383 if (it == kill_vec.end()) {
384 fl_add_browser_line(dialog_->browser_kill, pid_str.c_str());
385 int const n = fl_get_browser_maxline(dialog_->browser_kill);
386 fl_select_browser_line(dialog_->browser_kill, n);
389 setEnabled(dialog_->browser_kill, true);
390 setEnabled(dialog_->button_remove, true);
391 setEnabled(dialog_->button_add, false);
393 return ButtonPolicy::SMI_VALID;
397 ButtonPolicy::SMInput FormForks::input_button_remove()
399 // Pressed the "Remove" button.
401 // 1. Remove the selected item in the browser of processes to kill.
403 // 2. Activate the "add" button and "all" buttons.
405 // 3. Deactivate the "remove" button.
407 int const sel = fl_get_browser(dialog_->browser_kill);
408 fl_delete_browser_line(dialog_->browser_kill, sel);
410 setEnabled(dialog_->button_add, true);
411 setEnabled(dialog_->button_all, true);
412 setEnabled(dialog_->button_remove, false);
414 return ButtonPolicy::SMI_VALID;