[gnome-boxes] Add properties page



commit ec2395035170cef62d2ab72c8fd0449a8c56f63a
Author: Marc-Andrà Lureau <marcandre lureau gmail com>
Date:   Thu Oct 27 16:17:49 2011 +0200

    Add properties page

 src/Makefile.am          |    3 +-
 src/app.vala             |   32 ++++++---
 src/collection-view.vala |   86 ++++++++++++++----------
 src/display-page.vala    |   34 +++++++---
 src/machine.vala         |   28 +++++----
 src/properties.vala      |  165 ++++++++++++++++++++++++++++++++++++++++++++++
 src/sidebar.vala         |   16 ++++-
 src/spice-display.vala   |    8 +-
 src/topbar.vala          |   15 ++++-
 src/ui.vala              |    5 +-
 src/wizard.vala          |    4 +-
 11 files changed, 311 insertions(+), 85 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 5ecf99f..bf92a5a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,6 +30,7 @@ bin_PROGRAMS = gnome-boxes gnome-boxes-installer
 
 gnome_boxes_SOURCES =				\
 	app.vala				\
+	boxes-main.vala				\
 	collection-source.vala			\
 	collection-view.vala			\
 	collection.vala				\
@@ -37,7 +38,7 @@ gnome_boxes_SOURCES =				\
 	display.vala				\
 	libvirt-machine.vala			\
 	machine.vala				\
-	boxes-main.vala				\
+	properties.vala				\
 	remote-machine.vala			\
 	sidebar.vala				\
 	spice-display.vala			\
diff --git a/src/app.vala b/src/app.vala
index 18c12c3..14c4a94 100644
--- a/src/app.vala
+++ b/src/app.vala
@@ -22,6 +22,7 @@ private class Boxes.App: Boxes.UI {
     public static const uint duration = 555;  // default to 1/2 for all transitions
     public static GLib.Settings settings;
     public Wizard wizard;
+    public Properties properties;
     public DisplayPage display_page;
 
     private Clutter.TableLayout box_table;
@@ -128,7 +129,7 @@ private class Boxes.App: Boxes.UI {
 
     private void setup_ui () {
         window = new Gtk.Window ();
-        window.set_default_size (640, 480);
+        window.set_default_size (680, 480);
         notebook = new Gtk.Notebook ();
         notebook.show_border = false;
         notebook.show_tabs = false;
@@ -160,11 +161,21 @@ private class Boxes.App: Boxes.UI {
         window.show_all ();
 
         wizard = new Wizard (this);
+        properties = new Properties (this);
+
         ui_state = UIState.COLLECTION;
     }
 
+    private void set_main_ui_state (string clutter_state) {
+        notebook.page = Boxes.AppPage.MAIN;
+        box.set_layout_manager (box_table);
+        state.set_state (clutter_state);
+    }
+
     public override void ui_state_changed () {
-        foreach (var o in new Boxes.UI[] { sidebar, topbar, view, wizard }) {
+        box.set_layout_manager (box_table);
+
+        foreach (var o in new Boxes.UI[] { sidebar, topbar, view, wizard, properties }) {
             o.ui_state = ui_state;
         }
 
@@ -175,9 +186,7 @@ private class Boxes.App: Boxes.UI {
             break;
 
         case UIState.CREDS:
-            notebook.page = Boxes.AppPage.MAIN;
-            box.set_layout_manager (box_table);
-            state.set_state ("creds");
+            set_main_ui_state ("creds");
             break;
 
         case UIState.COLLECTION:
@@ -187,14 +196,12 @@ private class Boxes.App: Boxes.UI {
                 machine.disconnect_display ();
                 machine.update_screenshot.begin ();
             }
-            notebook.page = Boxes.AppPage.MAIN;
-            box.set_layout_manager (box_table);
-            state.set_state ("collection");
+            set_main_ui_state ("collection");
             break;
 
+        case UIState.PROPERTIES:
         case UIState.WIZARD:
-            notebook.page = Boxes.AppPage.MAIN;
-            box.set_layout_manager (box_table);
+            set_main_ui_state ("collection");
             break;
 
         default:
@@ -221,6 +228,11 @@ private class Boxes.App: Boxes.UI {
     }
 
     private bool item_clicked (CollectionItem item, Clutter.ButtonEvent event) {
+        message ("button %u".printf (event.button));
+
+        if (Clutter.ModifierType.BUTTON2_MASK in event.modifier_state)
+            return false;
+
         if (ui_state == UIState.COLLECTION) {
             current_item = item;
 
diff --git a/src/collection-view.vala b/src/collection-view.vala
index a9d4a1b..f724aaa 100644
--- a/src/collection-view.vala
+++ b/src/collection-view.vala
@@ -15,15 +15,41 @@ private class Boxes.CollectionView: Boxes.UI {
         setup_view ();
     }
 
+    private void set_main_ui_state () {
+        actor_remove (app.wizard.actor);
+        actor_remove (app.properties.actor);
+
+        if (app.current_item != null) {
+            actor_remove (app.current_item.actor);
+            add_item (app.current_item);
+        }
+
+        /* follow main table layout again */
+        actor_unpin (boxes);
+        boxes.set_position (15f, 15f);
+        margin.add_constraint_with_name ("boxes-left",
+                                         new Clutter.SnapConstraint (app.stage, SnapEdge.RIGHT, SnapEdge.RIGHT, 0));
+        margin.add_constraint_with_name ("boxes-bottom",
+                                         new Clutter.SnapConstraint (app.stage, SnapEdge.BOTTOM, SnapEdge.RIGHT.BOTTOM, 0));
+        /* normal flow items */
+        boxes.set_layout_manager (layout);
+
+        actor_remove (over_boxes);
+    }
+
+    public void set_over_boxes () {
+        remove_item (app.current_item);
+        over_boxes.pack (app.current_item.actor,
+                         "x-align", Clutter.BinAlignment.CENTER,
+                         "y-align", Clutter.BinAlignment.CENTER);
+        actor_add (over_boxes, app.stage);
+    }
+
     public override void ui_state_changed () {
         switch (ui_state) {
         case UIState.CREDS:
-            remove_item (app.current_item);
-            over_boxes.pack (app.current_item.actor,
-                             "x-align", Clutter.BinAlignment.CENTER,
-                             "y-align", Clutter.BinAlignment.CENTER);
+            set_over_boxes ();
             app.current_item.ui_state = UIState.CREDS;
-            actor_add (over_boxes, app.stage);
 
             /* item don't move anymore */
             boxes.set_layout_manager (new Clutter.FixedLayout ());
@@ -34,18 +60,20 @@ private class Boxes.CollectionView: Boxes.UI {
             float x, y;
             var display = app.current_item.actor;
 
-            /* move display/machine actor to stage, keep same position */
-            display.get_transformed_position (out x, out y);
-            actor_remove (display);
-            actor_add (display, app.stage);
-            display.set_position (x, y);
-
-            /* make sure the boxes stay where they are */
-            boxes.get_transformed_position (out x, out y);
-            boxes.set_position (x, y);
-            actor_pin (boxes);
-            margin.remove_constraint_by_name ("boxes-left");
-            margin.remove_constraint_by_name ("boxes-bottom");
+            if (previous_ui_state == UIState.CREDS) {
+                /* move display/machine actor to stage, keep same position */
+                display.get_transformed_position (out x, out y);
+                actor_remove (display);
+                actor_add (display, app.stage);
+                display.set_position (x, y);
+
+                /* make sure the boxes stay where they are */
+                boxes.get_transformed_position (out x, out y);
+                boxes.set_position (x, y);
+                actor_pin (boxes);
+                margin.remove_constraint_by_name ("boxes-left");
+                margin.remove_constraint_by_name ("boxes-bottom");
+            }
 
             app.current_item.ui_state = UIState.DISPLAY;
 
@@ -53,29 +81,13 @@ private class Boxes.CollectionView: Boxes.UI {
         }
 
         case UIState.COLLECTION:
-            actor_remove (app.wizard.actor);
-
-            if (app.current_item != null) {
-                actor_remove (app.current_item.actor);
-                add_item (app.current_item);
-            }
-
-            /* follow main table layout again */
-            actor_unpin (boxes);
-            boxes.set_position (15f, 15f);
-            margin.add_constraint_with_name ("boxes-left",
-                                             new Clutter.SnapConstraint (app.stage, SnapEdge.RIGHT, SnapEdge.RIGHT, 0));
-            margin.add_constraint_with_name ("boxes-bottom",
-                                             new Clutter.SnapConstraint (app.stage, SnapEdge.BOTTOM, SnapEdge.RIGHT.BOTTOM, 0));
-            /* normal flow items */
-            boxes.set_layout_manager (layout);
-
-            actor_remove (over_boxes);
-
+            set_main_ui_state ();
             break;
 
         case UIState.WIZARD:
-            over_boxes.pack (app.wizard.actor);
+        case UIState.PROPERTIES:
+            set_main_ui_state ();
+            over_boxes.pack (ui_state == UIState.WIZARD ? app.wizard.actor : app.properties.actor);
             app.wizard.actor.add_constraint (new Clutter.BindConstraint (over_boxes, BindCoordinate.SIZE, 0));
             actor_add (over_boxes, app.stage);
             break;
diff --git a/src/display-page.vala b/src/display-page.vala
index 55588ff..a57ef5d 100644
--- a/src/display-page.vala
+++ b/src/display-page.vala
@@ -25,15 +25,22 @@ private class Boxes.DisplayPage: GLib.Object {
             if (event.type == EventType.MOTION_NOTIFY) {
                 var y = event.motion.y;
 
-                if (y <= 20 && toolbar_show_id == 0) {
+                if (y <= 50 && toolbar_show_id == 0) {
                     toolbar_event_stop ();
                     toolbar_show_id = Timeout.add (app.duration, () => {
                         toolbar.show_all ();
                         toolbar_show_id = 0;
                         return false;
                     });
-                } else if (y > 5)
+                } else if (y > 20) {
                     toolbar_event_stop (true, false);
+                    if (toolbar_hide_id == 0)
+                        toolbar_hide_id = Timeout.add (app.duration, () => {
+                            toolbar.hide ();
+                            toolbar_hide_id = 0;
+                            return false;
+                        });
+                }
             }
 
             if (event_box.get_child () != null)
@@ -50,7 +57,7 @@ private class Boxes.DisplayPage: GLib.Object {
         toolbar.get_style_context ().add_class (STYLE_CLASS_MENUBAR);
 
         var back = new ToolButton (null, null);
-        back.icon_name =  "go-previous-symbolic";
+        back.icon_name = "go-previous-symbolic";
         back.get_style_context ().add_class ("raised");
         back.clicked.connect ((button) => { app.ui_state = UIState.COLLECTION; });
         toolbar.insert (back, 0);
@@ -62,8 +69,14 @@ private class Boxes.DisplayPage: GLib.Object {
         item.set_expand (true);
         toolbar.insert (item, -1);
 
-        toolbar.set_halign (Align.FILL);
-        toolbar.set_valign (Align.START);
+        var props = new ToolButton (null, null);
+        props.icon_name = "go-next-symbolic";
+        props.get_style_context ().add_class ("raised");
+        props.clicked.connect ((button) => { app.ui_state = UIState.PROPERTIES; });
+        toolbar.insert (props, -1);
+
+        toolbar.set_show_arrow (false);
+        toolbar.set_valign (Gtk.Align.START);
 
         overlay.add_overlay (toolbar);
         overlay.show_all ();
@@ -87,6 +100,10 @@ private class Boxes.DisplayPage: GLib.Object {
         }
     }
 
+    public void show () {
+        app.notebook.page = Boxes.AppPage.DISPLAY;
+    }
+
     public void show_display (Boxes.Machine machine, Widget display) {
         remove_display ();
         toolbar.hide ();
@@ -101,11 +118,6 @@ private class Boxes.DisplayPage: GLib.Object {
                 break;
             case EventType.ENTER_NOTIFY:
                 toolbar_event_stop ();
-                toolbar_hide_id = Timeout.add (app.duration, () => {
-                    toolbar.hide ();
-                    toolbar_hide_id = 0;
-                    return false;
-                });
                 break;
             }
             return false;
@@ -115,7 +127,7 @@ private class Boxes.DisplayPage: GLib.Object {
             event_box.get_window ().set_cursor (display.get_window ().cursor);
         });
 
-        app.notebook.page = Boxes.AppPage.DISPLAY;
+        show ();
     }
 
     public void remove_display () {
diff --git a/src/machine.vala b/src/machine.vala
index dc94484..3c561a5 100644
--- a/src/machine.vala
+++ b/src/machine.vala
@@ -141,8 +141,8 @@ private abstract class Boxes.Machine: Boxes.CollectionItem {
 
         try {
             machine_actor.set_screenshot (pixbuf);
-        } catch (GLib.Error err) {
-            warning (err.message);
+        } catch (GLib.Error error) {
+            warning (error.message);
         }
     }
 
@@ -303,17 +303,21 @@ private class Boxes.MachineActor: Boxes.UI {
             break;
 
         case UIState.DISPLAY:
-            int width, height;
+            if (previous_ui_state == UIState.CREDS) {
+                int width, height;
+
+                password_entry.hide ();
+                label.hide ();
+                machine.app.window.get_size (out width, out height);
+                screenshot.animate (Clutter.AnimationMode.LINEAR, Boxes.App.duration,
+                                    "width", (float) width,
+                                    "height", (float) height);
+                actor.animate (Clutter.AnimationMode.LINEAR, Boxes.App.duration,
+                               "x", 0.0f,
+                               "y", 0.0f);
+            } else
+                machine.app.display_page.show ();
 
-            password_entry.hide ();
-            label.hide ();
-            machine.app.window.get_size (out width, out height);
-            screenshot.animate (Clutter.AnimationMode.LINEAR, Boxes.App.duration,
-                                "width", (float) width,
-                                "height", (float) height);
-            actor.animate (Clutter.AnimationMode.LINEAR, Boxes.App.duration,
-                           "x", 0.0f,
-                           "y", 0.0f);
             break;
 
         case UIState.COLLECTION:
diff --git a/src/properties.vala b/src/properties.vala
new file mode 100644
index 0000000..aec3c28
--- /dev/null
+++ b/src/properties.vala
@@ -0,0 +1,165 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+using Gtk;
+
+private enum Boxes.PropertiesPage {
+    LOGIN,
+    DISPLAY,
+    DEVICES,
+
+    LAST,
+}
+
+private class Boxes.Properties: Boxes.UI {
+    public override Clutter.Actor actor { get { return gtk_actor; } }
+
+    private GtkClutter.Actor gtk_actor;
+    private Boxes.App app;
+    private Gtk.Notebook notebook;
+    private Gtk.ToolButton back;
+    private Gtk.Label toolbar_label;
+    private Gtk.ListStore listmodel;
+    private Gtk.TreeView tree_view;
+
+    private class PageWidget {
+        public Gtk.Widget widget;
+        public string name;
+
+        private Gtk.Table table;
+
+        public PageWidget (PropertiesPage page, Machine machine) {
+            switch (page) {
+            case PropertiesPage.LOGIN:
+                name = _("Login");
+                break;
+
+            case PropertiesPage.DISPLAY:
+                name = _("Display");
+                break;
+
+            case PropertiesPage.DEVICES:
+                name = _("Devices");
+                break;
+            }
+
+            var vbox = new Gtk.VBox (false, 10);
+            table = new Gtk.Table (1, 2, false);
+            vbox.pack_start (table, false, false, 0);
+            table.margin = 20;
+            table.row_spacing = 10;
+            table.column_spacing = 20;
+
+            table.resize (1, 2);
+            var label = new Gtk.Label (name);
+            label.get_style_context ().add_class ("boxes-step-label");
+            label.margin_bottom = 10;
+            label.xalign = 0.0f;
+            table.attach_defaults (label, 0, 2, 0, 1);
+
+            vbox.show_all ();
+            widget = vbox;
+        }
+
+        public bool is_empty () {
+            return false;
+        }
+    }
+
+    public Properties (App app) {
+        this.app = app;
+
+        setup_ui ();
+    }
+
+    private void list_append (Gtk.ListStore listmodel, string label) {
+        Gtk.TreeIter iter;
+
+        listmodel.append (out iter);
+        listmodel.set (iter, 0, label);
+    }
+
+    private void populate () {
+        listmodel.clear ();
+        for (var i = 0; i < PropertiesPage.LAST; i++)
+            notebook.remove_page (i);
+
+        if (app.current_item == null)
+            return;
+
+        for (var i = 0; i < PropertiesPage.LAST; i++) {
+            var page = new PageWidget (i, app.current_item as Machine);
+            notebook.append_page (page.widget, null);
+
+            if (!page.is_empty ())
+                list_append (listmodel, page.name);
+        }
+
+        tree_view.get_selection ().select_path (new Gtk.TreePath.from_string ("0"));
+    }
+
+    private void setup_ui () {
+        notebook = new Gtk.Notebook ();
+        notebook.show_tabs = false;
+        notebook.get_style_context ().add_class ("boxes-bg");
+        gtk_actor = new GtkClutter.Actor.with_contents (notebook);
+
+        /* topbar */
+        var hbox = app.topbar.notebook.get_nth_page (Boxes.TopbarPage.PROPERTIES) as Gtk.HBox;
+
+        var toolbar = new Toolbar ();
+        toolbar.set_valign (Align.CENTER);
+        toolbar.icon_size = IconSize.MENU;
+        toolbar.get_style_context ().add_class (STYLE_CLASS_MENUBAR);
+        toolbar.set_show_arrow (false);
+
+        var toolbar_box = new Gtk.HBox (false, 0);
+        toolbar_box.set_size_request (50, (int) Boxes.Topbar.height);
+        toolbar_box.add (toolbar);
+
+        var box = new Gtk.HBox (false, 5);
+        box.add (new Gtk.Image.from_icon_name ("go-previous-symbolic", Gtk.IconSize.MENU));
+        toolbar_label = new Gtk.Label ("label");
+        box.add (toolbar_label);
+        back = new ToolButton (box, null);
+        back.get_style_context ().add_class ("raised");
+        back.clicked.connect ((button) => { app.ui_state = UIState.DISPLAY; });
+        toolbar.insert (back, 0);
+        hbox.pack_start (toolbar_box, true, true, 0);
+
+        hbox.show_all ();
+
+        /* sidebar */
+        var vbox = app.sidebar.notebook.get_nth_page (Boxes.SidebarPage.PROPERTIES) as Gtk.VBox;
+
+        var image = new Gtk.Image ();
+        image.set_size_request (180, 125);
+        image.margin = 15;
+        vbox.pack_start (image, false, false, 0);
+
+        tree_view = new Gtk.TreeView ();
+        var selection = tree_view.get_selection ();
+        selection.set_mode (Gtk.SelectionMode.BROWSE);
+        tree_view_activate_on_single_click (tree_view, true);
+        tree_view.row_activated.connect ( (treeview, path, column) => {
+            notebook.page = path.get_indices ()[0];
+        });
+
+        listmodel = new Gtk.ListStore (1, typeof (string));
+        tree_view.set_model (listmodel);
+        tree_view.headers_visible = false;
+        var renderer = new CellRendererText ();
+        tree_view.insert_column_with_attributes (-1, "", renderer, "text", 0);
+        vbox.pack_start (tree_view, true, true, 0);
+
+        vbox.show_all ();
+        notebook.show_all ();
+    }
+
+    public override void ui_state_changed () {
+        switch (ui_state) {
+        case UIState.PROPERTIES:
+            toolbar_label.label = app.current_item.name;
+            populate ();
+            break;
+        }
+    }
+}
diff --git a/src/sidebar.vala b/src/sidebar.vala
index 5ad5c33..0e5c992 100644
--- a/src/sidebar.vala
+++ b/src/sidebar.vala
@@ -6,6 +6,7 @@ using Clutter;
 private enum Boxes.SidebarPage {
     COLLECTION,
     WIZARD,
+    PROPERTIES,
 }
 
 private class Boxes.Sidebar: Boxes.UI {
@@ -34,7 +35,7 @@ private class Boxes.Sidebar: Boxes.UI {
 
     public Sidebar (App app) {
         this.app = app;
-        width = 180;
+        width = 200;
 
         setup_sidebar ();
     }
@@ -46,18 +47,21 @@ private class Boxes.Sidebar: Boxes.UI {
             app.box.pack (gtk_actor, "column", 0, "row", 0, "row-span", 2, "x-expand", false, "y-expand", true);
             notebook.page = SidebarPage.COLLECTION;
             break;
+
         case UIState.DISPLAY:
             actor_pin (actor);
             break;
+
         case UIState.WIZARD:
+        case UIState.PROPERTIES:
             actor_remove (gtk_actor);
-            app.box.pack (gtk_actor, "column", 0, "row", 1, "x-expand", false, "y-expand", true);
-            notebook.page = SidebarPage.WIZARD;
+            app.box.pack (gtk_actor, "column", 0, "row", 1, "row-span", 1, "x-expand", false, "y-expand", true);
+            notebook.page = ui_state == UIState.WIZARD ? SidebarPage.WIZARD : SidebarPage.PROPERTIES;
             break;
         }
     }
 
-    private void list_append (ListStore listmodel,
+    private void list_append (Gtk.ListStore listmodel,
                               Category  category,
                               string?   icon = null,
                               uint      height = 0,
@@ -170,6 +174,10 @@ private class Boxes.Sidebar: Boxes.UI {
         vbox = new Gtk.VBox (false, 0);
         notebook.append_page (vbox, null);
 
+        /* SidebarPage.PROPERTIES */
+        vbox = new Gtk.VBox (false, 10);
+        notebook.append_page (vbox, null);
+
         notebook.show_all ();
 
         // FIXME: make it dynamic depending on sidebar size..:
diff --git a/src/spice-display.vala b/src/spice-display.vala
index 3a5d212..61870e4 100644
--- a/src/spice-display.vala
+++ b/src/spice-display.vala
@@ -25,15 +25,15 @@ private class Boxes.SpiceDisplay: Boxes.Display {
     public override Gtk.Widget? get_display (int n) throws Boxes.Error {
         var display = displays.lookup (n) as Spice.Display;
 
-        if (display == null) {
+        if (display == null)
             display = new Spice.Display (session, n);
-            display.resize_guest = true;
-            display.scaling = true;
-        }
 
         if (display == null)
             throw new Boxes.Error.INVALID ("invalid display");
 
+        display.resize_guest = true;
+        display.scaling = true;
+
         return display;
     }
 
diff --git a/src/topbar.vala b/src/topbar.vala
index ecd14fa..11e6e33 100644
--- a/src/topbar.vala
+++ b/src/topbar.vala
@@ -5,6 +5,7 @@ using Gtk;
 public enum Boxes.TopbarPage {
     COLLECTION,
     WIZARD,
+    PROPERTIES
 }
 
 private class Boxes.Topbar: Boxes.UI {
@@ -12,7 +13,7 @@ private class Boxes.Topbar: Boxes.UI {
     public Gtk.Label label;
 
     private App app;
-    private uint height;
+    public const uint height = 50;
 
     private GtkClutter.Actor gtk_actor; // the topbar box
     public Notebook notebook;
@@ -23,7 +24,6 @@ private class Boxes.Topbar: Boxes.UI {
 
     public Topbar (App app) {
         this.app = app;
-        height = 50;
 
         setup_topbar ();
     }
@@ -73,6 +73,11 @@ private class Boxes.Topbar: Boxes.UI {
         notebook.append_page (hbox, null);
         hbox.get_style_context ().add_class (Gtk.STYLE_CLASS_SIDEBAR);
 
+        /* TopbarPage.PROPERTIES */
+        hbox = new Gtk.HBox (false, 0);
+        notebook.append_page (hbox, null);
+        hbox.get_style_context ().add_class (Gtk.STYLE_CLASS_SIDEBAR);
+
         notebook.show_tabs = false;
         notebook.show_all ();
 
@@ -89,17 +94,21 @@ private class Boxes.Topbar: Boxes.UI {
             toolbar_start.hide ();
             toolbar_end.hide ();
             break;
+
         case UIState.CREDS:
             toolbar_start.show ();
             toolbar_end.show ();
             break;
+
         case UIState.DISPLAY:
             actor_pin (gtk_actor);
             break;
+
+        case UIState.PROPERTIES:
         case UIState.WIZARD:
             actor_remove (gtk_actor);
             app.box.pack (gtk_actor, "row", 0, "column", 0, "column-span", 2, "x-expand", true, "y-expand", false);
-            notebook.page = TopbarPage.WIZARD;
+            notebook.page = ui_state == UIState.WIZARD ? TopbarPage.WIZARD : TopbarPage.PROPERTIES;
             break;
 
         default:
diff --git a/src/ui.vala b/src/ui.vala
index 95a296f..2c56f5b 100644
--- a/src/ui.vala
+++ b/src/ui.vala
@@ -6,18 +6,21 @@ private enum Boxes.UIState {
     CREDS,
     DISPLAY,
     SETTINGS,
-    WIZARD
+    WIZARD,
+    PROPERTIES
 }
 
 private abstract class Boxes.UI: GLib.Object {
     public abstract Clutter.Actor actor { get; }
 
+    protected UIState previous_ui_state;
     private UIState _ui_state;
     [CCode (notify = false)]
     public UIState ui_state {
         get { return _ui_state; }
         set {
             if (_ui_state != value) {
+                previous_ui_state = _ui_state;
                 _ui_state = value;
                 ui_state_changed ();
                 notify_property ("ui-state");
diff --git a/src/wizard.vala b/src/wizard.vala
index d377b37..46fe667 100644
--- a/src/wizard.vala
+++ b/src/wizard.vala
@@ -103,13 +103,13 @@ private class Boxes.Wizard: Boxes.UI {
 
                     var query = new Query (uri.query_raw ?? uri.query);
 
-                    if (uri.port != -1)
+                    if (uri.port > 0)
                         throw new Boxes.Error.INVALID ("the Spice URI is invalid");
 
                     summary.add_property (_("Port"), query.get ("port"));
                     summary.add_property (_("TLS Port"), query.get ("tls-port"));
                 } else {
-                    if (uri.port != -1)
+                    if (uri.port > 0)
                         summary.add_property (_("Port"), uri.port.to_string ());
                 }
             } else



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