filetree_markup.cmi: slave_types.cmi
 filetree_markup.cmo: utils.cmi slave_types.cmi filetree_markup.cmi
 filetree_markup.cmx: utils.cmx slave_types.cmx filetree_markup.cmi
-main.cmo: window.cmi utils.cmi slave.cmi op_view_file.cmi op_inspection_dialog.cmi op_file_information.cmi op_download_file.cmi op_download_dir_tarball.cmi op_download_dir_find0.cmi op_download_as_reg.cmi op_disk_usage.cmi op_copy_regvalue.cmi op_checksum_file.cmi menu_open_uri.cmi menu_open_disk.cmi config.cmi cmdline.cmi
-main.cmx: window.cmx utils.cmx slave.cmx op_view_file.cmx op_inspection_dialog.cmx op_file_information.cmx op_download_file.cmx op_download_dir_tarball.cmx op_download_dir_find0.cmx op_download_as_reg.cmx op_disk_usage.cmx op_copy_regvalue.cmx op_checksum_file.cmx menu_open_uri.cmx menu_open_disk.cmx config.cmx cmdline.cmx
+main.cmo: window.cmi utils.cmi slave.cmi op_view_file.cmi op_inspection_dialog.cmi op_file_information.cmi op_download_file.cmi op_download_dir_tarball.cmi op_download_dir_find0.cmi op_download_as_reg.cmi op_disk_usage.cmi op_copy_regvalue.cmi op_checksum_file.cmi menu_open_uri.cmi menu_open_disk.cmi menu_about.cmi config.cmi cmdline.cmi
+main.cmx: window.cmx utils.cmx slave.cmx op_view_file.cmx op_inspection_dialog.cmx op_file_information.cmx op_download_file.cmx op_download_dir_tarball.cmx op_download_dir_find0.cmx op_download_as_reg.cmx op_disk_usage.cmx op_copy_regvalue.cmx op_checksum_file.cmx menu_open_uri.cmx menu_open_disk.cmx menu_about.cmx config.cmx cmdline.cmx
+menu_about.cmi: window.cmi
+menu_about.cmo: utils.cmi config.cmi menu_about.cmi
+menu_about.cmx: utils.cmx config.cmx menu_about.cmi
 menu_open_disk.cmi: window.cmi
 menu_open_disk.cmo: utils.cmi menu_open_disk.cmi
 menu_open_disk.cmx: utils.cmx menu_open_disk.cmi
 
        filetree_markup.mli \
        filetree_markup.ml \
        main.ml \
+       menu_about.mli \
+       menu_about.ml \
        menu_open_disk.mli \
        menu_open_disk.ml \
        menu_open_uri.mli \
        op_view_file.cmo \
        menu_open_uri.cmo \
        menu_open_disk.cmo \
+       menu_about.cmo \
        window.cmo \
        main.cmo
 
 
 If the mount points are the same as the previous command, it
 should cache them.
 
-About dialog
-
 Extended attributes, SELinux.
 
               Op_inspection_dialog.inspection_dialog tree os
       )
   );
+  ignore (w#about_signal ~callback:(Menu_about.open_about_dialog w));
 
   (* What did the user request on the command line? *)
   w#run_cli_request cli_request;
 
--- /dev/null
+(* Guestfs Browser.
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+open Utils
+
+open Printf
+
+let license =
+  "\
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA."
+
+let authors = [
+  "Richard W.M. Jones"
+]
+
+let logo =
+  let rec loop = function
+    | [] -> None
+    | filename :: rest ->
+        try Some (GdkPixbuf.from_file_at_size ~width:100 ~height:100 filename)
+        with _ -> loop rest
+  in
+  loop [Config.icondir ^ "/guestfs-browser.svg";
+        "guestfs-browser.svg"]
+
+let open_about_dialog w () =
+  let d = GWindow.about_dialog
+    ~name:"Guest filesystem browser"
+    ~version:Config.version
+    ?logo
+    ~authors
+    ~copyright:(utf8_copyright ^ " 2010-2011 Red Hat Inc.")
+    ~license
+    ~website:"http://people.redhat.com/~rjones/guestfs-browser/"
+    ~website_label:"Visit the guestfs-browser website"
+    ~modal:true
+    () in
+
+  ignore (d#run ());
+  d#destroy ()
 
--- /dev/null
+(* Guestfs Browser.
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+(** Help -> About dialog. *)
+
+val open_about_dialog : Window.window -> unit -> unit
 
 let set_connect_uri conn = connect_uri := conn
 let connect_uri () = !connect_uri
 
+let utf8_copyright = "\194\169"
 let utf8_rarrow = "\xe2\x86\x92"
 
 let pretty_string_of_exn =
 
       To get raw exception string, use {!Printexc.to_string} from the
       standard library. *)
 
+val utf8_copyright : string (** UTF-8 copyright symbol *)
 val utf8_rarrow : string (** UTF-8 RIGHTWARDS ARROW *)
 
 val human_size : int64 -> string
 
   guest_inspection_item : GMenu.menu_item;
 }
 
+type help_menu = {
+  help_menu : GMenu.menu;
+  about_item : GMenu.menu_item;
+}
+
 class window =
   (* Window. *)
   let title = "Guest Filesystem Browser" in
     let inspection = factory#add_item "Operating system information ..." in
     { guest_menu = menu; guest_inspection_item = inspection } in
 
+  let help_menu =
+    let menu = factory#add_submenu "_Help" in
+    let factory = new GMenu.factory menu ~accel_group in
+    let about = factory#add_item "About guest filesystem browser ..." in
+    { help_menu = menu; about_item = about } in
+
   (* Top toolbar. *)
   let hbox =
     let hbox = GPack.hbox ~border_width:4 ~packing:vbox#pack () in
   let open_disk_signal = new GUtil.signal () in
   let reopen_signal = new GUtil.signal () in
   let inspection_signal = new GUtil.signal () in
+  let about_signal = new GUtil.signal () in
 
 object (self)
   inherit GUtil.ml_signals [connect_kvm_signal#disconnect;
                             connect_uri_signal#disconnect;
                             open_disk_signal#disconnect;
                             reopen_signal#disconnect;
-                            inspection_signal#disconnect]
+                            inspection_signal#disconnect;
+                            about_signal#disconnect]
 
   method connect_kvm_signal = connect_kvm_signal#connect ~after
   method connect_xen_signal = connect_xen_signal#connect ~after
   method open_disk_signal = open_disk_signal#connect ~after
   method reopen_signal = reopen_signal#connect ~after
   method inspection_signal = inspection_signal#connect ~after
+  method about_signal = about_signal#connect ~after
 
   initializer
     ignore (statusbar_context#push title);
               ~callback:reopen_signal#call);
     ignore (guest_menu.guest_inspection_item#connect#activate
               ~callback:inspection_signal#call);
+    ignore (help_menu.about_item#connect#activate
+              ~callback:about_signal#call);
 
     (* VM combo box when changed by the user.
      * The refresh button acts like changing the VM combo too.
 
   method open_disk_signal : callback:(unit -> unit) -> GtkSignal.id
   method reopen_signal : callback:(unit -> unit) -> GtkSignal.id
   method inspection_signal : callback:(unit -> unit) -> GtkSignal.id
+  method about_signal : callback:(unit -> unit) -> GtkSignal.id
 
   method failure : exn -> unit
     (** This is the global error handling function.  It is invoked in