open Printf
open Utils
+open Slave_types
module G = Guestfs
window : GWindow.window;
view : Filetree.t;
vmcombo : GEdit.combo_box GEdit.text_combo;
+ refresh_button : GButton.button;
throbber : GMisc.image;
throbber_static : GdkPixbuf.pixbuf;
statusbar : GMisc.statusbar;
ws.statusbar_context#pop ();
ignore (ws.statusbar_context#push msg)
-let clear_statusbar ws = set_statusbar ws ""
-
(* Clear the filetree. *)
let clear_view ws =
Filetree.clear ws.view
(* Callback from Connect -> ... menu items. *)
let rec connect_to ws uri =
- (match uri with
- | None -> set_statusbar ws "Connecting to default libvirt ..."
- | Some uri -> set_statusbar ws (sprintf "Connecting to %s ..." uri)
- );
clear_view ws;
Slave.discard_command_queue ();
Slave.connect uri (when_connected ws uri)
(* Called back when connected to a new hypervisor. *)
and when_connected ws uri doms =
- (match uri with
- | None -> set_statusbar ws "Connected to default libvirt"
- | Some uri -> set_statusbar ws (sprintf "Connected to %s" uri)
- );
+ populate_vmcombo ws doms
+
+and populate_vmcombo ws doms =
(* Populate the VM combo box. *)
let combo, (model, column) = ws.vmcombo in
model#clear ();
List.iter (
- fun { Slave.dom_name = name } ->
+ fun { dom_name = name } ->
let row = model#append () in
model#set ~row ~column name
) doms
(* When a new domain is selected by the user, eg through vmcombo. *)
let rec open_domain ws name =
- set_statusbar ws (sprintf "Opening %s ..." name);
clear_view ws;
Slave.discard_command_queue ();
Slave.open_domain name (when_opened_domain ws name)
(* Called back when domain was opened successfully. *)
and when_opened_domain ws name data =
debug "when_opened_domain callback";
- set_statusbar ws (sprintf "Opened %s" name);
when_opened_common ws name data
(* When a set of disk images is selected by the user. *)
match images with
| [] -> ()
| images ->
- set_statusbar ws (sprintf "Opening disk image %s ..."
- (String.concat " " images));
clear_view ws;
Slave.discard_command_queue ();
Slave.open_images images (when_opened_disk_images ws images)
and when_opened_disk_images ws images data =
match images with
| [] -> ()
- | image :: _ as images ->
+ | (image, _) :: _ ->
debug "when_opened_disk_images callback";
- set_statusbar ws (sprintf "Opened disk image %s"
- (String.concat " " images));
when_opened_common ws image data
(* Common code for when_opened_domain/when_opened_disk_images. *)
and when_opened_common ws name data =
(* Dump some of the inspection data in debug messages. *)
List.iter (fun (dev, t) -> debug "filesystem: %s: %s" dev t)
- data.Slave.insp_all_filesystems;
+ data.insp_all_filesystems;
List.iter (
- fun { Slave.insp_root = root; insp_type = typ; insp_distro = distro;
+ fun { insp_root = root; insp_type = typ; insp_distro = distro;
insp_major_version = major; insp_minor_version = minor } ->
debug "root device %s contains %s %s %d.%d" root typ distro major minor;
- ) data.Slave.insp_oses;
+ ) data.insp_oses;
Filetree.add ws.view name data
let throbber_idle ws () =
ws.throbber#set_pixbuf ws.throbber_static
+let progress ws (position, total) =
+ if position = 0L && total = 1L then
+ ws.progress_bar#pulse ()
+ else
+ ws.progress_bar#set_fraction
+ (Int64.to_float position /. Int64.to_float total)
+
(* This is called in the main thread whenever a command fails in the
* slave thread. The command queue has been cleared before this is
* called, so our job here is to reset the main window, and if
make_menubar window vbox ~packing:vbox#pack () in
(* Top toolbar. *)
- let vmcombo, throbber, throbber_static =
+ let vmcombo, refresh_button, throbber, throbber_static =
make_toolbar ~packing:vbox#pack () in
(* Main part of display is the file tree. *)
let view = make_filetree ~packing:(vbox#pack ~expand:true ~fill:true) () in
(* Status bar and progress bar. *)
- let hbox = GPack.hbox ~packing:vbox#pack () in
+ let hbox = GPack.hbox ~spacing:4 ~packing:vbox#pack () in
let progress_bar = GRange.progress_bar ~packing:hbox#pack () in
let statusbar = GMisc.statusbar ~packing:(hbox#pack ~expand:true) () in
let statusbar_context = statusbar#new_context ~name:"Standard" in
window = window;
view = view;
vmcombo = vmcombo;
+ refresh_button = refresh_button;
throbber = throbber; throbber_static = throbber_static;
statusbar = statusbar; statusbar_context = statusbar_context;
progress_bar = progress_bar
ignore (connect_none_item#connect#activate
~callback:(fun () -> connect_to ws None));
- (* VM combo box when changed by the user. *)
+ (* VM combo box when changed by the user.
+ * The refresh button acts like changing the VM combo too.
+ *)
let combo, (model, column) = ws.vmcombo in
ignore (
combo#connect#changed
| Some row -> open_domain ws (model#get ~row ~column)
)
);
+ ignore (
+ refresh_button#connect#clicked
+ ~callback:(
+ fun () ->
+ match combo#active_iter with
+ | None -> () (* nothing selected *)
+ | Some row -> open_domain ws (model#get ~row ~column)
+ )
+ );
+ (* Return the window_state struct. *)
ws
and make_menubar window vbox ~packing () =
hbox#pack (mklabel "Guest: ");
let vmcombo = GEdit.combo_box_text ~packing:hbox#pack () in
+ (* Refresh button.
+ * http://stackoverflow.com/questions/2188659/stock-icons-not-shown-on-buttons
+ *)
+ let refresh_button =
+ let image = GMisc.image ~stock:`REFRESH () in
+ let b = GButton.button ~packing:hbox#pack () in
+ b#set_image (image :> GObj.widget);
+ b in
+
(* Throbber. *)
let static = Throbber.static () in
(*let animation = Throbber.animation () in*)
let throbber =
- GMisc.image ~pixbuf:static ~packing:(hbox#pack ~from:`END) () in
+ (* Workaround for http://caml.inria.fr/mantis/view.php?id=4732 *)
+ let from = Obj.magic 3448763 (* `END *) in
+ GMisc.image ~pixbuf:static ~packing:(hbox#pack ~from) () in
- vmcombo, throbber, static
+ vmcombo, refresh_button, throbber, static
and make_filetree ~packing () =
let sw =
GBin.scrolled_window ~packing ~hpolicy:`AUTOMATIC ~vpolicy:`ALWAYS () in
Filetree.create ~packing:sw#add ()
+
+(* Do what the user asked on the command line. *)
+let rec run_cli_request ws = function
+ | Cmdline.Empty_window -> ()
+ | Cmdline.Open_images images ->
+ open_disk_images ws images
+ | Cmdline.Open_guest guest ->
+ (* Open libvirt connection, and in the callback open the guest. *)
+ let uri = connect_uri () in
+ Slave.connect uri (when_connected_cli_request ws guest)
+and when_connected_cli_request ws guest doms =
+ populate_vmcombo ws doms;
+
+ (* "guest" should match a domain in "doms". Check this and
+ * get the index of it.
+ *)
+ let rec loop i = function
+ | [] ->
+ failwith "guest %s not found (do you need to use --connect?)" guest
+ | d::ds when d = guest -> i
+ | _::ds -> loop (i+1) ds
+ in
+ let i = loop 0 (List.map (fun { dom_name = name } -> name) doms) in
+
+ let combo, _ = ws.vmcombo in
+ combo#set_active i