mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-06-06 16:42:47 +08:00
* CSV export now possible in batch
* Choice for the separator
This commit is contained in:
@@ -4,7 +4,6 @@
|
||||
<glade-interface>
|
||||
|
||||
<widget class="GtkWindow" id="export">
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="yes">Save CSV</property>
|
||||
<property name="type">GTK_WINDOW_TOPLEVEL</property>
|
||||
<property name="window_position">GTK_WIN_POS_NONE</property>
|
||||
@@ -14,7 +13,7 @@
|
||||
<property name="decorated">True</property>
|
||||
<property name="skip_taskbar_hint">False</property>
|
||||
<property name="skip_pager_hint">False</property>
|
||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
|
||||
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
||||
<property name="focus_on_map">True</property>
|
||||
<property name="urgency_hint">False</property>
|
||||
@@ -29,9 +28,9 @@
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
|
||||
<property name="shadow_type">GTK_SHADOW_IN</property>
|
||||
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
||||
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
||||
|
||||
<child>
|
||||
@@ -142,6 +141,31 @@
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">3</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Sep:</property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
@@ -150,7 +174,7 @@
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkEventBox" id="box_choose_interpol">
|
||||
<widget class="GtkEventBox" id="box_choose_sep">
|
||||
<property name="visible">True</property>
|
||||
<property name="visible_window">True</property>
|
||||
<property name="above_child">False</property>
|
||||
@@ -203,7 +227,7 @@
|
||||
<widget class="GtkButton" id="button_cancel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="label">gtk-close</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
|
||||
+49
-19
@@ -26,7 +26,7 @@
|
||||
|
||||
open Printf
|
||||
open Latlong
|
||||
|
||||
|
||||
let (//) = Filename.concat
|
||||
let class_name="telemetry"
|
||||
|
||||
@@ -85,7 +85,8 @@ type timestamp =
|
||||
|
||||
|
||||
(*****************************************************************************)
|
||||
let export_values = fun ?(export_geo_pos=true) (model:GTree.tree_store) data timestamp filename ->
|
||||
let export_values = fun ?(sep="tab") ?(export_geo_pos=true) (model:GTree.tree_store) data timestamp filename ->
|
||||
let sep = if sep = "tab" then "\t" else sep in
|
||||
let fields_to_export = ref [] in
|
||||
model#foreach (fun _path row ->
|
||||
if model#get ~row ~column:col_to_export then begin
|
||||
@@ -108,8 +109,8 @@ let export_values = fun ?(export_geo_pos=true) (model:GTree.tree_store) data tim
|
||||
(* Print the header *)
|
||||
fprintf f "Time";
|
||||
if export_geo_pos then
|
||||
fprintf f ";GPS lat(deg);GPS long(deg)";
|
||||
List.iter (fun (m,field) -> fprintf f ";%s:%s" m field) !fields_to_export;
|
||||
fprintf f "%sGPS lat(deg)%sGPS long(deg)" sep sep;
|
||||
List.iter (fun (m,field) -> fprintf f "%s%s:%s" sep m field) !fields_to_export;
|
||||
fprintf f "\n%!";
|
||||
|
||||
(* Store for the current values *)
|
||||
@@ -117,25 +118,35 @@ let export_values = fun ?(export_geo_pos=true) (model:GTree.tree_store) data tim
|
||||
and time = ref (match data with (t, _, _)::_ -> t | _ -> 0.) in
|
||||
|
||||
let print_last_values = fun t ->
|
||||
fprintf f "%.3f" t;
|
||||
let all_values = ref true in
|
||||
|
||||
let lookup = fun m field ->
|
||||
try Pprz.string_of_value (Hashtbl.find last_values (m,field)) with Not_found -> "" in
|
||||
try Pprz.string_of_value (Hashtbl.find last_values (m,field)) with Not_found -> all_values := false; "" in
|
||||
|
||||
let buf = Buffer.create 64 in
|
||||
|
||||
bprintf buf "%.3f" t;
|
||||
|
||||
if export_geo_pos then begin
|
||||
try
|
||||
let utm_east = float_of_string (lookup "GPS" "utm_east") /. 100.
|
||||
and utm_north = float_of_string (lookup "GPS" "utm_north") /. 100.
|
||||
and utm_zone = int_of_string (lookup "GPS" "utm_zone") in
|
||||
let wgs84 = Latlong.of_utm WGS84 {utm_x=utm_east; utm_y=utm_north; utm_zone=utm_zone} in
|
||||
fprintf f ";%.6f;%.6f" ((Rad>>Deg) wgs84.posn_lat) ((Rad>>Deg) wgs84.posn_long)
|
||||
bprintf buf "%s%.6f%s%.6f" sep ((Rad>>Deg) wgs84.posn_lat) sep ((Rad>>Deg) wgs84.posn_long)
|
||||
with
|
||||
exc -> fprintf stderr "%s\n%!" (Printexc.to_string exc)
|
||||
Failure "float_of_string" -> ()
|
||||
| exc -> fprintf stderr "%s\n%!" (Printexc.to_string exc)
|
||||
end;
|
||||
|
||||
List.iter
|
||||
(fun (m,field) ->
|
||||
let v = lookup m field in
|
||||
fprintf f ";%s" v)
|
||||
bprintf buf "%s%s" sep v)
|
||||
!fields_to_export;
|
||||
fprintf f "\n%!" in
|
||||
|
||||
if !all_values then
|
||||
fprintf f "%s\n" (Buffer.contents buf) in
|
||||
|
||||
(* Write one line per time stamp. *)
|
||||
List.iter (fun (t, msg, fields) ->
|
||||
@@ -185,8 +196,7 @@ let read_preferences = fun () ->
|
||||
|
||||
|
||||
(** The save file dialog box *)
|
||||
let save_values = fun w log_filename save ->
|
||||
let filename = Env.paparazzi_home // "var" // "logs" // log_filename ^ ".csv" in
|
||||
let save_values = fun w filename save ->
|
||||
match GToolbox.select_file ~title:"Save Values" ~filename () with
|
||||
None -> ()
|
||||
| Some file ->
|
||||
@@ -196,7 +206,7 @@ let save_values = fun w log_filename save ->
|
||||
|
||||
(*****************************************************************************)
|
||||
(** The popup window displaying values to export *)
|
||||
let popup = fun xml log_filename data ->
|
||||
let popup = fun ?(no_gui = false) xml log_filename data ->
|
||||
(* Build the list window *)
|
||||
let file = Env.paparazzi_src // "sw" // "logalizer" // "export.glade" in
|
||||
let w = new Gtk_export.export ~file () in
|
||||
@@ -236,11 +246,15 @@ let popup = fun xml log_filename data ->
|
||||
|
||||
|
||||
|
||||
(* The combo box for the extrapolation FIXME
|
||||
let strings = ["Last Value"; "Linear Extrapolation"] in
|
||||
let (combo, (tree, column)) = GEdit.combo_box_text ~packing:w#box_choose_interpol#add ~strings () in
|
||||
(* The combo box for the separator *)
|
||||
let strings = ["tab"; ";"; ","] in
|
||||
let (combo, (tree, column)) = GEdit.combo_box_text ~packing:w#box_choose_sep#add ~strings () in
|
||||
tree#foreach (fun _path row -> combo#set_active_iter (Some row); true); (* Select the first *)
|
||||
*)
|
||||
let get_separator = fun () ->
|
||||
match combo#active_iter with
|
||||
| None -> failwith "get_timestamp"
|
||||
| Some row ->
|
||||
combo#model#get ~row ~column in
|
||||
|
||||
ignore (w#button_cancel#connect#clicked (fun () -> w#export#destroy ()));
|
||||
|
||||
@@ -252,5 +266,21 @@ let popup = fun xml log_filename data ->
|
||||
Period (float_of_string w#entry_period#text)
|
||||
else
|
||||
Msg combo_value in
|
||||
save_values w log_filename (fun x -> export_values ~export_geo_pos:w#checkbutton_LL#active model data timestamp x) in
|
||||
ignore (w#button_save#connect#clicked callback)
|
||||
let sep = get_separator () in
|
||||
|
||||
let do_export = fun x -> export_values ~sep ~export_geo_pos:w#checkbutton_LL#active model data timestamp x in
|
||||
|
||||
let default_filename = Env.paparazzi_home // "var" // "logs" // log_filename ^ ".csv" in
|
||||
|
||||
if no_gui then
|
||||
do_export default_filename
|
||||
else
|
||||
save_values w default_filename do_export in
|
||||
ignore (w#button_save#connect#clicked callback);
|
||||
|
||||
if no_gui then begin
|
||||
callback ();
|
||||
w#export#destroy ()
|
||||
end else
|
||||
w#export#show ()
|
||||
|
||||
|
||||
+29
-24
@@ -24,14 +24,13 @@
|
||||
*
|
||||
*)
|
||||
|
||||
module LL = Latlong
|
||||
open LL
|
||||
|
||||
open Latlong
|
||||
open Printf
|
||||
|
||||
let (//) = Filename.concat
|
||||
let logs_dir = Env.paparazzi_home // "var" // "logs"
|
||||
let sample_kml = Env.paparazzi_home // "data/maps/sample_path.kml"
|
||||
let verbose = ref false
|
||||
|
||||
class type text_value = object method text : string end
|
||||
|
||||
@@ -284,9 +283,9 @@ let write_kml = fun plot log_name values ->
|
||||
and y = snd ys.(i) /. 100.
|
||||
and z = truncate (snd zs.(i))
|
||||
and a = snd alts.(i) /. 100. in
|
||||
let utm = { LL.utm_x = x; LL.utm_y = y; LL.utm_zone = z } in
|
||||
let utm = { utm_x = x; utm_y = y; utm_zone = z } in
|
||||
if z <> 0 then
|
||||
l := (LL.of_utm LL.WGS84 utm, a) :: !l
|
||||
l := (of_utm WGS84 utm, a) :: !l
|
||||
done;
|
||||
let l = List.rev !l in
|
||||
let xml = Xml.parse_file sample_kml in
|
||||
@@ -326,7 +325,7 @@ let write_kml = fun plot log_name values ->
|
||||
|
||||
|
||||
|
||||
let add_ac_submenu = fun protocol ?(factor=object method text="1" end) plot menubar (curves_menu_fact: GMenu.menu GMenu.factory) ac menu_name l raw_msgs ->
|
||||
let add_ac_submenu = fun ?(export=false) protocol ?(factor=object method text="1" end) plot menubar (curves_menu_fact: GMenu.menu GMenu.factory) ac menu_name l raw_msgs ->
|
||||
let menu = GMenu.menu () in
|
||||
let menuitem = GMenu.menu_item ~label:menu_name () in
|
||||
menuitem#set_submenu menu;
|
||||
@@ -370,13 +369,14 @@ let add_ac_submenu = fun protocol ?(factor=object method text="1" end) plot menu
|
||||
snd (List.find (fun (m, _) -> m.Pprz.name = "GPS") l) in
|
||||
write_kml plot menu_name gps_values in
|
||||
ignore (menu_fact#add_item ~callback "Export KML path");
|
||||
let callback = fun () ->
|
||||
Export.popup protocol menu_name raw_msgs in
|
||||
ignore (menu_fact#add_item ~callback "Export CSV")
|
||||
|
||||
let callback = fun ?no_gui () ->
|
||||
Export.popup ?no_gui protocol menu_name raw_msgs in
|
||||
ignore (menu_fact#add_item ~callback "Export CSV");
|
||||
if export then
|
||||
callback ~no_gui:true ()
|
||||
|
||||
|
||||
let load_log = fun ?factor (plot:plot) (menubar:GMenu.menu_shell GMenu.factory) curves_fact xml_file ->
|
||||
let load_log = fun ?export ?factor (plot:plot) (menubar:GMenu.menu_shell GMenu.factory) curves_fact xml_file ->
|
||||
Debug.call 'p' (fun f -> fprintf f "load_log: %s\n" xml_file);
|
||||
let xml = Xml.parse_file xml_file in
|
||||
let data_file = ExtXml.attrib xml "data_file" in
|
||||
@@ -436,7 +436,9 @@ let load_log = fun ?factor (plot:plot) (menubar:GMenu.menu_shell GMenu.factory)
|
||||
raw_msgs := (t, msg_name, vs) :: !raw_msgs
|
||||
)
|
||||
with
|
||||
exc -> prerr_endline (Printexc.to_string exc)
|
||||
exc ->
|
||||
if !verbose then
|
||||
prerr_endline (Printexc.to_string exc)
|
||||
done
|
||||
with
|
||||
End_of_file ->
|
||||
@@ -475,7 +477,7 @@ let load_log = fun ?factor (plot:plot) (menubar:GMenu.menu_shell GMenu.factory)
|
||||
(* Store data for other windows *)
|
||||
logs_menus := (ac, menu_name, (msgs, raw_msgs), protocol) :: !logs_menus;
|
||||
|
||||
add_ac_submenu protocol ?factor plot menubar curves_fact ac menu_name msgs raw_msgs;
|
||||
add_ac_submenu ?export protocol ?factor plot menubar curves_fact ac menu_name msgs raw_msgs;
|
||||
)
|
||||
acs
|
||||
|
||||
@@ -518,7 +520,7 @@ let screenshot = fun frame ->
|
||||
|
||||
|
||||
(*****************************************************************************)
|
||||
let rec plot_window = fun init ->
|
||||
let rec plot_window = fun ?export init ->
|
||||
let plotter = GWindow.window ~allow_shrink:true ~title:"Log Plotter" () in
|
||||
plotter#set_icon (Some (GdkPixbuf.from_file Env.icon_file));
|
||||
let vbox = GPack.vbox ~packing:plotter#add () in
|
||||
@@ -606,24 +608,27 @@ let rec plot_window = fun init ->
|
||||
ignore(open_log_item#connect#activate ~callback:(fun () -> let factor = (factor:>text_value) in open_log ~factor plot factory curves_menu_fact ()));
|
||||
|
||||
|
||||
List.iter (fun f -> load_log ~factor:(factor:>text_value) plot factory curves_menu_fact f) init;
|
||||
List.iter (fun f -> load_log ?export ~factor:(factor:>text_value) plot factory curves_menu_fact f) init;
|
||||
|
||||
plotter#add_accel_group accel_group;
|
||||
plotter#show ()
|
||||
|
||||
|
||||
|
||||
|
||||
let _ =
|
||||
let logs = ref [] in
|
||||
(***************************** Main ****************************************)
|
||||
let () =
|
||||
let logs = ref []
|
||||
and export = ref false in
|
||||
Arg.parse
|
||||
[]
|
||||
[ ("-export_csv", Arg.Set export, "Export in CSV in batch mode according to saved preferences (conf/%gconf.xml)");
|
||||
("-v", Arg.Set verbose, "Verbose")]
|
||||
(fun x -> logs := x :: !logs)
|
||||
"Usage: plot <log files>";
|
||||
|
||||
plot_window !logs;
|
||||
plot_window ~export: !export !logs;
|
||||
|
||||
let loop = Glib.Main.create true in
|
||||
while Glib.Main.is_running loop do
|
||||
ignore (Glib.Main.iteration true)
|
||||
done
|
||||
if not !export then
|
||||
let loop = Glib.Main.create true in
|
||||
while Glib.Main.is_running loop do
|
||||
ignore (Glib.Main.iteration true)
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user