[gnome-boxes] Create VM before 'review' page



commit 13bca42b991bb72143a49faa25ebff856fae930b
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Wed May 16 16:46:00 2012 +0300

    Create VM before 'review' page
    
    This means that we now move most of the failure points before arriving to
    review page. If user hits 'create' on the review page, the VM is simply
    launched. OTOH if user hits 'back' or 'cancel', the created VM is deleted
    along with its volume (cheap operation).
    
    Why do we need this change?
    
    If you look at the later commit, you'll notice that we at least need to
    create the configuration(s) before 'review' since we need information
    about the new domain to display to user. Now its an interesting question
    whether we should only create configuration before hand or the whole
    machine.
    
    The reasons I decided to go with the latter approach was:
    
    1. I recalled mccann saying that we should ensure that we have everything
    ready at the 'review' page. I agree with that since its better to error
    out during preparation and setup rather than after we told user that
    everything is ready, she/he clicks create and we go *boom*.
    
    2. IMHO it makes for a much better end-user experience if user has to
    wait less on each step rather than wait a long time on one step.
    
    3. I did try to change this to only create config before review page
    rather than the whole VM. The problem is that we can't create complete
    domain configuration before creation of main storage volume as we can
    only reliably get the path of the volume *after* the volume is
    created. So we'll either have to have a partial domain config at review
    and we add the volume's path at creation time (seems pretty ugly to me)
    or we create the volume before review page (which brings us to the same
    potential issues as with pre-creating the VM).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=674209

 src/app.vala    |    2 +
 src/wizard.vala |   69 +++++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 52 insertions(+), 19 deletions(-)
---
diff --git a/src/app.vala b/src/app.vala
index ede6b4b..9865ed4 100644
--- a/src/app.vala
+++ b/src/app.vala
@@ -523,6 +523,8 @@ private class Boxes.App: Boxes.UI {
                     machine.suspend.begin ();
             }
 
+        wizard.cleanup ();
+
         return false;
     }
 
diff --git a/src/wizard.vala b/src/wizard.vala
index bb143d5..3fb7f14 100644
--- a/src/wizard.vala
+++ b/src/wizard.vala
@@ -16,6 +16,7 @@ private class Boxes.Wizard: Boxes.UI {
     private GtkClutter.Actor gtk_actor;
     private GenericArray<Gtk.Label> steps;
     private Gtk.Notebook notebook;
+    private Gtk.Button cancel_button;
     private Gtk.Button back_button;
     private Gtk.Button next_button;
     private Boxes.WizardSource wizard_source;
@@ -30,11 +31,14 @@ private class Boxes.Wizard: Boxes.UI {
     private VMCreator vm_creator;
 
     private InstallerMedia? install_media;
+    private LibvirtMachine? machine;
 
     private WizardPage _page;
     private WizardPage page {
         get { return _page; }
         set {
+            back_button.sensitive = value != WizardPage.INTRODUCTION;
+
             var forwards = value > page;
 
             switch (value) {
@@ -67,20 +71,33 @@ private class Boxes.Wizard: Boxes.UI {
                     break;
 
                 case WizardPage.REVIEW:
-                    if (!review ())
-                        return;
+                    back_button.sensitive = false;
+                    next_button.sensitive = false;
+                    cancel_button.sensitive = false;
+                    review.begin ((source, result) => {
+                        back_button.sensitive = true;
+                        next_button.sensitive = true;
+                        cancel_button.sensitive = true;
+
+                        if (!review.end (result))
+                            page = page - 1;
+                    });
                     break;
 
                 case WizardPage.LAST:
                     skip_review_for_live = false;
-                    create.begin ((source, result) => {
-                        if (create.end (result))
-                            App.app.ui_state = UIState.COLLECTION;
-                        else
-                            App.app.notificationbar.display_error (_("Box creation failed!"));
-                    });
+                    if (create ())
+                       App.app.ui_state = UIState.COLLECTION;
+                    else
+                       App.app.notificationbar.display_error (_("Box creation failed!"));
                     return;
                 }
+            } else {
+                switch (page) {
+                case WizardPage.REVIEW:
+                    destroy_machine ();
+                    break;
+                }
             }
 
             if (skip_page (value))
@@ -97,7 +114,6 @@ private class Boxes.Wizard: Boxes.UI {
             /* highlight in white current page label */
             steps.get (page).modify_fg (Gtk.StateType.NORMAL, get_color ("white"));
 
-            back_button.sensitive = page != WizardPage.INTRODUCTION;
             next_button.label = page != WizardPage.REVIEW ? _("C_ontinue") : _("C_reate");
         }
     }
@@ -157,22 +173,26 @@ private class Boxes.Wizard: Boxes.UI {
         setup_ui ();
     }
 
-    private async bool create () {
+    public void cleanup () {
+        destroy_machine ();
+    }
+
+    private bool create () {
         if (source == null) {
             if (install_media == null)
                 return false;
 
             next_button.sensitive = false;
             try {
-                var machine = yield vm_creator.create_vm (install_media, null);
                 vm_creator.launch_vm (machine, install_media);
-            } catch (IOError.CANCELLED cancel_error) { // We did this, so ignore!
             } catch (GLib.Error error) {
                 warning (error.message);
+
                 return false;
             }
 
             install_media = null;
+            machine = null;
             wizard_source.uri = "";
 
             return true;
@@ -286,19 +306,22 @@ private class Boxes.Wizard: Boxes.UI {
         return true;
     }
 
-    private bool review () {
+    private async bool review () {
+        summary.clear ();
+
         if (install_media != null && install_media is UnattendedInstaller) {
             try {
                 (install_media as UnattendedInstaller).check_needed_info ();
-            } catch (UnattendedInstallerError.SETUP_INCOMPLETE error) {
+                machine = yield vm_creator.create_vm (install_media, null);
+            } catch (IOError.CANCELLED cancel_error) { // We did this, so ignore!
+                return false;
+            } catch (GLib.Error error) {
                 App.app.notificationbar.display_error (error.message);
 
                 return false;
             }
         }
 
-        summary.clear ();
-
         review_label.set_text (_("Will create a new box with the following properties:"));
 
         if (source != null) {
@@ -521,11 +544,12 @@ private class Boxes.Wizard: Boxes.UI {
         tool_item.child = label;
         toolbar.insert (tool_item, 0);
 
-        var cancel = new Gtk.Button.from_stock (Gtk.Stock.CANCEL);
+        cancel_button = new Gtk.Button.from_stock (Gtk.Stock.CANCEL);
         tool_item = new Gtk.ToolItem ();
-        tool_item.child = cancel;
+        tool_item.child = cancel_button;
         toolbar.insert (tool_item, 1);
-        cancel.clicked.connect (() => {
+        cancel_button.clicked.connect (() => {
+            destroy_machine ();
             wizard_source.page = SourcePage.MAIN;
             App.app.ui_state = UIState.COLLECTION;
         });
@@ -575,6 +599,13 @@ private class Boxes.Wizard: Boxes.UI {
         fade_actor (actor, opacity);
     }
 
+    private void destroy_machine () {
+        if (machine != null) {
+            machine.delete ();
+            machine = null;
+        }
+    }
+
     private class WizardSummary: GLib.Object {
         public Gtk.Widget widget { get { return table; } }
         private Gtk.Table table;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]