Use signals to loosely couple modules.
[guestfs-browser.git] / main.ml
diff --git a/main.ml b/main.ml
index a823aa5..c908bbc 100644 (file)
--- a/main.ml
+++ b/main.ml
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *)
 
-open Utils
-
-(* Display state. *)
-type display_state = {
-  window : GWindow.window;
-  throbber_busy : unit -> unit;
-  throbber_idle : unit -> unit;
-}
-
-let open_main_window () =
-  let title = "Guest Filesystem Browser" in
-  let window = GWindow.window ~width:800 ~height:600 ~title () in
-  let vbox = GPack.vbox ~packing:window#add () in
+open Printf
 
-  (* Do the menus. *)
-  let menubar = GMenu.menu_bar ~packing:vbox#pack () in
-  let factory = new GMenu.factory menubar in
-  let accel_group = factory#accel_group in
-  let connect_menu = factory#add_submenu "_Connect" in
-
-  let factory = new GMenu.factory connect_menu ~accel_group in
-  let quit_item = factory#add_item "E_xit" ~key:GdkKeysyms._Q in
+open Utils
 
-  (* Quit. *)
-  let quit _ = GMain.quit (); false in
-  ignore (window#connect#destroy ~callback:GMain.quit);
-  ignore (window#event#connect#delete ~callback:quit);
-  ignore (quit_item#connect#activate
-            ~callback:(fun () -> ignore (quit ()); ()));
+(* Main. *)
+let () =
+  let cli_request = Cmdline.command_line () in
 
-  (* Top status area. *)
-  let hbox = GPack.hbox ~border_width:4 ~packing:vbox#pack () in
-  ignore (GMisc.label ~text:"Guest: " ~packing:hbox#pack ());
+  (* If we're in verbose mode, print some debug information which
+   * could be useful in bug reports.
+   *)
+  if verbose () then (
+    debug "%s %s" Config.package Config.version;
+    debug "libguestfs %s" (libguestfs_version_string ());
+    debug "libvirt %s" (libvirt_version_string ());
+  );
 
-  (* Throbber, http://faq.pygtk.org/index.py?req=show&file=faq23.037.htp *)
-  let static = Throbber.static () in
-  (*let animation = Throbber.animation () in*)
-  let throbber =
-    GMisc.image ~pixbuf:static ~packing:(hbox#pack ~from:`END) () in
-  let throbber_busy () =
-    (*throbber#set_pixbuf animation*)
-    (* Workaround because no binding for GdkPixbufAnimation: *)
-    let file = Filename.dirname Sys.argv.(0) // "Throbber.gif" in
-    throbber#set_file file
-  and throbber_idle () =
-    throbber#set_pixbuf static
-  in
+  (* Create the main window. *)
+  let w = new Window.window in
 
-  window#show ();
-  window#add_accel_group accel_group;
+  (* Wire up hooks that carry messages from the slave thread
+   * to the main thread.
+   *)
+  Slave.set_failure_hook w#failure;
+  Slave.set_busy_hook w#throbber_busy;
+  Slave.set_idle_hook w#throbber_idle;
+  Slave.set_status_hook w#set_statusbar;
+  Slave.set_progress_hook w#progress;
 
-  (* display_state which is threaded through all the other callbacks,
-   * allowing callbacks to update the window.
+  (* Wire up the loosely-coupled external components of the filetree.
+   * See the note about signals in {!Filetree.tree} documentation.
    *)
-  { window = window;
-    throbber_busy = throbber_busy; throbber_idle = throbber_idle }
+  let tree = w#tree in
+  ignore (tree#op_checksum_file
+            ~callback:(Op_checksum_file.checksum_file tree));
+  ignore (tree#op_copy_regvalue
+            ~callback:(Op_copy_regvalue.copy_regvalue tree));
+  ignore (tree#op_disk_usage
+            ~callback:(Op_disk_usage.disk_usage tree));
+  ignore (tree#op_download_as_reg
+            ~callback:(Op_download_as_reg.download_as_reg tree));
+  ignore (tree#op_download_dir_find0
+            ~callback:(Op_download_dir_find0.download_dir_find0 tree));
+  ignore (tree#op_download_dir_tarball
+            ~callback:(Op_download_dir_tarball.download_dir_tarball tree));
+  ignore (tree#op_download_file
+            ~callback:(Op_download_file.download_file tree));
+  ignore (tree#op_file_information
+            ~callback:(Op_file_information.file_information tree));
+  ignore (tree#op_inspection_dialog
+            ~callback:(Op_inspection_dialog.inspection_dialog tree));
+  ignore (tree#op_view_file
+            ~callback:(Op_view_file.view_file tree));
 
-let () =
-  let ds = open_main_window () in
-  Slave.set_failure_hook (failure ds);
-  Slave.set_busy_hook ds.throbber_busy;
-  Slave.set_idle_hook ds.throbber_idle;
+  (* Connect menu entry signals to the functions that implement them. *)
+  ignore (w#connect_kvm_signal
+            ~callback:(w#connect_to (Some "qemu:///system")));
+  ignore (w#connect_xen_signal
+            ~callback:(w#connect_to (Some "xen:///")));
+  ignore (w#connect_none_signal
+            ~callback:(w#connect_to None));
+
+  (* What did the user request on the command line? *)
+  w#run_cli_request cli_request;
 
   (* Run the main display thread.  When this returns, the application
    * has been closed.