Exciting new Alt/h help key provided by sge (Georgy) with many thanks!
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / shbtnprefs.C
1 #include "bcwindowbase.h"
2 #include "bcdisplayinfo.h"
3 #include "bcdialog.h"
4 #include "awindow.h"
5 #include "awindowgui.h"
6 #include "cstrdup.h"
7 #include "indexable.h"
8 #include "language.h"
9 #include "mainerror.h"
10 #include "mainsession.h"
11 #include "mwindow.h"
12 #include "shbtnprefs.h"
13 #include "preferences.h"
14 #include "preferencesthread.h"
15 #include "theme.h"
16
17 #include <sys/wait.h>
18
19 ShBtnRun::ShBtnRun(const char *nm, const char *cmds, int warn)
20  : Thread(0, 0, 1)
21 {
22         argv.set_array_delete();
23         strncpy(name, nm, sizeof(name)-1);
24         name[sizeof(name)-1] = 0;
25         strncpy(commands, cmds, sizeof(commands)-1);
26         commands[sizeof(commands)-1] = 0;
27         this->warn = warn;
28 }
29 ShBtnRun::~ShBtnRun()
30 {
31         argv.remove_all_objects();
32 }
33
34 void ShBtnRun::add_arg(const char *v)
35 {
36         argv.append(cstrdup(v));
37 }
38
39 void ShBtnRun::run()
40 {
41         pid_t pid = vfork();
42         if( pid < 0 ) {
43                 perror("fork");
44                 return;
45         }
46         char msg[BCTEXTLEN];
47         if( !pid ) {
48                 argv.append(0);
49                 execvp(argv[0], &argv[0]);
50                 return;
51         }
52         // warn <0:always, =0:never, >0:on err
53         if( !warn ) return;
54         int stat;  waitpid(pid, &stat, 0);
55         if( !stat ) {
56                 if( warn > 0 ) return;
57                 sprintf(msg, "%s: completed", name);
58         }
59         else
60                 sprintf(msg, "%s: error exit status %d", name, stat);
61         MainError::show_error(msg);
62 }
63
64 ShBtnPref::ShBtnPref(const char *nm, const char *cmds, int warn, int run_script)
65 {
66         strncpy(name, nm, sizeof(name));
67         strncpy(commands, cmds, sizeof(commands));
68         this->warn = warn;
69         this->run_script = run_script;
70 }
71
72 ShBtnPref::~ShBtnPref()
73 {
74 }
75
76 void ShBtnPref::execute(ArrayList<Indexable*> &args)
77 {
78 // thread async+autodelete, no explicit delete
79         ShBtnRun *job = new ShBtnRun(name, commands, warn);
80         job->add_arg("/bin/bash");
81         job->add_arg(commands);
82         int n = args.size();
83         for( int i=0; i<n; ++i ) {
84                 Indexable *idxbl = args[i];
85                 if( !idxbl->is_asset ) continue;
86                 job->add_arg(idxbl->path);
87         }
88         job->start();
89 }
90
91 void ShBtnPref::execute()
92 {
93         ShBtnRun *job = new ShBtnRun(name, commands, warn);
94         job->add_arg("/bin/bash");
95         job->add_arg("-c");
96         job->add_arg(commands);
97         job->start();
98 }
99
100 ShBtnEditDialog::ShBtnEditDialog(PreferencesWindow *pwindow)
101  : BC_DialogThread()
102 {
103         this->pwindow = pwindow;
104 }
105
106 ShBtnEditDialog::~ShBtnEditDialog()
107 {
108         close_window();
109 }
110
111 BC_Window* ShBtnEditDialog::new_gui()
112 {
113         BC_DisplayInfo display_info;
114         int x = display_info.get_abs_cursor_x();
115         int y = display_info.get_abs_cursor_y();
116
117         sb_window = new ShBtnEditWindow(this, x, y);
118         sb_window->create_objects();
119         return sb_window;
120 }
121
122 void ShBtnEditDialog::handle_close_event(int result)
123 {
124         sb_window = 0;
125 }
126
127
128 ShBtnEditWindow::ShBtnEditWindow(ShBtnEditDialog *shbtn_edit, int x, int y)
129  : BC_Window(_(PROGRAM_NAME ": Shell"), x, y,
130                 xS(300), yS(200), xS(300), yS(200), 0, 0, 1)
131 {
132         this->shbtn_edit = shbtn_edit;
133         sb_dialog = 0;
134 // *** CONTEXT_HELP ***
135         context_help_set_keyword("Menu Bar Shell Commands");
136 }
137
138 ShBtnEditWindow::~ShBtnEditWindow()
139 {
140         delete sb_dialog;
141 }
142
143 int ShBtnEditWindow::list_update()
144 {
145         shbtn_items.remove_all_objects();
146         Preferences *preferences = shbtn_edit->pwindow->thread->preferences;
147         for( int i=0; i<preferences->shbtn_prefs.size(); ++i ) {
148                 shbtn_items.append(new ShBtnPrefItem(preferences->shbtn_prefs[i]));
149         }
150         return op_list->update(&shbtn_items, 0, 0, 1);
151 }
152
153 ShBtnAddButton::ShBtnAddButton(ShBtnEditWindow *sb_window, int x, int y)
154  : BC_GenericButton(x, y, _("Add"))
155 {
156         this->sb_window = sb_window;
157 }
158
159 ShBtnAddButton::~ShBtnAddButton()
160 {
161 }
162
163 int ShBtnAddButton::handle_event()
164 {
165
166         Preferences *preferences = sb_window->shbtn_edit->pwindow->thread->preferences;
167         ShBtnPref *pref = new ShBtnPref(_("new"), "", 0, 0);
168         preferences->shbtn_prefs.append(pref);
169         sb_window->list_update();
170         return sb_window->start_edit(pref);
171 }
172
173 ShBtnDelButton::ShBtnDelButton(ShBtnEditWindow *sb_window, int x, int y)
174  : BC_GenericButton(x, y, _("Del"))
175 {
176         this->sb_window = sb_window;
177 }
178
179 ShBtnDelButton::~ShBtnDelButton()
180 {
181 }
182
183 int ShBtnDelButton::handle_event()
184 {
185         ShBtnPrefItem *sp = (ShBtnPrefItem *)sb_window->op_list->get_selection(0,0);
186         if( !sp ) return 0;
187         Preferences *preferences = sb_window->shbtn_edit->pwindow->thread->preferences;
188         preferences->shbtn_prefs.remove(sp->pref);
189         sb_window->list_update();
190         return 1;
191 }
192
193 ShBtnEditButton::ShBtnEditButton(ShBtnEditWindow *sb_window, int x, int y)
194  : BC_GenericButton(x, y, _("Edit"))
195 {
196         this->sb_window = sb_window;
197 }
198
199 ShBtnEditButton::~ShBtnEditButton()
200 {
201 }
202
203 int ShBtnEditButton::handle_event()
204 {
205         ShBtnPrefItem *sp = (ShBtnPrefItem *)sb_window->op_list->get_selection(0,0);
206         if( !sp ) return 0;
207         return sb_window->start_edit(sp->pref);
208 }
209
210 ShBtnTextDialog::ShBtnTextDialog(ShBtnEditWindow *sb_window)
211  : BC_DialogThread()
212 {
213         this->sb_window = sb_window;
214         this->pref = 0;
215 }
216
217 ShBtnTextDialog::~ShBtnTextDialog()
218 {
219         close_window();
220 }
221
222 ShBtnTextWindow::ShBtnTextWindow(ShBtnEditWindow *sb_window, int x, int y)
223  : BC_Window(_(PROGRAM_NAME ": Commands"), x, y,
224                 xS(640), yS(160), xS(640), yS(150), 0, 0, 1)
225 {
226         this->sb_window = sb_window;
227         warn = sb_window->sb_dialog->pref->warn;
228         run_script = sb_window->sb_dialog->pref->run_script;
229 // *** CONTEXT_HELP ***
230         context_help_set_keyword("Menu Bar Shell Commands");
231 }
232
233 ShBtnTextWindow::~ShBtnTextWindow()
234 {
235 }
236
237
238 ShBtnErrWarnItem::ShBtnErrWarnItem(ShBtnErrWarn *popup,
239                 const char *text, int warn)
240  : BC_MenuItem(text)
241 {
242         this->popup = popup;
243         this->warn = warn;
244 }
245
246 int ShBtnErrWarnItem::handle_event()
247 {
248         popup->set_text(get_text());
249         popup->st_window->warn = warn;
250         return 1;
251 }
252
253 ShBtnErrWarn::ShBtnErrWarn(ShBtnTextWindow *st_window, int x, int y)
254  : BC_PopupMenu(x, y, xS(120), st_window->warn < 0 ? _("Always"):
255         !st_window->warn ? _("Never") : _("On Error"))
256 {
257         this->st_window = st_window;
258 }
259 ShBtnErrWarn::~ShBtnErrWarn()
260 {
261 }
262 int ShBtnErrWarn::handle_event()
263 {
264         return 0;
265 }
266
267 void ShBtnErrWarn::create_objects()
268 {
269         add_item(new ShBtnErrWarnItem(this,_("Always"), -1));
270         add_item(new ShBtnErrWarnItem(this,_("Never"), 0));
271         add_item(new ShBtnErrWarnItem(this,_("On Error"), 1));
272 }
273
274
275 ShBtnRunScript::ShBtnRunScript(ShBtnTextWindow *st_window, int x, int y)
276  : BC_CheckBox(x, y, &st_window->run_script, _("run /path/script.sh + argvs"))
277 {
278         this->st_window = st_window;
279 }
280
281 ShBtnRunScript::~ShBtnRunScript()
282 {
283 }
284
285 void ShBtnTextWindow::create_objects()
286 {
287         lock_window("ShBtnTextWindow::create_objects");
288         int x = xS(10), y = yS(10);
289         int x1 = xS(160);
290         BC_Title *title = new BC_Title(x, y, _("Label:"));
291         add_subwindow(title);
292         title = new BC_Title(x1, y, _("Commands:"));
293         add_subwindow(title);
294         y += title->get_h() + yS(8);
295         ShBtnPref *pref = sb_window->sb_dialog->pref;
296         cmd_name = new BC_TextBox(x, y, xS(140), 1, pref->name);
297         add_subwindow(cmd_name);
298         cmd_text = new BC_ScrollTextBox(this, x1, y, get_w()-x1-xS(20), 4, pref->commands);
299         cmd_text->create_objects();
300         y += cmd_text->get_h() + yS(16);
301         add_subwindow(title = new BC_Title(x1,y, _("OnExit Notify:")));
302         x1 += title->get_w() + xS(10);
303         add_subwindow(st_err_warn = new ShBtnErrWarn(this, x1, y));
304         st_err_warn->create_objects();
305         x1 += st_err_warn->get_w() + xS(20);
306         add_subwindow(st_run_script = new ShBtnRunScript(this, x1, y));
307         y = get_h() - ShBtnTextOK::calculate_h() - yS(10);
308         add_subwindow(new ShBtnTextOK(this, x, y));
309         show_window();
310         unlock_window();
311 }
312
313 ShBtnTextOK::ShBtnTextOK(ShBtnTextWindow *st_window, int x, int y)
314  : BC_OKButton(x, y)
315 {
316         this->st_window = st_window;
317 }
318
319 ShBtnTextOK::~ShBtnTextOK()
320 {
321 }
322
323 int ShBtnTextOK::handle_event()
324 {
325         ShBtnPref *pref = st_window->sb_window->sb_dialog->pref;
326         strcpy(pref->name, st_window->cmd_name->get_text());
327         strcpy(pref->commands, st_window->cmd_text->get_text());
328         pref->warn = st_window->warn;
329         pref->run_script = st_window->run_script;
330         return BC_OKButton::handle_event();
331 }
332
333
334 BC_Window *ShBtnTextDialog::new_gui()
335 {
336         BC_DisplayInfo display_info;
337         int x = display_info.get_abs_cursor_x();
338         int y = display_info.get_abs_cursor_y();
339
340         st_window = new ShBtnTextWindow(sb_window, x, y);
341         st_window->create_objects();
342         return st_window;
343 }
344
345 void ShBtnTextDialog::handle_close_event(int result)
346 {
347         if( !result ) {
348                 sb_window->lock_window("ShBtnTextDialog::handle_close_event");
349                 sb_window->list_update();
350                 sb_window->unlock_window();
351         }
352         st_window = 0;
353 }
354
355 int ShBtnTextDialog::start_edit(ShBtnPref *pref)
356 {
357         this->pref = pref;
358         start();
359         return 1;
360 }
361
362 void ShBtnEditWindow::create_objects()
363 {
364         lock_window("ShBtnEditWindow::create_objects");
365         Preferences *preferences = shbtn_edit->pwindow->thread->preferences;
366         for( int i=0; i<preferences->shbtn_prefs.size(); ++i ) {
367                 shbtn_items.append(new ShBtnPrefItem(preferences->shbtn_prefs[i]));
368         }
369         int x = xS(10), y = yS(10);
370         add_subwindow(op_list = new ShBtnPrefList(this, x, y));
371         x = xS(190);
372         add_subwindow(add_button = new ShBtnAddButton(this, x, y));
373         y += add_button->get_h() + yS(8);
374         add_subwindow(del_button = new ShBtnDelButton(this, x, y));
375         y += del_button->get_h() + yS(8);
376         add_subwindow(edit_button = new ShBtnEditButton(this, x, y));
377         add_subwindow(new BC_OKButton(this));
378         show_window();
379         unlock_window();
380 }
381
382 int ShBtnEditWindow::start_edit(ShBtnPref *pref)
383 {
384         if( !sb_dialog )
385                 sb_dialog = new ShBtnTextDialog(this);
386         return sb_dialog->start_edit(pref);
387 }
388
389
390 ShBtnPrefItem::ShBtnPrefItem(ShBtnPref *pref)
391  : BC_ListBoxItem(pref->name)
392 {
393         this->pref = pref;
394 }
395
396 ShBtnPrefItem::~ShBtnPrefItem()
397 {
398 }
399
400 ShBtnPrefList::ShBtnPrefList(ShBtnEditWindow *sb_window, int x, int y)
401  : BC_ListBox(x, y, xS(140), yS(100), LISTBOX_TEXT, &sb_window->shbtn_items, 0, 0)
402 {
403         this->sb_window = sb_window;
404 }
405
406 ShBtnPrefList::~ShBtnPrefList()
407 {
408 }
409
410 int ShBtnPrefList::handle_event()
411 {
412         return 1;
413 }
414
415 MainShBtnItem::MainShBtnItem(MainShBtns *shbtns, ShBtnPref *pref)
416  : BC_MenuItem(pref->name)
417 {
418         this->shbtns = shbtns;
419         this->pref = pref;
420 }
421
422 int MainShBtnItem::handle_event()
423 {
424         MWindow *mwindow = shbtns->mwindow;
425         if( pref->run_script ) {
426                 AWindowGUI *agui = mwindow->awindow->gui;
427                 agui->lock_window("MainShBtnItem::handle_event");
428                 mwindow->awindow->gui->collect_assets();
429                 pref->execute(*mwindow->session->drag_assets);
430                 agui->unlock_window();
431         }
432         else
433                 pref->execute();
434         return 1;
435 }
436
437 MainShBtns::MainShBtns(MWindow *mwindow, int x, int y)
438  : BC_PopupMenu(x, y, 0, "", -1, mwindow->theme->shbtn_data)
439 {
440         this->mwindow = mwindow;
441         set_tooltip(_("shell cmds"));
442 // *** CONTEXT_HELP ***
443         context_help_set_keyword("Menu Bar Shell Commands");
444 }
445
446 int MainShBtns::load(Preferences *preferences)
447 {
448         while( total_items() ) del_item(0);
449         for( int i=0; i<preferences->shbtn_prefs.size(); ++i )
450                 add_item(new MainShBtnItem(this, preferences->shbtn_prefs[i]));
451         return 0;
452 }
453
454 int MainShBtns::handle_event()
455 {
456         return 1;
457 }
458