[gnome-boxes] Allow customization of box in creation wizard



commit e37e4da010d4eafebbd3f6a9b38580b5fc1c660d
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Thu Aug 30 00:55:08 2012 +0300

    Allow customization of box in creation wizard
    
    This patch adds a 'Customize..." button at the review page, as shown in
    the design mockup[1], that takes users to properties view to allow them
    to configure various properties before launching the box.
    
    The properties view should be showing 'media-optical' theme icon like in
    the mockup[2] but we can add that later. Current priority is to have
    this feature working before 3.6 release.
    
    Known issue: If you configure the spice props in wizard, you might get
    warnings like these on hitting 'Create' button:
    
    (gnome-boxes:8748): GSpice-CRITICAL **: spice_main_set_display: assertion `channel != NULL' failed
    
    (gnome-boxes:8748): GSpice-WARNING **: Warning no automount-inhibiting implementation available
    
    [1] https://github.com/gnome-design-team/gnome-mockups/raw/master/boxes/boxes-install5.png
    [2] https://github.com/gnome-design-team/gnome-mockups/raw/master/boxes/boxes-install5.5.png
    
    https://bugzilla.gnome.org/show_bug.cgi?id=672554

 src/app.vala             |    8 ++++++-
 src/libvirt-machine.vala |   51 ++++++++++++++++++++++++++++-----------------
 src/machine.vala         |    5 ++++
 src/properties.vala      |    2 +-
 src/wizard.vala          |   25 +++++++++++++++++++--
 5 files changed, 67 insertions(+), 24 deletions(-)
---
diff --git a/src/app.vala b/src/app.vala
index d8cbbce..082f0fa 100644
--- a/src/app.vala
+++ b/src/app.vala
@@ -526,7 +526,9 @@ private class Boxes.App: Boxes.UI {
         action_properties.set_enabled (ui_state == UIState.DISPLAY);
         action_shutdown.set_enabled (ui_state == UIState.DISPLAY && current_item is LibvirtMachine);
 
-        foreach (var ui in new Boxes.UI[] { sidebar, searchbar, topbar, view, wizard, properties }) {
+        // The order is important for some widgets here (e.g properties must change its state before wizard so it can
+        // flush any deferred changes for wizard to pick-up when going back from properties to wizard (review).
+        foreach (var ui in new Boxes.UI[] { sidebar, searchbar, topbar, view, properties, wizard }) {
             ui.ui_state = ui_state;
         }
 
@@ -656,6 +658,10 @@ private class Boxes.App: Boxes.UI {
                 warning ("unknown item, fix your code");
 
             item_selected (item);
+        } else if (ui_state == UIState.WIZARD) {
+            current_item = item;
+
+            ui_state = UIState.PROPERTIES;
         }
     }
 }
diff --git a/src/libvirt-machine.vala b/src/libvirt-machine.vala
index c1b6fbe..e59f380 100644
--- a/src/libvirt-machine.vala
+++ b/src/libvirt-machine.vala
@@ -293,13 +293,22 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
     public override List<Boxes.Property> get_properties (Boxes.PropertiesPage page) {
         var list = new List<Boxes.Property> ();
 
+        var display = this.display;
+        if (display == null)
+            try {
+                display = create_display ();
+            } catch (GLib.Error error) {
+                warning (error.message);
+            }
+
         switch (page) {
         case PropertiesPage.LOGIN:
             add_string_property (ref list, _("Name"), name, (property, name) => {
                 try_change_name (name);
             });
             add_string_property (ref list, _("Virtualizer"), source.uri);
-            add_string_property (ref list, _("URI"), display.uri);
+            if (display != null)
+                add_string_property (ref list, _("URI"), display.uri);
             break;
 
         case PropertiesPage.SYSTEM:
@@ -308,46 +317,48 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
             break;
 
         case PropertiesPage.DISPLAY:
-            add_string_property (ref list, _("Protocol"), display.protocol);
+            if (display != null)
+                add_string_property (ref list, _("Protocol"), display.protocol);
             break;
         }
 
-        list.concat (display.get_properties (page));
+        if (display != null)
+            list.concat (display.get_properties (page));
 
         return list;
     }
 
     private void update_display () {
-        string type, port, socket, host;
-
         update_domain_config ();
 
         try {
-            var xmldoc = domain_config.to_xml ();
-            type = extract_xpath (xmldoc, "string(/domain/devices/graphics/@type)", true);
-            port = extract_xpath (xmldoc, @"string(/domain/devices/graphics[ type='$type']/@port)");
-            socket = extract_xpath (xmldoc, @"string(/domain/devices/graphics[ type='$type']/@socket)");
-            host = extract_xpath (xmldoc, @"string(/domain/devices/graphics[ type='$type']/@listen)");
+            display = create_display ();
         } catch (GLib.Error error) {
             warning (error.message);
-            return;
         }
+    }
+
+    private Display? create_display () throws Boxes.Error {
+        string type, port, socket, host;
+
+        var xmldoc = domain_config.to_xml ();
+        type = extract_xpath (xmldoc, "string(/domain/devices/graphics/@type)", true);
+        port = extract_xpath (xmldoc, @"string(/domain/devices/graphics[ type='$type']/@port)");
+        socket = extract_xpath (xmldoc, @"string(/domain/devices/graphics[ type='$type']/@socket)");
+        host = extract_xpath (xmldoc, @"string(/domain/devices/graphics[ type='$type']/@listen)");
 
         if (host == null || host == "")
             host = "localhost";
 
         switch (type) {
         case "spice":
-            display = new SpiceDisplay (config, host, int.parse (port));
-            break;
+            return new SpiceDisplay (config, host, int.parse (port));
 
         case "vnc":
-            display = new VncDisplay (config, host, int.parse (port));
-            break;
+            return new VncDisplay (config, host, int.parse (port));
 
         default:
-            warning ("unsupported display of type " + type);
-            break;
+            throw new Boxes.Error.INVALID ("unsupported display of type " + type);
         }
     }
 
@@ -527,7 +538,8 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
                 config.memory = value;
                 domain.set_config (config);
                 debug ("RAM changed to %llu", value);
-                notify_reboot_required ();
+                if (state == MachineState.RUNNING || state == MachineState.PAUSED)
+                    notify_reboot_required ();
             } catch (GLib.Error error) {
                 warning ("Failed to change RAM of box '%s' to %llu: %s",
                          domain.get_name (),
@@ -535,7 +547,8 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
                          error.message);
             }
 
-            update_ram_property (property);
+            if (state == MachineState.RUNNING || state == MachineState.PAUSED)
+                update_ram_property (property);
 
             return false;
         };
diff --git a/src/machine.vala b/src/machine.vala
index 7fa422b..e1f742e 100644
--- a/src/machine.vala
+++ b/src/machine.vala
@@ -642,6 +642,11 @@ private class Boxes.MachineActor: Boxes.UI {
             break;
 
         case UIState.PROPERTIES:
+            if (previous_ui_state == UIState.WIZARD)
+                // FIXME: We should draw a CD instead as in the mockup:
+                //        https://github.com/gnome-design-team/gnome-mockups/raw/master/boxes/boxes-install5.5.png
+                break;
+
             var widget = App.app.display_page.remove_display ();
             update_display (widget);
             Clutter.ActorBox box = { 0, 0,  width, height};
diff --git a/src/properties.vala b/src/properties.vala
index 01de259..3964762 100644
--- a/src/properties.vala
+++ b/src/properties.vala
@@ -189,7 +189,7 @@ private class Boxes.Properties: Boxes.UI {
         hbox.pack_start (toolbar, true, true, 0);
         back = toolbar.add_button (null, null, true) as Gtk.Button;
         back.child = box;
-        back.clicked.connect ((button) => { App.app.ui_state = UIState.DISPLAY; });
+        back.clicked.connect ((button) => { App.app.ui_state = App.app.previous_ui_state; });
 
         hbox.show_all ();
 
diff --git a/src/wizard.vala b/src/wizard.vala
index 24c40cf..7078816 100644
--- a/src/wizard.vala
+++ b/src/wizard.vala
@@ -315,7 +315,7 @@ private class Boxes.Wizard: Boxes.UI {
         nokvm_label.hide ();
         summary.clear ();
 
-        if (vm_creator != null) {
+        if (vm_creator != null && machine == null) {
             try {
                 machine = yield vm_creator.create_vm (null);
             } catch (IOError.CANCELLED cancel_error) { // We did this, so ignore!
@@ -386,6 +386,11 @@ private class Boxes.Wizard: Boxes.UI {
             nokvm_label.visible = (machine.domain_config.get_virt_type () != GVirConfig.DomainVirtType.KVM);
         }
 
+        summary.append_customize_button (() => {
+            // Selecting an item in UIState.WIZARD implies changing state to UIState.PROPERTIES
+            App.app.select_item (machine);
+        });
+
         return true;
     }
 
@@ -601,7 +606,10 @@ private class Boxes.Wizard: Boxes.UI {
         uint opacity = 0;
         switch (ui_state) {
         case UIState.WIZARD:
-            page = WizardPage.INTRODUCTION;
+            if (previous_ui_state == UIState.PROPERTIES)
+                review.begin ();
+            else
+                page = WizardPage.INTRODUCTION;
             opacity = 255;
             break;
         }
@@ -617,12 +625,14 @@ private class Boxes.Wizard: Boxes.UI {
     }
 
     private class WizardSummary: GLib.Object {
+        public delegate void CustomizeFunc ();
+
         public Gtk.Widget widget { get { return table; } }
         private Gtk.Table table;
         private uint current_row;
 
         public WizardSummary () {
-            table = new Gtk.Table (1, 2, false);
+            table = new Gtk.Table (1, 3, false);
             table.row_spacing = 10;
             table.column_spacing = 20;
 
@@ -647,6 +657,15 @@ private class Boxes.Wizard: Boxes.UI {
             table.show_all ();
         }
 
+        public void append_customize_button (CustomizeFunc cutomize_func) {
+            var button = new Gtk.Button.with_mnemonic (_("C_ustomize..."));
+            button.modify_fg (Gtk.StateType.NORMAL, get_color ("white"));
+            table.attach_defaults (button, 2, 3, current_row - 1, current_row);
+            button.show ();
+
+            button.clicked.connect (() => { cutomize_func (); });
+        }
+
         public void clear () {
             foreach (var child in table.get_children ()) {
                 table.remove (child);



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