3 * Copyright 2001 the LyX Team
4 * Read the file COPYING
6 * \author Angus Leeming
13 #pragma implementation
17 #include "FormForks.h"
18 #include "ControlForks.h"
19 #include "form_forks.h"
21 #include "helper_funcs.h"
22 #include "xforms_helpers.h"
23 #include "support/lstrings.h"
29 typedef FormCB<ControlForks, FormDB<FD_form_forks> > base_class;
31 FormForks::FormForks(ControlForks & c)
32 : base_class(c, _("Child processes"))
36 void FormForks::build() {
37 dialog_.reset(build_forks());
39 // It appears that the browsers aren't initialised properly.
40 // This fudge fixes tings.
41 fl_add_browser_line(dialog_->browser_children, " ");
42 fl_add_browser_line(dialog_->browser_kill, " ");
43 fl_clear_browser(dialog_->browser_children);
44 fl_clear_browser(dialog_->browser_kill);
46 // Manage the ok, apply, restore and cancel/close buttons
47 bc().setOK(dialog_->button_ok);
48 bc().setApply(dialog_->button_apply);
49 bc().setCancel(dialog_->button_close);
52 // Set up the tooltip mechanism
53 setTooltipHandler(dialog_->browser_children);
54 setTooltipHandler(dialog_->browser_kill);
55 setTooltipHandler(dialog_->button_all);
56 setTooltipHandler(dialog_->button_add);
57 setTooltipHandler(dialog_->button_remove);
61 void FormForks::update()
66 string const current_pid_str =
67 getSelectedStringFromBrowser(dialog_->browser_kill);
68 pid_t const current_pid = strToInt(current_pid_str);
70 vector<pid_t> pids = controller().getPIDs();
72 // No child processes.
74 if (fl_get_browser_maxline(dialog_->browser_kill) > 0)
75 fl_clear_browser(dialog_->browser_kill);
76 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
77 fl_clear_browser(dialog_->browser_children);
79 setEnabled(dialog_->browser_children, false);
80 setEnabled(dialog_->browser_kill, false);
81 setEnabled(dialog_->button_all, false);
82 setEnabled(dialog_->button_add, false);
83 setEnabled(dialog_->button_remove, false);
88 // Remove any processes from the kill browser that aren't in the
89 // vector of existing PIDs.
90 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_kill);
92 string const pid_str =
93 getStringFromBrowser(dialog_->browser_kill, i);
94 pid_t const pid = strToInt(pid_str);
95 vector<pid_t>::const_iterator it =
96 find(pids.begin(), pids.end(), pid);
98 fl_delete_browser_line(dialog_->browser_kill, i);
101 // Build the children browser from scratch.
102 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
103 fl_clear_browser(dialog_->browser_children);
105 for (vector<pid_t>::const_iterator it = pids.begin();
106 it != pids.end(); ++it) {
107 string const pid_str = tostr(*it);
108 string const command = controller().getCommand(*it);
109 string const line = pid_str + '\t' + command;
111 fl_add_browser_line(dialog_->browser_children, line.c_str());
113 if (*it == current_pid)
114 fl_select_browser_line(dialog_->browser_children, i);
118 setEnabled(dialog_->browser_children, true);
119 setEnabled(dialog_->button_all, true);
120 setEnabled(dialog_->button_add, true);
124 void FormForks::apply()
126 // Get the list of all processes to kill.
127 vector<string> const kill_vec =
128 getVectorFromBrowser(dialog_->browser_kill);
130 if (kill_vec.empty())
133 // Remove these items from the vector of child processes.
134 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_children);
136 string const selection =
137 getStringFromBrowser(dialog_->browser_children, i);
139 split(selection, pid_str, '\t');
141 vector<string>::const_iterator it =
142 find(kill_vec.begin(), kill_vec.end(), pid_str);
144 if (it != kill_vec.end())
145 fl_delete_browser_line(dialog_->browser_children, i);
148 // Clear the kill browser and deactivate appropriately.
149 fl_clear_browser(dialog_->browser_kill);
150 setEnabled(dialog_->browser_kill, false);
151 setEnabled(dialog_->button_remove, false);
153 // Pass these pids to the controller for destruction.
154 for (vector<string>::const_iterator it = kill_vec.begin();
155 it != kill_vec.end(); ++it) {
156 pid_t const pid = strToInt(*it);
157 controller().kill(pid);
163 ButtonPolicy::SMInput FormForks::input(FL_OBJECT * ob, long)
165 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
167 if (ob == dialog_->browser_children) {
168 activate = input_browser_children();
170 } else if (ob == dialog_->browser_kill) {
171 activate = input_browser_kill();
173 } else if (ob == dialog_->button_all) {
174 activate = input_button_all();
176 } else if (ob == dialog_->button_add) {
177 activate = input_button_add();
179 } else if (ob == dialog_->button_remove) {
180 activate = input_button_remove();
186 ButtonPolicy::SMInput FormForks::input_browser_children()
188 // Selected an item in the browser containing a list of all child
191 // 1. Highlight this item in the browser of processes to kill
192 // if it is already there.
194 // 2. If it is there, enable the remove button so that it can
195 // be removed from this list, if so desired.
197 // 3. If it isn't there, activate the add button so that it can
198 // be added to this list if so desired.
200 string const selection =
201 getSelectedStringFromBrowser(dialog_->browser_children);
203 split(selection, pid_str, '\t');
205 vector<string> const kill_vec =
206 getVectorFromBrowser(dialog_->browser_kill);
208 vector<string>::const_iterator it =
209 find(kill_vec.begin(), kill_vec.end(), pid_str);
211 fl_deselect_browser(dialog_->browser_kill);
212 if (it != kill_vec.end()) {
213 int const n = int(it - kill_vec.begin());
214 fl_select_browser_line(dialog_->browser_kill, n+1);
215 fl_set_browser_topline(dialog_->browser_kill, n+1);
218 setEnabled(dialog_->button_remove, it != kill_vec.end());
219 setEnabled(dialog_->button_add, it == kill_vec.end());
221 return ButtonPolicy::SMI_NOOP;
229 FindPID(string const & pid) : pid_(pid) {}
230 bool operator()(string const & line)
236 split(line, pid_str, '\t');
237 return pid_str == pid_;
247 ButtonPolicy::SMInput FormForks::input_browser_kill()
249 // Selected an item in the browser containing a list of processes
252 // 1. Highlight this item in the browser of all child processes.
254 // 2. Enable the remove button so that it can removed from this list,
257 // 3. Disable the add button.
259 string const pid_str =
260 getSelectedStringFromBrowser(dialog_->browser_kill);
262 // Find this string in the list of all child processes
263 vector<string> const child_vec =
264 getVectorFromBrowser(dialog_->browser_children);
266 vector<string>::const_iterator it =
267 find_if(child_vec.begin(), child_vec.end(), FindPID(pid_str));
269 fl_deselect_browser(dialog_->browser_children);
270 if (it != child_vec.end()) {
271 int const n = int(it - child_vec.begin());
272 fl_select_browser_line(dialog_->browser_children, n+1);
273 fl_set_browser_topline(dialog_->browser_children, n+1);
276 setEnabled(dialog_->button_remove, true);
277 setEnabled(dialog_->button_add, false);
279 return ButtonPolicy::SMI_NOOP;
285 vector<string> const getPIDvector(FL_OBJECT * ob)
287 vector<string> vec = getVectorFromBrowser(ob);
291 for (vector<string>::iterator it = vec.begin(); it != vec.end(); ++it) {
293 split(*it, pid_str, '\t');
303 ButtonPolicy::SMInput FormForks::input_button_all()
305 // Pressed the "All" button.
307 // 1. Check that the browser of processes to kill doesn't already
308 // contain the entire list.
310 // 2. If it doesn't, copy the PIDs of all child processes into the
311 // browser of processes to kill.
313 // 3. Deactivate the "children" browser and the "add" and "all" buttons
315 // 4. Activate the "kill" browser and the "remove" button"
317 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
319 vector<string> const pid_vec = getPIDvector(dialog_->browser_children);
320 if (fl_get_browser_maxline(dialog_->browser_kill) != pid_vec.size()) {
321 activate = ButtonPolicy::SMI_VALID;
323 fl_clear_browser(dialog_->browser_kill);
324 for (vector<string>::const_iterator it = pid_vec.begin();
325 it != pid_vec.end(); ++it) {
326 fl_add_browser_line(dialog_->browser_kill, it->c_str());
329 if (fl_get_browser_maxline(dialog_->browser_kill) >= 1)
330 fl_set_browser_topline(dialog_->browser_kill, 1);
333 setEnabled(dialog_->browser_children, false);
334 setEnabled(dialog_->button_add, false);
335 setEnabled(dialog_->button_all, false);
336 setEnabled(dialog_->browser_kill, true);
337 setEnabled(dialog_->button_remove, true);
343 ButtonPolicy::SMInput FormForks::input_button_add()
345 // Pressed the "Add" button.
347 // 1. Copy the PID of the selected item in the browser of all child
348 // processes over into the browser of processes to kill.
350 // 2. Activate the "kill" browser and the "remove" button.
352 // 3. Deactivate the "add" button.
354 string const selection =
355 getSelectedStringFromBrowser(dialog_->browser_children);
357 split(selection, pid_str, '\t');
359 vector<string> const kill_vec =
360 getVectorFromBrowser(dialog_->browser_kill);
362 vector<string>::const_iterator it =
363 find(kill_vec.begin(), kill_vec.end(), pid_str);
365 if (it == kill_vec.end()) {
366 fl_add_browser_line(dialog_->browser_kill, pid_str.c_str());
367 int const n = fl_get_browser_maxline(dialog_->browser_kill);
368 fl_select_browser_line(dialog_->browser_kill, n);
371 setEnabled(dialog_->browser_kill, true);
372 setEnabled(dialog_->button_remove, true);
373 setEnabled(dialog_->button_add, false);
375 return ButtonPolicy::SMI_VALID;
379 ButtonPolicy::SMInput FormForks::input_button_remove()
381 // Pressed the "Remove" button.
383 // 1. Remove the selected item in the browser of processes to kill.
385 // 2. Activate the "add" button and "all" buttons.
387 // 3. Deactivate the "remove" button.
389 int const sel = fl_get_browser(dialog_->browser_kill);
390 fl_delete_browser_line(dialog_->browser_kill, sel);
392 setEnabled(dialog_->button_add, true);
393 setEnabled(dialog_->button_all, true);
394 setEnabled(dialog_->button_remove, false);
396 return ButtonPolicy::SMI_VALID;
400 string const FormForks::getVerboseTooltip(FL_OBJECT const * ob) const
404 if (ob == dialog_->browser_children) {
405 str = _("All currently running child processes forked by LyX.");
406 } else if (ob == dialog_->browser_kill) {
407 str = _("A list of all child processes to kill.");
408 } else if (ob == dialog_->button_all) {
409 str = _("Add all processes to the list of processes to kill.");
410 } else if (ob == dialog_->button_add) {
411 str = _("Add the currently selected child process to the list of processes to kill.");
412 } else if (ob == dialog_->button_remove) {
413 str = _("Remove the currently selected item from the list of processes to kill.");