Heavy rewriting:

- notebook removed
 - combo for sessions
 - handling of conf.xml saving and backup
 - preferences saved in conf/%gconf.xml (A/C, target, session)
 - make handled as a process
This commit is contained in:
Pascal Brisset
2007-10-05 12:13:52 +00:00
parent 6371090ba2
commit 01d9bf9b55
6 changed files with 2307 additions and 2388 deletions
+7 -3
View File
@@ -15,21 +15,25 @@ paparazzicenter : $(PAPARAZZICENTERCMO) $(OCAMLLIB)/lib-pprz.cma
$(Q)$(OCAMLC) -custom $(INCLUDES) -o $@ unix.cma str.cma xml-light.cma lablgtk.cma lablglade.cma gtkInit.cmo lib-pprz.cma lablgnomeui.cma $^
gtk_pc.ml : paparazzicenter.glade
lablgladecc2 -root window $< > $@
lablgladecc2 -hide-default -root window $< > $@
gtk_process.ml : paparazzicenter.glade
lablgladecc2 -root hbox_program $< | grep -B 1000000 " end" > $@
lablgladecc2 -hide-default -root hbox_program $< | grep -B 1000000 " end" > $@
%.cmo : %.ml
@echo OC $<
$(Q)$(OCAMLC) $(INCLUDES) -c $<
%.cmi : %.mli
@echo OC $<
$(Q)$(OCAMLC) $(INCLUDES) $<
paparazzicenter.cmo : gtk_pc.cmo gtk_process.cmo pc_common.cmo pc_control_panel.cmo pc_aircraft.cmo
pc_control_panel.cmo pc_aircraft.cmo : pc_common.cmo
clean:
\rm *.cm* gtk_pc.ml gtk_process.ml
\rm *.cm* gtk_pc.ml gtk_process.ml .depend
#
# Dependencies
File diff suppressed because it is too large Load Diff
+136 -34
View File
@@ -25,15 +25,112 @@
*)
open Printf
open Pc_common
module Utils = Pc_common
module CP = Pc_control_panel
module AC = Pc_aircraft
let quit_page = 3 (* FIXME *)
let (//) = Filename.concat
let fullscreen = ref false
(*********************** Preferences handling **************************)
let get_entry_value = fun xml name ->
let e = ExtXml.child ~select:(fun x -> Xml.attrib x "name" = name) xml "entry" in
Xml.attrib e "value"
let read_preferences = fun file (ac_combo:Utils.combo) (session_combo:Utils.combo) (target_combo:Utils.combo) ->
let xml = Xml.parse_file file in
(*********** Last A/C *)
begin
try
let ac_name = get_entry_value xml "last A/C" in
Utils.select_in_combo ac_combo ac_name
with Not_found -> ()
end;
(*********** Last session *)
begin
try
let session_name = get_entry_value xml "last session" in
Utils.select_in_combo session_combo session_name
with Not_found -> ()
end;
(*********** Last target *)
begin
try
let name = get_entry_value xml "last target" in
Utils.select_in_combo target_combo name
with Not_found -> ()
end
let gconf_entry = fun name value ->
Xml.Element ("entry", ["name", name;
"value", value;
"application", "paparazzi center"],
[])
let add_entry = fun xml name value ->
let entry = gconf_entry name value in
let select = fun x -> Xml.attrib x "name" = name in
let xml = ExtXml.remove_child ~select "entry" xml in
Xml.Element (Xml.tag xml, Xml.attribs xml, entry::Xml.children xml)
let write_preferences = fun file (ac_combo:Utils.combo) (session_combo:Utils.combo) (target_combo:Utils.combo) ->
let xml = if Sys.file_exists file then Xml.parse_file file else Xml.Element ("gconf", [], []) in
(* Save A/C name *)
let xml =
try
let ac_name = Utils.combo_value ac_combo in
add_entry xml "last A/C" ac_name
with Not_found -> xml in
(* Save session *)
let xml =
let session_name = Utils.combo_value session_combo in
add_entry xml "last session" session_name in
(* Save target *)
let xml =
let name = Utils.combo_value target_combo in
add_entry xml "last target" name in
let f = open_out file in
Printf.fprintf f "%s\n" (ExtXml.to_string_fmt xml);
close_out f
let quit_callback = fun gui ac_combo session_combo target_combo () ->
CP.close_programs gui;
write_preferences Env.gconf_file ac_combo session_combo target_combo;
exit 0
let quit_button_callback = fun gui ac_combo session_combo target_combo () ->
if Sys.file_exists Utils.backup_xml_file then begin
let rec question_box = fun () ->
match GToolbox.question_box ~title:"Quit" ~buttons:["Save changes"; "Discard changes"; "View changes"; "Cancel"] ~default:1 "Configuration changes have not been saved" with
| 2 ->
Sys.rename Utils.backup_xml_file Utils.conf_xml_file;
quit_callback gui ac_combo session_combo target_combo ()
| 3 ->
ignore (Sys.command (sprintf "tkdiff %s %s" Utils.backup_xml_file Utils.conf_xml_file));
question_box ()
| 1 ->
Sys.remove Utils.backup_xml_file;
quit_callback gui ac_combo session_combo target_combo ()
| _ -> () in
question_box ()
end else
match GToolbox.question_box ~title:"Quit" ~buttons:["Cancel"; "Quit"] ~default:2 "Quit ?" with
2 -> quit_callback gui ac_combo session_combo target_combo ()
| _ -> ()
let () =
Arg.parse
["-fullscreen", Arg.Set fullscreen, "Fullscreen window"]
@@ -41,7 +138,7 @@ let () =
"Usage: ";
let file = Env.paparazzi_src // "sw" // "supervision" // "paparazzicenter.glade" in
let gui = new Gtk_pc.window ~file () in
ignore (gui#window#connect#destroy ~callback:(fun _ -> CP.close_programs gui; exit 0));
if !fullscreen then
gui#window#fullscreen ();
gui#toplevel#show ();
@@ -51,17 +148,26 @@ let () =
let s = gui#statusbar#new_context "env" in
ignore (s#push (sprintf "HOME=%s SRC=%s" Env.paparazzi_home Env.paparazzi_src));
let ac_combo = AC.parse_conf_xml gui#vbox_ac
and target_combo = combo ["sim";"fbw";"ap"] gui#vbox_target in
if Sys.file_exists Utils.backup_xml_file then begin
let rec question_box = fun () ->
match GToolbox.question_box ~title:"Backup" ~buttons:["Keep changes"; "Discard changes"; "View changes"] ~default:2 "Configuration changes made during the last session were not saved. ?" with
| 2 -> Sys.rename Utils.backup_xml_file Utils.conf_xml_file
| 3 -> ignore (Sys.command (sprintf "tkdiff %s %s" Utils.backup_xml_file Utils.conf_xml_file)); question_box ()
| _ -> Sys.remove Utils.backup_xml_file in
question_box ()
end;
(combo_widget target_combo)#misc#set_sensitive false;
Utils.build_aircrafts ();
let ac_combo = AC.parse_conf_xml gui#vbox_ac
and target_combo = Utils.combo ["sim";"fbw";"ap"] gui#vbox_target in
(Utils.combo_widget target_combo)#misc#set_sensitive false;
gui#button_clean#misc#set_sensitive false;
gui#button_build#misc#set_sensitive false;
AC.ac_combo_handler gui ac_combo target_combo;
AC.conf_handler gui;
(* Change the buffer of the text view to attach a tag_table *)
let background_tags =
List.map (fun color ->
@@ -70,7 +176,7 @@ let () =
(color, tag))
["red"; "green";"orange"] in
let tag_table = GText.tag_table () in
List.iter (fun (color, tag) -> tag_table#add tag#as_tag) background_tags;
List.iter (fun (_color, tag) -> tag_table#add tag#as_tag) background_tags;
let buffer = GText.buffer ~tag_table () in
gui#console#set_buffer buffer;
@@ -94,9 +200,6 @@ let () =
| [] -> [] in
loop color_regexps in
(* Attach the second console to the buffer of the first one *)
gui#console_cp#set_buffer gui#console#buffer;
let log = fun s ->
let iter = gui#console#buffer#end_iter in
let tags = compute_tags s in
@@ -104,29 +207,28 @@ let () =
(* Scroll to the bottom line *)
let end_iter = gui#console#buffer#end_iter in
let end_mark = gui#console#buffer#create_mark end_iter in
gui#console#scroll_mark_onscreen (`MARK end_mark);
gui#console_cp#scroll_mark_onscreen (`MARK end_mark) in
gui#console#scroll_mark_onscreen (`MARK end_mark) in
AC.build_handler gui ac_combo target_combo log;
AC.build_handler ~file gui ac_combo target_combo log;
CP.supervision ~file gui log;
(* GCS plugin
Cannot reattach a new window: hack by kill and remake the socket *)
let rec socket = fun () ->
let socket_GCS = GWindow.socket ~packing:gui#vbox_GCS#add () in
CP.socket_GCS_id := socket_GCS#xwindow;
ignore(socket_GCS#connect#plug_removed
(fun () -> gui#vbox_GCS#remove socket_GCS#coerce; socket ())) in
socket ();
let session_combo = CP.supervision ~file gui log ac_combo in
(* Quit button *)
let callback = fun num_page ->
if num_page = quit_page then
match GToolbox.question_box ~title:"Quit" ~buttons:["Cancel"; "Quit"] ~default:2 "Quit ?" with
2 -> exit 0
| _ ->ignore (GMain.Idle.add (fun () -> gui#notebook#goto_page 0; false))
in
ignore (gui#notebook#connect#switch_page ~callback);
ignore (gui#menu_item_quit#connect#activate ~callback:(quit_button_callback gui ac_combo session_combo target_combo));
ignore (gui#window#connect#destroy ~callback:(quit_callback gui ac_combo session_combo target_combo));
let callback = fun () ->
fullscreen := not !fullscreen;
if !fullscreen then
gui#window#fullscreen ()
else
gui#window#unfullscreen () in
ignore (gui#menu_item_fullscreen#connect#activate ~callback);
(* Read preferences *)
if Sys.file_exists Env.gconf_file then begin
read_preferences Env.gconf_file ac_combo session_combo target_combo
end;
GMain.Main.main ();;
+84 -112
View File
@@ -24,9 +24,11 @@
*
*)
open Pc_common
module Utils = Pc_common
open Printf
let (//) = Filename.concat
let gcs = Env.paparazzi_src // "sw/ground_segment/cockpit/gcs"
let string_of_gdkcolor = fun c ->
@@ -45,30 +47,34 @@ let aircraft_sample = fun name ac_id ->
[])
let airframes_dir = conf_dir // "airframes"
let flight_plans_dir = conf_dir // "flight_plans"
let write_conf_xml = fun () ->
Sys.rename conf_xml_file (conf_xml_file^"~");
let l = Hashtbl.fold (fun _ a r -> a::r) aircrafts [] in
let write_conf_xml = fun ?(user_save = false) () ->
let l = Hashtbl.fold (fun _ a r -> a::r) Utils.aircrafts [] in
let l = List.sort (fun ac1 ac2 -> compare (Xml.attrib ac1 "name") (Xml.attrib ac2 "name")) l in
let c = Xml.Element ("conf", [], l) in
let f = open_out conf_xml_file in
output_string f (ExtXml.to_string_fmt ~tab_attribs:true c);
close_out f
if c <> Xml.parse_file Utils.conf_xml_file then begin
if not (Sys.file_exists Utils.backup_xml_file) then
ignore (Sys.command (sprintf "cp %s %s" Utils.conf_xml_file Utils.backup_xml_file));
let f = open_out Utils.conf_xml_file in
fprintf f "%s\n" (ExtXml.to_string_fmt ~tab_attribs:true c);
close_out f
end;
if user_save && Sys.file_exists Utils.backup_xml_file then begin
let today = Unix.localtime (Unix.gettimeofday ()) in
Sys.rename Utils.backup_xml_file (sprintf "%s.%04d-%02d-%02d_%02d:%02d" Utils.conf_xml_file (1900+today.Unix.tm_year) (today.Unix.tm_mon+1) today.Unix.tm_mday today.Unix.tm_hour today.Unix.tm_min)
end
let new_ac_id = fun () ->
let m = ref 0 in
Hashtbl.iter
(fun _ x ->
m := max !m (int_of_string (ExtXml.attrib x "ac_id")))
aircrafts ;
Utils.aircrafts ;
!m + 1
let parse_conf_xml = fun vbox ->
let strings = ref [] in
Hashtbl.iter (fun name _ac -> strings := name :: !strings) aircrafts;
combo ~others:[""] !strings vbox
Hashtbl.iter (fun name _ac -> strings := name :: !strings) Utils.aircrafts;
Utils.combo ("" :: !strings) vbox
let combo_connect = fun ((combo: #GEdit.combo_box), (_,column)) cb ->
@@ -80,23 +86,6 @@ let combo_connect = fun ((combo: #GEdit.combo_box), (_,column)) cb ->
let data = combo#model#get ~row ~column in
cb data))
let combo_value = fun ((combo: #GEdit.combo_box), (_,column)) ->
match combo#active_iter with
| None -> raise Not_found
| Some row -> combo#model#get ~row ~column
let is_xml_file = fun s ->
let n = String.length s in
n >= 4 && String.sub s (n-4) 4 = ".xml"
let combo_dir = fun ?others directory vbox ->
let files = Array.to_list (Sys.readdir directory) in
let xml_files = List.filter is_xml_file files in
combo ?others xml_files vbox
let editor =
try Sys.getenv "EDITOR" with _ -> "gedit"
@@ -121,8 +110,8 @@ let ac_files = fun gui ->
(* Awful but easier *)
let current_color = ref "white"
let save_callback = fun gui ac_combo () ->
let ac_name = combo_value ac_combo in
let save_callback = fun ?user_save gui ac_combo () ->
let ac_name = Utils.combo_value ac_combo in
if ac_name <> "" then begin
let color = !current_color in
let aircraft =
@@ -136,19 +125,30 @@ let save_callback = fun gui ac_combo () ->
"settings", gui#label_settings#text;
"gui_color", color],
[]) in
begin try Hashtbl.remove aircrafts ac_name with _ -> () end;
Hashtbl.add aircrafts ac_name aircraft
if gui#entry_ac_id#text <> "" then begin
begin try Hashtbl.remove Utils.aircrafts ac_name with _ -> () end;
Hashtbl.add Utils.aircrafts ac_name aircraft
end
end;
write_conf_xml ()
write_conf_xml ?user_save ()
let first_word = fun s ->
try
let n = String.index s ' ' in
String.sub s 0 n
with
Not_found -> s
(* Link A/C to airframe & flight_plan labels *)
let ac_combo_handler = fun gui (ac_combo:combo) target_combo ->
let ac_combo_handler = fun gui (ac_combo:Utils.combo) target_combo ->
combo_connect ac_combo
(fun ac_name ->
try
let aircraft = Hashtbl.find Utils.aircrafts ac_name in
let sample = aircraft_sample ac_name "42" in
let aircraft = Hashtbl.find aircrafts ac_name in
let value = fun a ->
try (ExtXml.attrib aircraft a) with _ -> Xml.attrib sample a in
List.iter
@@ -161,14 +161,14 @@ let ac_combo_handler = fun gui (ac_combo:combo) target_combo ->
gui#eventbox_gui_color#misc#modify_bg [`NORMAL, `NAME gui_color];
current_color := gui_color;
gui#entry_ac_id#set_text ac_id;
(combo_widget target_combo)#misc#set_sensitive true;
(Utils.combo_widget target_combo)#misc#set_sensitive true;
with
Not_found ->
gui#label_airframe#set_text "";
gui#label_flight_plan#set_text "";
gui#button_clean#misc#set_sensitive false;
gui#button_build#misc#set_sensitive false;
(combo_widget target_combo)#misc#set_sensitive false
(Utils.combo_widget target_combo)#misc#set_sensitive false
);
(* New A/C button *)
@@ -176,35 +176,32 @@ let ac_combo_handler = fun gui (ac_combo:combo) target_combo ->
match GToolbox.input_string ~title:"New A/C" ~text:"MYAC" "New A/C name ?" with
None -> ()
| Some s ->
let (store, column) = combo_model ac_combo in
let row = store#append () in
store#set ~row ~column s;
Utils.add_to_combo ac_combo s;
let a = aircraft_sample s (string_of_int (new_ac_id ())) in
Hashtbl.add aircrafts s a;
aircrafts_table_has_changed := true;
(combo_widget ac_combo)#set_active_iter (Some row)
Hashtbl.add Utils.aircrafts s a;
Utils.aircrafts_table_has_changed := true
in
ignore (gui#button_new_ac#connect#clicked ~callback);
ignore (gui#menu_item_new_ac#connect#activate ~callback);
(* Delete A/C *)
let callback = fun _ ->
let ac_name = combo_value ac_combo in
let ac_name = Utils.combo_value ac_combo in
if ac_name <> "" then
match GToolbox.question_box ~title:"Delete A/C" ~buttons:["Cancel"; "Delete"] ~default:2 (sprintf "Delete %s ? (no undo after Save)" ac_name) with
2 -> begin
begin try Hashtbl.remove aircrafts ac_name with _ -> () end;
aircrafts_table_has_changed := true;
let combo_box = combo_widget ac_combo in
begin try Hashtbl.remove Utils.aircrafts ac_name with _ -> () end;
Utils.aircrafts_table_has_changed := true;
let combo_box = Utils.combo_widget ac_combo in
match combo_box#active_iter with
| None -> ()
| Some row ->
let (store, column) = combo_model ac_combo in
let (store, _column) = Utils.combo_model ac_combo in
ignore (store#remove row);
combo_box#set_active 1
end
| _ -> ()
in
ignore (gui#button_delete_ac#connect#clicked ~callback);
ignore (gui#delete_ac_menu_item#connect#activate ~callback);
(* GUI color *)
let callback = fun _ ->
@@ -213,16 +210,38 @@ let ac_combo_handler = fun gui (ac_combo:combo) target_combo ->
let colorname = string_of_gdkcolor csd#colorsel#color in
gui#eventbox_gui_color#misc#modify_bg [`NORMAL, `NAME colorname];
current_color := colorname;
save_callback gui ac_combo ();
csd#destroy () in
ignore (csd#ok_button#connect#clicked ~callback);
ignore (csd#cancel_button#connect#clicked ~callback:csd#destroy) in
ignore(gui#button_gui_color#connect#clicked ~callback);
(* A/C id *)
ignore(gui#entry_ac_id#connect#changed ~callback:(fun () -> save_callback gui ac_combo ()));
(* Conf *)
List.iter (fun (name, label, button_browse, button_edit, editor, multiple) ->
let callback = fun _ ->
editor (Utils.conf_dir // label#text) in
ignore (button_edit#connect#clicked ~callback);
let callback = fun _ ->
let subdir = Filename.dirname (first_word label#text) in
let cb = fun selected ->
let names = List.map (fun name -> subdir//name) selected in
let names = String.concat " " names in
label#set_text names;
save_callback gui ac_combo ()
in
Utils.choose_xml_file ~multiple name subdir cb in
ignore (button_browse#connect#clicked ~callback))
(ac_files gui);
(* Save button *)
ignore(gui#button_save_ac#connect#clicked ~callback:(save_callback gui ac_combo))
ignore(gui#menu_item_save_ac#connect#activate ~callback:(save_callback ~user_save:true gui ac_combo))
let build_handler = fun gui ac_combo (target_combo:combo) (log:string->unit) ->
let build_handler = fun ~file gui ac_combo (target_combo:Utils.combo) (log:string->unit) ->
(* Link target to upload button *)
combo_connect target_combo
(fun target ->
@@ -233,77 +252,30 @@ let build_handler = fun gui ac_combo (target_combo:combo) (log:string->unit) ->
match GToolbox.input_string ~title:"New Target" ~text:"tunnel" "New build target ?" with
None -> ()
| Some s ->
let (store, column) = combo_model target_combo in
let (store, column) = Utils.combo_model target_combo in
let row = store#append () in
store#set ~row ~column s;
(combo_widget target_combo)#set_active_iter (Some row)
(Utils.combo_widget target_combo)#set_active_iter (Some row)
in
ignore (gui#button_new_target#connect#clicked ~callback);
let autosave = fun () ->
if gui#button_autosave#active then
save_callback gui ac_combo () in
(* Clean button *)
let callback = fun () ->
autosave ();
command log (combo_value ac_combo) "clean_ac" in
Utils.command ~file gui log (Utils.combo_value ac_combo) "clean_ac" in
ignore (gui#button_clean#connect#clicked ~callback);
(* Build button *)
let callback = fun () ->
autosave ();
let ac_name = combo_value ac_combo
and target = combo_value target_combo in
let ac_name = Utils.combo_value ac_combo
and target = Utils.combo_value target_combo in
let target = if target="sim" then target else sprintf "%s.compile" target in
command log ac_name target in
Utils.command ~file gui log ac_name target in
ignore (gui#button_build#connect#clicked ~callback);
(* Upload button *)
let callback = fun () ->
autosave ();
let ac_name = combo_value ac_combo
and target = combo_value target_combo in
command log ac_name (sprintf "%s.upload" target) in
let ac_name = Utils.combo_value ac_combo
and target = Utils.combo_value target_combo in
Utils.command ~file gui log ac_name (sprintf "%s.upload" target) in
ignore (gui#button_upload#connect#clicked ~callback)
let choose_xml_file = fun ?(multiple = false) title subdir cb ->
let dir = conf_dir // subdir in
let dialog = GWindow.file_chooser_dialog ~action:`OPEN ~title () in
ignore (dialog#set_current_folder dir);
dialog#add_filter (GFile.filter ~name:"xml" ~patterns:["*.xml"] ());
dialog#add_button_stock `CANCEL `CANCEL ;
dialog#add_select_button_stock `OPEN `OPEN ;
dialog#set_select_multiple multiple;
begin match dialog#run (), dialog#filename with
| `OPEN, _ when multiple ->
let names = dialog#get_filenames in
dialog#destroy ();
cb (List.map Filename.basename names)
| `OPEN, Some name ->
dialog#destroy ();
cb [Filename.basename name]
| _ -> dialog#destroy ()
end
let first_word = fun s ->
try
let n = String.index s ' ' in
String.sub s 0 n
with
Not_found -> s
let conf_handler = fun gui ->
List.iter (fun (name, label, button_browse, button_edit, editor, multiple) ->
let callback = fun _ ->
editor (conf_dir // label#text) in
ignore (button_edit#connect#clicked ~callback);
let callback = fun _ ->
let subdir = Filename.dirname (first_word label#text) in
let cb = fun selected ->
let names = List.map (fun name -> subdir//name) selected in
let names = String.concat " " names in
label#set_text names in
choose_xml_file ~multiple name subdir cb in
ignore (button_browse#connect#clicked ~callback))
(ac_files gui)
+119 -12
View File
@@ -60,26 +60,129 @@ let run_and_log = fun log com ->
log (sprintf "\nDONE (%s)\n\n" com);
false
end in
let _io_watch_out = Glib.Io.add_watch [`IN; `HUP] cb channel_out in
pid, channel_out
let command = fun (log:string->unit) ac_name target ->
let com = sprintf "export PATH=/usr/bin:$PATH; make -C %s -f Makefile.ac AIRCRAFT=%s %s" Env.paparazzi_src ac_name target in
log com;
ignore (run_and_log log com)
let io_watch_out = Glib.Io.add_watch [`IN; `HUP] cb channel_out in
pid, channel_out, com_stdout, io_watch_out
type combo = GEdit.combo_box * (GTree.list_store * string GTree.column)
let combo_widget = fst
let combo_model = snd
let combo_value = fun ((combo: #GEdit.combo_box), (_,column)) ->
match combo#active_iter with
| None -> raise Not_found
| Some row -> combo#model#get ~row ~column
let combo = fun ?(others = []) strings vbox ->
let strings = others @ strings in
let combo_separator = "--"
let combo = fun strings vbox ->
let (combo, (tree, column)) =
GEdit.combo_box_text ~packing:vbox#add ~strings () in
combo#set_active 0;
combo#set_row_separator_func
(Some (fun m row -> m#get ~row ~column = combo_separator)) ;
(combo, (tree, column))
let add_to_combo = fun (combo : combo) string ->
let (store, column) = combo_model combo in
let row = store#append () in
store#set ~row ~column string;
(combo_widget combo)#set_active_iter (Some row)
let select_in_combo = fun (combo : combo) string ->
let (store, column) = combo_model combo in
store#foreach
(fun _path row ->
if store#get ~row ~column = string then begin
(combo_widget combo)#set_active_iter (Some row);
true
end else
false)
let choose_xml_file = fun ?(multiple = false) title subdir cb ->
let dir = conf_dir // subdir in
let dialog = GWindow.file_chooser_dialog ~action:`OPEN ~title () in
ignore (dialog#set_current_folder dir);
dialog#add_filter (GFile.filter ~name:"xml" ~patterns:["*.xml"] ());
dialog#add_button_stock `CANCEL `CANCEL ;
dialog#add_select_button_stock `OPEN `OPEN ;
dialog#set_select_multiple multiple;
begin match dialog#run (), dialog#filename with
| `OPEN, _ when multiple ->
let names = dialog#get_filenames in
dialog#destroy ();
cb (List.map Filename.basename names)
| `OPEN, Some name ->
dialog#destroy ();
cb [Filename.basename name]
| _ -> dialog#destroy ()
end
let run_and_monitor = fun ?(once = false) ?file gui log com_name com args ->
let c = sprintf "%s %s" com args in
let p = new Gtk_process.hbox_program ?file () in
(gui#vbox_programs:GPack.box)#pack p#toplevel#coerce;
p#label_com_name#set_text com_name;
p#entry_program#set_text c;
let pid = ref (-1)
and outchan = ref stdin
and watches = ref [] in
let run = fun callback ->
let c = p#entry_program#text in
log (sprintf "Run '%s'\n" c);
let (pi, out, unixfd, io_watch) = run_and_log log ("exec "^c) in
pid := pi;
outchan := unixfd;
let io_watch' = Glib.Io.add_watch [`HUP] (fun _ -> callback true;false) out in
watches := [ io_watch; io_watch'] in
let remove_callback = fun () ->
gui#vbox_programs#remove p#toplevel#coerce in
let rec callback = fun stop ->
match p#button_stop#label, stop with
"gtk-stop", _ ->
List.iter Glib.Io.remove !watches;
close_in !outchan;
ignore (Unix.kill !pid Sys.sigkill);
ignore (Unix.waitpid [] !pid);
p#button_stop#set_label "gtk-redo";
p#button_remove#misc#set_sensitive true;
if once then
remove_callback ()
else if stop && p#checkbutton_autolaunch#active then
callback false
| "gtk-redo", false ->
p#button_stop#set_label "gtk-stop";
run callback;
p#button_remove#misc#set_sensitive false
| _ -> ()
in
ignore (p#button_stop#connect#clicked ~callback:(fun () -> callback false));
run callback;
(* Stop the program if the box is closed *)
let callback = fun () ->
callback true in
ignore(p#toplevel#connect#destroy ~callback);
(* Remove button *)
ignore (p#button_remove#connect#clicked ~callback:remove_callback)
let basic_command = fun (log:string->unit) ac_name target ->
let com = sprintf "export PATH=/usr/bin:$PATH; make -C %s -f Makefile.ac AIRCRAFT=%s %s" Env.paparazzi_src ac_name target in
log com;
ignore (run_and_log log com)
let command = fun ?file gui (log:string->unit) ac_name target ->
let com = sprintf "make -C %s -f Makefile.ac AIRCRAFT=%s %s" Env.paparazzi_src ac_name target in
run_and_monitor ~once:true ?file gui log "make" com ""
let conf_is_set = fun home ->
Sys.file_exists home &&
@@ -99,7 +202,7 @@ let druid = fun home ->
d#append_page fp;
ignore (fp#connect#next
(fun _ ->
command prerr_endline "" "init";
basic_command prerr_endline "" "init";
false
))
@@ -125,11 +228,15 @@ let _ =
druid home
let conf_xml_file = conf_dir // "conf.xml"
let conf_xml = Xml.parse_file conf_xml_file
let backup_xml_file = conf_xml_file ^ "~"
let aircrafts = Hashtbl.create 7
let aircrafts_table_has_changed = ref false
let _ =
let build_aircrafts = fun () ->
let conf_xml = Xml.parse_file conf_xml_file in
List.iter (fun aircraft ->
Hashtbl.add aircrafts (ExtXml.attrib aircraft "name") aircraft)
(Xml.children conf_xml);
aircrafts_table_has_changed := true
+87 -141
View File
@@ -1,7 +1,7 @@
(*
* $Id$
*
* Paparazzi center process handling
* Paparazzi center processes handling
*
* Copyright (C) 2007 ENAC, Pascal Brisset, Antoine Drouin
*
@@ -25,11 +25,11 @@
*)
open Printf
open Pc_common
module Utils = Pc_common
let socket_GCS_id = ref (Int32.of_int 0)
let (//) = Filename.concat
let control_panel_xml_file = conf_dir // "control_panel.xml"
let control_panel_xml_file = Utils.conf_dir // "control_panel.xml"
let control_panel_xml = Xml.parse_file control_panel_xml_file
let programs =
let h = Hashtbl.create 7 in
@@ -67,50 +67,9 @@ let write_control_panel_xml = fun () ->
output_string f (ExtXml.to_string_fmt ~tab_attribs:false c);
close_out f
let run_and_monitor = fun ?file ?(plugged=false) gui log com_name args ->
let com = program_command com_name in
let c = sprintf "%s %s" com args in
let p = new Gtk_process.hbox_program ?file () in
(gui#vbox_programs:GPack.box)#pack p#toplevel#coerce;
p#label_com_name#set_text com_name;
p#entry_program#set_text c;
let pid = ref (-1) in
let run = fun callback ->
let c = p#entry_program#text in
let c = if plugged then sprintf "%s -wid 0x%lx" c !socket_GCS_id else c in
if plugged then
gui#notebook#goto_page 2; (* FIXME *)
log (sprintf "Run '%s'\n" c);
let (pi, out) = run_and_log log ("exec "^c) in
pid := pi;
ignore (Glib.Io.add_watch [`HUP] (fun _ -> callback true; false) out) in
let rec callback = fun stop ->
match p#button_stop#label, stop with
"gtk-stop", _ ->
ignore (Unix.kill !pid Sys.sigkill);
p#button_stop#set_label "gtk-redo";
p#button_remove#misc#set_sensitive true;
if stop && p#checkbutton_autolaunch#active then
callback false
| "gtk-redo", false ->
p#button_stop#set_label "gtk-stop";
run callback;
p#button_remove#misc#set_sensitive false
| _ -> ()
in
ignore (p#button_stop#connect#clicked ~callback:(fun () -> callback false));
run callback;
(* Stop the program if the box is removed *)
let callback = fun w ->
callback true in
ignore(p#toplevel#connect#destroy ~callback);
(* Remove button *)
let callback = fun () ->
gui#vbox_programs#remove p#toplevel#coerce in
ignore (p#button_remove#connect#clicked ~callback)
let run_and_monitor = fun ?file gui log com_name args ->
Utils.run_and_monitor ?file gui log com_name (program_command com_name) args
let close_programs = fun gui ->
List.iter (fun w ->
@@ -154,12 +113,12 @@ let parse_process_args = fun (name, args) ->
Xml.Element("arg", ["flag",option],[])::xml_args l in
Xml.Element("program", ["name", name], xml_args args)
let save_session = fun gui ->
let save_session = fun gui session_combo ->
(* Ask for a session name *)
let text = gui#entry_session_name#text in
let text = Utils.combo_value session_combo in
let text = if text = "" then "My session" else text in
match GToolbox.input_string ~ok:"Save" ~text ~title:"Session name" "Save custom session ?" with
None -> false
None -> ""
| Some name ->
let current_processes =
List.map (fun hbox ->
@@ -176,7 +135,7 @@ let save_session = fun gui ->
begin try Hashtbl.remove sessions name with _ -> () end;
Hashtbl.add sessions name session;
write_control_panel_xml ();
true
name
let double_quote = fun s ->
if String.contains s ' ' then
@@ -184,30 +143,72 @@ let double_quote = fun s ->
else
s
let supervision = fun ?file gui log ->
let supervision_page = 1 in (* FIXME *)
let supervision = fun ?file gui log (ac_combo : Utils.combo) ->
let run_gcs = fun () ->
run_and_monitor ?file ~plugged:true gui log "GCS" ""
run_and_monitor ?file gui log "GCS" ""
and run_server = fun args ->
run_and_monitor ?file gui log "Server" args
and run_link = fun args ->
run_and_monitor ?file gui log "Data Link" args
and run_sitl = fun ac_name ->
let args = sprintf "-a %s -boot -norc" ac_name in
run_and_monitor ?file gui log "Simulator" args
in
(* Replay menu *)
let callback = fun () ->
gui#entry_session_name#set_text "Replay";
(* Sessions *)
let session_combo = Utils.combo [] gui#vbox_session in
let remove_custom_sessions = fun () ->
let (store, _column) = Utils.combo_model session_combo in
store#clear ()
in
let register_custom_sessions = fun () ->
remove_custom_sessions ();
Utils.add_to_combo session_combo "Simulation";
Utils.add_to_combo session_combo "Replay";
Utils.add_to_combo session_combo Utils.combo_separator;
Hashtbl.iter
(fun name _session ->
Utils.add_to_combo session_combo name)
sessions in
register_custom_sessions ();
let execute_custom = fun session_name ->
let session = Hashtbl.find sessions session_name in
List.iter
(fun program ->
let name = ExtXml.attrib program "name" in
let p = ref "" in
List.iter
(fun arg ->
let constant =
try double_quote (Xml.attrib arg "constant") with _ -> "" in
p := sprintf "%s %s %s" !p (ExtXml.attrib arg "flag") constant)
(Xml.children program);
run_and_monitor ?file gui log name !p)
(Xml.children session)
in
(* Replay session *)
let replay = fun () ->
run_and_monitor ?file gui log "Log File Player" "";
run_server "-n";
run_gcs ()
in
ignore (gui#replay_menu_item#connect#activate ~callback);
run_gcs () in
(* Simulations *)
let simulation = fun () ->
run_gcs ();
run_server "-n";
run_sitl (Utils.combo_value ac_combo) in
(* Run session *)
let callback = fun () ->
match Utils.combo_value session_combo with
"Simulation" -> simulation ()
| "Replay" -> replay ()
| custom -> execute_custom custom in
ignore (gui#button_execute#connect#clicked ~callback);
(* Close session *)
let callback = fun () ->
close_programs gui in
@@ -216,7 +217,7 @@ let supervision = fun ?file gui log ->
(* Tools *)
let entries = ref [] in
Hashtbl.iter
(fun name prog ->
(fun name _prog ->
let cb = fun () ->
run_and_monitor ?file gui log name "" in
entries := `I (name, cb) :: !entries)
@@ -230,92 +231,37 @@ let supervision = fun ?file gui log ->
GToolbox.build_menu menu sorted_entries;
gui#programs_menu_item#set_submenu menu;
(* Simulations *)
let insert_sims_in_menu = fun num_page ->
if num_page = supervision_page && !aircrafts_table_has_changed then
let entries = ref [] in
Hashtbl.iter
(fun ac_name ac ->
let cb = fun () ->
gui#entry_session_name#set_text (sprintf "Simulator %s" ac_name);
run_gcs ();
run_server "-n";
run_sitl ac_name
in
entries := `I (ac_name, cb) :: !entries)
aircrafts;
let menu = GMenu.menu ()
and sorted_entries = List.sort compare !entries in
GToolbox.build_menu menu sorted_entries;
gui#sim_menu_item#set_submenu menu;
aircrafts_table_has_changed := false in
ignore (gui#notebook#connect#switch_page ~callback:insert_sims_in_menu);
(* Sessions *)
let insert_sessions_in_menu = fun () ->
let entries = ref [] in
let cb = fun name session () ->
gui#entry_session_name#set_text name;
List.iter
(fun program ->
let name = ExtXml.attrib program "name" in
let p = ref "" in
List.iter
(fun arg ->
let constant =
try double_quote (Xml.attrib arg "constant") with _ -> "" in
p := sprintf "%s %s %s" !p (ExtXml.attrib arg "flag") constant)
(Xml.children program);
run_and_monitor ~plugged:(name="gcs") ?file gui log name !p)
(Xml.children session)
in
Hashtbl.iter
(fun name session ->
entries := `I (name, cb name session) :: !entries)
sessions;
let menu = GMenu.menu ()
and sorted_entries = List.sort compare !entries in
GToolbox.build_menu menu sorted_entries;
gui#session_menu_item#set_submenu menu in
insert_sessions_in_menu ();
(* Add new session *)
(* New session *)
let callback = fun () ->
if save_session gui then
insert_sessions_in_menu () in
ignore (gui#button_save_session#connect#clicked ~callback);
match GToolbox.input_string ~title:"New session" ~text:"My session" "New session name ?" with
None -> ()
| Some s ->
Utils.add_to_combo session_combo s in
ignore (gui#menu_item_new_session#connect#activate ~callback);
(* Save new session *)
let callback = fun () ->
match save_session gui session_combo with
"" -> ()
| session_name ->
register_custom_sessions ();
Utils.select_in_combo session_combo session_name
in
ignore (gui#menu_item_save_session#connect#activate ~callback);
(* Remove current session *)
let callback = fun () ->
let session_name = gui#entry_session_name#text in
let session_name = Utils.combo_value session_combo in
match GToolbox.question_box ~title:"Delete custom session" ~buttons:["Cancel"; "Delete"] ~default:2 (sprintf "Delete '%s' custom session ? (NO undo)" session_name) with
2 ->
if Hashtbl.mem sessions session_name then begin
Hashtbl.remove sessions session_name;
write_control_panel_xml ();
insert_sessions_in_menu ()
register_custom_sessions ()
end;
close_programs gui;
gui#entry_session_name#set_text ""
close_programs gui
| _ -> ()
in
ignore (gui#button_delete_session#connect#clicked ~callback);
(* Flights *)
let cb = fun name args () ->
gui#entry_session_name#set_text (sprintf "Flight: %s" name);
run_gcs ();
run_server "";
run_link args
in
let entries =
[`I ("Maxstream", cb "Maxstream" "-transport xbee -uplink");
`I ("Aerocomm", cb "Aerocomm" "-s 57600 -aerocomm -uplink");
`I ("Serial", cb "Serial" "-uplink")] in
let menu = GMenu.menu ()
and sorted_entries = List.sort compare entries in
GToolbox.build_menu menu sorted_entries;
gui#fly_menu_item#set_submenu menu
ignore (gui#menu_item_delete_session#connect#activate ~callback);
session_combo