[gnome-boxes/wip/props-ui-files: 3/5] i-props-provider: get_properties() return page



commit 89e60a4d6967558559804e6d0a5d9c9e39673d90
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Thu Aug 18 15:17:07 2016 +0100

    i-props-provider: get_properties() return page
    
    Implementations of IPropertiesProvider.get_properties() now construct and
    return the whole properties page (PropertiesPageWidget). This
    effectively obsolets Properties hierarchy.
    
    Known issue: Properties view updates now require a complete refresh of
    page in question.

 src/display.vala                    |    3 +-
 src/i-properties-provider.vala      |    2 +-
 src/libvirt-machine-properties.vala |  214 +++++++++++++++++------------------
 src/libvirt-machine.vala            |    8 +-
 src/machine.vala                    |    2 +-
 src/ovirt-machine.vala              |   14 +-
 src/properties-page-widget.vala     |   25 +----
 src/properties-snapshots.vala       |    2 +-
 src/properties.vala                 |    2 +-
 src/remote-machine.vala             |   30 +++---
 src/spice-display.vala              |   24 +++--
 src/vnc-display.vala                |   14 ++-
 src/wizard-window.vala              |   33 +----
 13 files changed, 168 insertions(+), 205 deletions(-)
---
diff --git a/src/display.vala b/src/display.vala
index 43128f2..7f17127 100644
--- a/src/display.vala
+++ b/src/display.vala
@@ -37,7 +37,8 @@ private abstract class Boxes.Display: GLib.Object, Boxes.IPropertiesProvider {
     }
     public abstract void send_keys (uint[] keyvals);
 
-    public abstract async List<Boxes.Property> get_properties (Boxes.PropertiesPage page);
+    public abstract async PropertiesPageWidget get_properties (Boxes.PropertiesPage page);
+    public abstract async void add_properties (PropertiesPageWidget widget, PropertiesPage page);
 
     protected HashTable<int, Gtk.Widget?> displays;
 
diff --git a/src/i-properties-provider.vala b/src/i-properties-provider.vala
index 0a670d2..4ce9308 100644
--- a/src/i-properties-provider.vala
+++ b/src/i-properties-provider.vala
@@ -193,7 +193,7 @@ private class Boxes.EditableStringProperty : Boxes.Property {
 }
 
 private interface Boxes.IPropertiesProvider: GLib.Object {
-    public abstract async List<Boxes.Property> get_properties (Boxes.PropertiesPage page);
+    public abstract async PropertiesPageWidget get_properties (Boxes.PropertiesPage page);
 
     protected Boxes.Property add_property (ref List<Boxes.Property> list,
                                            string? name,
diff --git a/src/libvirt-machine-properties.vala b/src/libvirt-machine-properties.vala
index b210fbe..5c3a28e 100644
--- a/src/libvirt-machine-properties.vala
+++ b/src/libvirt-machine-properties.vala
@@ -80,8 +80,8 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
         return builder.str;
     }
 
-    public async List<Boxes.Property> get_properties (Boxes.PropertiesPage page) {
-        var list = new List<Boxes.Property> ();
+    public async PropertiesPageWidget get_properties (Boxes.PropertiesPage page) {
+        var widget = new PropertiesPageWidget (page);
 
         // the wizard may want to modify display properties, before connect_display()
         if (machine.is_on && machine.display == null)
@@ -93,39 +93,37 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
 
         switch (page) {
         case PropertiesPage.GENERAL:
-            var property = add_editable_string_property (ref list, _("_Name"), machine.name);
-            property.changed.connect ((property, name) => {
+            widget.add_string_property (_("_Name"), machine.name, (widget, name) => {
                 machine.name = name;
             });
 
-            var name_property = property;
             machine.notify["name"].connect (() => {
-                name_property.text = machine.name;
+                widget.refresh_properties ();
             });
 
             var ip = machine.get_ip_address ();
             if (ip != null)
-                add_string_property (ref list, _("IP Address"), ip);
+                widget.add_string_property (_("IP Address"), ip);
 
-            add_string_property (ref list, _("Broker"), machine.source.name);
+            widget.add_string_property (_("Broker"), machine.source.name);
             if (machine.display != null) {
                 // Translators: This is the protocal being used to connect to the display/desktop, e.g 
Spice, VNC, etc.
-                add_string_property (ref list, _("Display Protocol"), machine.display.protocol);
+                widget.add_string_property (_("Display Protocol"), machine.display.protocol);
                 if (machine.display.uri != null)
                     // Translators: This is the URL to connect to the display/desktop. e.g 
spice://somehost:5051.
-                    add_string_property (ref list, _("Display URL"), machine.display.uri);
+                    widget.add_string_property (_("Display URL"), machine.display.uri);
             }
 
             break;
 
         case PropertiesPage.SYSTEM:
-            add_resource_usage_graphs (ref list);
+            add_resource_usage_graphs (widget);
 
-            add_system_props_buttons (ref list);
+            add_system_props_buttons (widget);
 
-            get_resources_properties (ref list);
+            yield add_resources_properties (widget);
 
-            add_run_in_bg_property (ref list);
+            add_run_in_bg_property (widget);
 
             break;
 
@@ -136,7 +134,7 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
                 var disk_config = device_config as GVirConfig.DomainDisk;
                 var disk_type = disk_config.get_guest_device_type ();
                 if (disk_type == GVirConfig.DomainDiskGuestDeviceType.CDROM)
-                    add_cdrom_property (disk_config, ref list);
+                    add_cdrom_property (disk_config, widget);
             }
 
             break;
@@ -147,7 +145,7 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
                 // Snapshots currently don't work with host-passthrough
                 if (config.get_cpu ().get_mode () != GVirConfig.DomainCpuMode.HOST_PASSTHROUGH &&
                     !VMConfigurator.is_install_config (config))
-                    add_snapshots_property (ref list);
+                    return add_snapshots_property ();
             } catch (GLib.Error e) {
                 warning (e.message);
             }
@@ -155,16 +153,22 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
             break;
         }
 
-        return list;
+        return widget;
     }
 
-    public void get_resources_properties (ref List<Boxes.Property> list) {
-        var ram_property = add_ram_property (ref list);
-        var storage_property = add_storage_property (ref list);
-        mark_recommended_resources.begin (ram_property, storage_property);
+    public async void add_resources_properties (PropertiesPageWidget widget) {
+        int64 ram = -1, storage = -1;
+        var resources = yield get_recommended_resources ();
+        if (resources != null) {
+            ram = resources.ram;
+            storage = resources.storage;
+        }
+
+        add_ram_property (widget, ram);
+        add_storage_property (widget, storage);
     }
 
-    private void add_cdrom_property (GVirConfig.DomainDisk disk_config, ref List<Boxes.Property> list) {
+    private void add_cdrom_property (GVirConfig.DomainDisk disk_config, PropertiesPageWidget widget) {
         var grid = new Gtk.Grid ();
         grid.set_orientation (Gtk.Orientation.HORIZONTAL);
         grid.set_column_spacing (12);
@@ -187,7 +191,7 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
 
             if (machine.vm_creator.express_install || (media.os_media != null && media.os_media.live)) {
                 // Don't let user eject installer media if it's an express installation or a live media
-                add_property (ref list, _("CD/DVD"), grid);
+                widget.add_property (_("CD/DVD"), grid);
 
                 return;
             }
@@ -239,11 +243,10 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
             }
         });
 
-        var property = add_property (ref list, _("CD/DVD"), grid);
-        property.description_alignment = Gtk.Align.START;
+        widget.add_property (_("CD/DVD"), grid, null, Gtk.Align.START);
     }
 
-    private void update_ram_property (Boxes.Property property) {
+    private void update_ram_property (PropertiesPageWidget widget) {
         try {
             var config = machine.domain.get_config (GVir.DomainXMLFlags.INACTIVE);
 
@@ -253,27 +256,18 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
 
             debug ("RAM actual: %llu, pending: %llu", actual, pending);
             // somehow, there are rounded errors, so let's forget about 1Mb diff
-            property.reboot_required = (actual - pending) > 1; // no need for abs()
+            widget.reboot_required = (actual - pending) > 1; // no need for abs()
 
         } catch (GLib.Error e) {}
     }
 
-    private async void mark_recommended_resources (SizeProperty? ram_property, SizeProperty? 
storage_property) {
-        if (ram_property == null && storage_property == null)
-            return;
-
+    private async Osinfo.Resources? get_recommended_resources () {
         var os = yield get_os_for_machine (machine);
         if (os == null)
-            return;
+            return null;
 
         var architecture = machine.domain_config.get_os ().get_arch ();
-        var resources = OSDatabase.get_recommended_resources_for_os (os, architecture);
-        if (resources != null) {
-            if (ram_property != null)
-                ram_property.recommended = resources.ram;
-            if (storage_property != null)
-                storage_property.recommended = resources.storage;
-        }
+        return OSDatabase.get_recommended_resources_for_os (os, architecture);
     }
 
     private async Osinfo.Os? get_os_for_machine (LibvirtMachine machine) {
@@ -290,7 +284,7 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
         }
     }
 
-    private void add_resource_usage_graphs (ref List<Boxes.Property> list) {
+    private void add_resource_usage_graphs (PropertiesPageWidget widget) {
         var grid = new Gtk.Grid ();
         grid.margin_top = 20;
         grid.margin_bottom = 20;
@@ -324,15 +318,17 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
             net_graph.points = machine.net_stats;
         });
 
-        var prop = add_property (ref list, null, grid);
-        ulong flushed_id = 0;
-        flushed_id = prop.flushed.connect (() => {
+        widget.add_property (null, grid);
+        SourceFunc change_func = () => {
             machine.disconnect (stats_id);
-            prop.disconnect (flushed_id);
-        });
+
+            return false;
+        };
+        var change = new DeferredChange ("graphs-disconnect", (owned) change_func);
+        widget.add_deferred_change (change);
     }
 
-    private void add_system_props_buttons (ref List<Boxes.Property> list) {
+    private void add_system_props_buttons (PropertiesPageWidget widget) {
         var grid = new Gtk.Grid ();
         grid.margin_bottom = 20;
         grid.column_spacing = 5;
@@ -374,52 +370,53 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
             machine.window.props_window.show_troubleshoot_log (log);
         });
 
-        var prop = add_property (ref list, null, grid);
-        ulong flushed_id = 0;
-        flushed_id = prop.flushed.connect (() => {
+        widget.add_property (null, grid);
+        SourceFunc change_func = () => {
             machine.disconnect (state_notify_id);
-            prop.disconnect (flushed_id);
-        });
+
+            return false;
+        };
+        var change = new DeferredChange ("troubleshooting-log-disconnect", (owned) change_func);
+        widget.add_deferred_change (change);
     }
 
-    private SizeProperty? add_ram_property (ref List<Boxes.Property> list) {
+    private void add_ram_property (PropertiesPageWidget widget, int64 recommended_ram) {
         try {
             var max_ram = machine.connection.get_node_info ().memory;
 
-            var property = add_size_property (ref list,
-                                              _("_Memory: "),
-                                              machine.domain_config.memory * Osinfo.KIBIBYTES,
-                                              64 * Osinfo.MEBIBYTES,
-                                              max_ram * Osinfo.KIBIBYTES,
-                                              0,
-                                              64 * Osinfo.MEBIBYTES,
-                                              FormatSizeFlags.IEC_UNITS);
-            property.description_alignment = Gtk.Align.START;
-            property.widget.margin_top = 5;
+            Gtk.Scale scale;
+            var prop_widget = widget.add_size_property (_("_Memory: "),
+                                                        machine.domain_config.memory * Osinfo.KIBIBYTES,
+                                                        64 * Osinfo.MEBIBYTES,
+                                                        max_ram * Osinfo.KIBIBYTES,
+                                                        0,
+                                                        64 * Osinfo.MEBIBYTES,
+                                                        on_ram_changed,
+                                                        recommended_ram,
+                                                        out scale,
+                                                        FormatSizeFlags.IEC_UNITS);
+            prop_widget.margin_top = 5;
             if ((VMConfigurator.is_install_config (machine.domain_config) ||
                  VMConfigurator.is_live_config (machine.domain_config)) &&
                 machine.window.ui_state != Boxes.UIState.WIZARD &&
-                machine.state != Machine.MachineState.FORCE_STOPPED)
-                property.sensitive = false;
-            else
-                property.changed.connect (on_ram_changed);
+                machine.state != Machine.MachineState.FORCE_STOPPED) {
+                prop_widget.sensitive = false;
+                scale.sensitive = false;
+            }
 
             machine.notify["state"].connect (() => {
                 if (!machine.is_on)
-                    property.reboot_required = false;
+                    widget.reboot_required = false;
             });
 
-            update_ram_property (property);
-
-            return property;
+            update_ram_property (widget);
         } catch (GLib.Error error) {
-            return null;
         }
     }
 
-    private void on_ram_changed (Boxes.Property property, uint64 value) {
+    private void on_ram_changed (PropertiesPageWidget widget, uint64 value) {
         // Ensure that we don't end-up changing RAM like a 1000 times a second while user moves the slider..
-        property.deferred_change = () => {
+        SourceFunc change_func = () => {
             var ram = (value + Osinfo.KIBIBYTES - 1) / Osinfo.KIBIBYTES;
             try {
                 var config = machine.domain.get_config (GVir.DomainXMLFlags.INACTIVE);
@@ -435,15 +432,17 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
                          error.message);
             }
 
-            update_ram_property (property);
+            update_ram_property (widget);
 
             return false;
         };
+        var change = new DeferredChange ("ram-changed", (owned) change_func);
+        widget.add_deferred_change (change);
     }
 
-    private SizeProperty? add_storage_property (ref List<Boxes.Property> list) {
+    private void add_storage_property (PropertiesPageWidget widget, int64 recommended_storage) {
         if (machine.importing || machine.storage_volume == null)
-            return null;
+            return;
 
         try {
             var volume_info = machine.storage_volume.get_info ();
@@ -460,7 +459,7 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
                 label.set_markup (markup);
                 label.halign = Gtk.Align.START;
 
-                add_property (ref list, null, label);
+                widget.add_property (null, label);
 
                 var infobar = new Gtk.InfoBar ();
                 infobar.message_type = Gtk.MessageType.WARNING;
@@ -476,50 +475,50 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
                 label = new Gtk.Label (msg);
                 content.add (label);
 
-                add_property (ref list, null, infobar);
+                widget.add_property (null, infobar);
 
-                return null;
+                return;
             }
 
-            var property = add_size_property (ref list,
-                                              _("Maximum _Disk Size: "),
-                                              volume_info.capacity,
-                                              min_storage,
-                                              max_storage,
-                                              volume_info.allocation,
-                                              256 * MEGABYTES);
-            property.description_alignment = Gtk.Align.START;
-            // Disable 'save on timeout' all together since that could lead us to very bad user experience:
-            // You accidently increase the capacity to too high value and if you are not quick enough to 
change
-            // it again, you'll not be able to correct this ever as we don't support shrinking of volumes.
-            property.defer_interval = 0;
+            Gtk.Scale scale;
+            var prop_widget = widget.add_size_property (_("Maximum _Disk Size: "),
+                                                        volume_info.capacity,
+                                                        min_storage,
+                                                        max_storage,
+                                                        volume_info.allocation,
+                                                        256 * MEGABYTES,
+                                                        on_storage_changed,
+                                                        recommended_storage,
+                                                        out scale);
             if ((VMConfigurator.is_install_config (machine.domain_config) ||
                  VMConfigurator.is_live_config (machine.domain_config)) &&
                 machine.window.ui_state != Boxes.UIState.WIZARD &&
-                machine.state != Machine.MachineState.FORCE_STOPPED)
-                property.sensitive = false;
-            else
-                property.changed.connect (on_storage_changed);
-
-            return property;
+                machine.state != Machine.MachineState.FORCE_STOPPED) {
+                prop_widget.sensitive = false;
+                scale.sensitive = false;
+            }
         } catch (GLib.Error error) {
             warning ("Failed to get information on volume '%s' or it's parent pool: %s",
                      machine.storage_volume.get_name (),
                      error.message);
-            return null;
         }
     }
 
-    private void on_storage_changed (Boxes.Property property, uint64 value) {
+    private void on_storage_changed (PropertiesPageWidget widget, uint64 value) {
         // Ensure that we don't end-up changing storage like a 1000 times a second while user moves the 
slider..
-        property.deferred_change = () => {
-            change_storage_size.begin (property, value);
+        // Also disable 'save on timeout' all together since that could lead us to very bad user experience:
+        // You accidently increase the capacity to too high value and if you are not quick enough to change
+        // it again, you'll not be able to correct this ever as we don't support shrinking of volumes.
+        SourceFunc change_func = () => {
+            change_storage_size.begin (value);
 
             return false;
         };
+        var change = new DeferredChange ("storage-changed", (owned) change_func, 0);
+        widget.add_deferred_change (change);
     }
 
-    private async void change_storage_size (Boxes.Property property, uint64 value) {
+    private async void change_storage_size (uint64 value) {
         if (machine.storage_volume == null)
             return;
 
@@ -600,7 +599,7 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
         return machine.domain.get_snapshots ();
     }
 
-    private void add_run_in_bg_property (ref List<Boxes.Property> list) {
+    private void add_run_in_bg_property (PropertiesPageWidget widget) {
         if (machine.connection != App.app.default_connection)
             return; // We only autosuspend machines on default connection so this property is N/A to other 
machines
 
@@ -626,13 +625,10 @@ private class Boxes.LibvirtMachineProperties: GLib.Object, Boxes.IPropertiesProv
                                               _("'%s' will be paused automatically to save 
resources.").printf (name);
         });
 
-        add_property (ref list, null, box, null);
+        widget.add_property (null, box, null);
     }
 
-    private Boxes.SnapshotsProperty add_snapshots_property (ref List<Boxes.Property> list) {
-        var property = new SnapshotsProperty (machine);
-        list.append (property);
-
-        return property;
+    private PropertiesSnapshots add_snapshots_property () {
+        return new PropertiesSnapshots (machine);
     }
 }
diff --git a/src/libvirt-machine.vala b/src/libvirt-machine.vala
index ef3871c..82e78d6 100644
--- a/src/libvirt-machine.vala
+++ b/src/libvirt-machine.vala
@@ -384,13 +384,13 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
         }
     }
 
-    public override async List<Boxes.Property> get_properties (Boxes.PropertiesPage page) {
-        var list = yield properties.get_properties (page);
+    public override async Boxes.PropertiesPageWidget get_properties (Boxes.PropertiesPage page) {
+        var widget = yield properties.get_properties (page);
 
         if (display != null)
-            list.concat (yield display.get_properties (page));
+            yield display.add_properties (widget, page);
 
-        return list;
+        return widget;
     }
 
     public bool update_display () throws GLib.Error {
diff --git a/src/machine.vala b/src/machine.vala
index a13d54a..e0e0d7d 100644
--- a/src/machine.vala
+++ b/src/machine.vala
@@ -358,7 +358,7 @@ private abstract class Boxes.Machine: Boxes.CollectionItem, Boxes.IPropertiesPro
         return display.get_pixbuf (0);
     }
 
-    public abstract async List<Boxes.Property> get_properties (Boxes.PropertiesPage page);
+    public abstract async PropertiesPageWidget get_properties (Boxes.PropertiesPage page);
 
     public abstract async void connect_display (ConnectFlags flags) throws GLib.Error;
     public abstract void restart ();
diff --git a/src/ovirt-machine.vala b/src/ovirt-machine.vala
index e510d63..04db198 100644
--- a/src/ovirt-machine.vala
+++ b/src/ovirt-machine.vala
@@ -63,20 +63,20 @@ private class Boxes.OvirtMachine: Boxes.Machine {
         }
     }
 
-    public override async List<Boxes.Property> get_properties (Boxes.PropertiesPage page) {
-        var list = new List<Boxes.Property> ();
+    public override async PropertiesPageWidget get_properties (Boxes.PropertiesPage page) {
+        var widget = new PropertiesPageWidget (page);
 
         switch (page) {
         case PropertiesPage.GENERAL:
-            add_string_property (ref list, _("Broker"), source.name);
-            add_string_property (ref list, _("Protocol"), display.protocol);
-            add_string_property (ref list, _("URL"), display.uri);
+            widget.add_string_property (_("Broker"), source.name);
+            widget.add_string_property (_("Protocol"), display.protocol);
+            widget.add_string_property (_("URL"), display.uri);
             break;
         }
 
-        list.concat (yield display.get_properties (page));
+        yield display.add_properties (widget, page);
 
-        return list;
+        return widget;
     }
 
     public override void restart () {} // See FIXME on RemoteMachine.restart
diff --git a/src/properties-page-widget.vala b/src/properties-page-widget.vala
index 485a947..a0ee738 100644
--- a/src/properties-page-widget.vala
+++ b/src/properties-page-widget.vala
@@ -2,11 +2,10 @@
 using Gtk;
 
 private class Boxes.PropertiesPageWidget: Gtk.Box {
-    public bool empty;
+    public bool empty { get { return (grid.get_children ().length () == 0); } }
     public bool reboot_required;
 
     private Gtk.Grid grid;
-    private List<Boxes.Property> properties;
     private List<DeferredChange> deferred_changes;
 
     public signal void refresh_properties ();
@@ -32,7 +31,7 @@ private class Boxes.PropertiesPageWidget: Gtk.Box {
         }
     }
 
-    public async PropertiesPageWidget (PropertiesPage page, Machine machine) {
+    public PropertiesPageWidget (PropertiesPage page) {
         deferred_changes = new List<DeferredChange> ();
 
         switch (page) {
@@ -66,32 +65,12 @@ private class Boxes.PropertiesPageWidget: Gtk.Box {
         scrolled_win.add (grid);
         pack_end (scrolled_win, true, true);
 
-        properties = yield machine.get_properties (page);
-        empty = properties.length () == 0;
-        if (!empty) {
-            foreach (var property in properties) {
-                add_property (property.description,
-                              property.widget,
-                              property.extra_widget,
-                              property.description_alignment);
-
-                property.refresh_properties.connect (() => {
-                    this.refresh_properties ();
-                });
-            }
-        }
-
         show_all ();
     }
 
     public bool flush_changes () {
         var reboot_required = this.reboot_required;
 
-        foreach (var property in properties) {
-            property.flush ();
-            reboot_required |= property.reboot_required;
-        }
-
         foreach (var change in deferred_changes)
             change.flush ();
         deferred_changes = new List<DeferredChange> (); // FIXME: Better way to clear the list?
diff --git a/src/properties-snapshots.vala b/src/properties-snapshots.vala
index da6bdc1..0b0fe37 100644
--- a/src/properties-snapshots.vala
+++ b/src/properties-snapshots.vala
@@ -23,7 +23,7 @@ private class Boxes.PropertiesSnapshots: Boxes.PropertiesPageWidget {
     private ulong removed_id;
 
     public PropertiesSnapshots (LibvirtMachine machine) {
-        base (PropertiesPage.SNAPSHOTS, machine);
+        base (PropertiesPage.SNAPSHOTS);
 
         this.machine = machine;
         stack = new Gtk.Stack ();
diff --git a/src/properties.vala b/src/properties.vala
index 5c3e531..e43d3fb 100644
--- a/src/properties.vala
+++ b/src/properties.vala
@@ -33,7 +33,7 @@ private class Boxes.Properties: Gtk.Notebook, Boxes.UI {
             return;
 
         for (var i = 0; i < PropertiesPage.LAST; i++) {
-            var page = yield new PropertiesPageWidget (i, machine);
+            var page = yield machine.get_properties (i);
             if (page.empty)
                 continue;
 
diff --git a/src/remote-machine.vala b/src/remote-machine.vala
index ece3ecb..926bb04 100644
--- a/src/remote-machine.vala
+++ b/src/remote-machine.vala
@@ -53,30 +53,28 @@ private class Boxes.RemoteMachine: Boxes.Machine, Boxes.IPropertiesProvider {
         }
     }
 
-    public override async List<Boxes.Property> get_properties (Boxes.PropertiesPage page) {
-        var list = new List<Boxes.Property> ();
+    public override async PropertiesPageWidget get_properties (Boxes.PropertiesPage page) {
+        var widget = new PropertiesPageWidget (page);
 
         switch (page) {
         case PropertiesPage.GENERAL:
-            var property = add_editable_string_property (ref list, _("_Name"), source.name);
-            property.changed.connect ((property, name) => {
+            widget.add_string_property (_("_Name"), source.name, (widget, name) => {
                 this.name = name;
             });
 
-            var name_property = property;
             notify["name"].connect (() => {
-                name_property.text = name;
+                widget.refresh_properties ();
             });
 
-            add_string_property (ref list, _("Protocol"), source.source_type.up ());
-            if (is_connected) {
-                add_string_property (ref list, _("URL"), source.uri);
-            } else {
-                property = add_editable_string_property (ref list, _("_URL"), source.uri);
-                property.changed.connect ((property, uri) => {
+            widget.add_string_property (_("Protocol"), source.source_type.up ());
+            PropertiesPageWidget.StringPropertyChanged? on_changed;
+            if (is_connected)
+                on_changed = null;
+            else
+                on_changed = (widget, uri) => {
                     source.uri = uri;
-               });
-            }
+                };
+            widget.add_string_property (_("_URL"), source.uri, on_changed);
 
             break;
         }
@@ -85,12 +83,12 @@ private class Boxes.RemoteMachine: Boxes.Machine, Boxes.IPropertiesProvider {
             if (display == null)
                 display = create_display ();
 
-            list.concat (yield display.get_properties (page));
+            yield display.add_properties (widget, page);
         } catch (Boxes.Error error) {
             warning (error.message);
         }
 
-        return list;
+        return widget;
     }
 
     public override void delete (bool by_user = true) {
diff --git a/src/spice-display.vala b/src/spice-display.vala
index 3a05fa8..6644a6b 100644
--- a/src/spice-display.vala
+++ b/src/spice-display.vala
@@ -306,16 +306,22 @@ private class Boxes.SpiceDisplay: Boxes.Display {
         }
     }
 
-    public override async List<Boxes.Property> get_properties (Boxes.PropertiesPage page) {
-        var list = new List<Boxes.Property> ();
+    public override async Boxes.PropertiesPageWidget get_properties (Boxes.PropertiesPage page) {
+        var widget = new PropertiesPageWidget (page);
 
+        yield add_properties (widget, page);
+
+        return widget;
+    }
+
+    public override async void add_properties (PropertiesPageWidget widget, PropertiesPage page) {
         switch (page) {
         case PropertiesPage.GENERAL:
             var toggle = new Gtk.Switch ();
             gtk_session.bind_property ("auto-clipboard", toggle, "active",
                                        BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE);
             toggle.halign = Gtk.Align.START;
-            add_property (ref list, _("Share Clipboard"), toggle);
+            widget.add_property (_("Share Clipboard"), toggle);
 
             if (!connected || main_channel.agent_connected)
                 break;
@@ -329,7 +335,7 @@ private class Boxes.SpiceDisplay: Boxes.Display {
             label.use_markup = true;
             label.get_style_context ().add_class ("boxes-spice-tools-notice-label");
 
-            add_property (ref list, null, label);
+            widget.add_property (null, label);
             break;
 
         case PropertiesPage.DEVICES:
@@ -341,7 +347,7 @@ private class Boxes.SpiceDisplay: Boxes.Display {
                 var devs = get_usb_devices (manager);
 
                 if (devs.length <= 0)
-                    return list;
+                    return;
 
                 devs.sort ( (a, b) => {
                     string str_a = a.get_description ("    %1$s %2$s");
@@ -395,20 +401,18 @@ private class Boxes.SpiceDisplay: Boxes.Display {
                     });
                 }
 
-                var usb_property = add_property (ref list, _("USB devices"), new Gtk.Label (""), frame);
+                widget.add_property (_("USB devices"), new Gtk.Label (""), frame);
 
                 manager.device_added.connect ((manager, dev) => {
-                    usb_property.refresh_properties ();
+                    widget.refresh_properties ();
                 });
                 manager.device_removed.connect ((manager, dev) => {
-                    usb_property.refresh_properties ();
+                    widget.refresh_properties ();
                 });
             } catch (GLib.Error error) {
             }
             break;
         }
-
-        return list;
     }
 
     public override void send_keys (uint[] keyvals) {
diff --git a/src/vnc-display.vala b/src/vnc-display.vala
index d572ae3..d5e526d 100644
--- a/src/vnc-display.vala
+++ b/src/vnc-display.vala
@@ -133,20 +133,24 @@ private class Boxes.VncDisplay: Boxes.Display {
             display.close ();
     }
 
-    public override async List<Boxes.Property> get_properties (Boxes.PropertiesPage page) {
-        var list = new List<Boxes.Property> ();
+    public override async Boxes.PropertiesPageWidget get_properties (Boxes.PropertiesPage page) {
+        var widget = new PropertiesPageWidget (page);
 
+        yield add_properties (widget, page);
+
+        return widget;
+    }
+
+    public override async void add_properties (PropertiesPageWidget widget, PropertiesPage page) {
         switch (page) {
         case PropertiesPage.GENERAL:
             var toggle = new Gtk.Switch ();
             toggle.halign = Gtk.Align.START;
             display.bind_property ("read-only", toggle, "active",
                                    BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE);
-            add_property (ref list, _("Read-only"), toggle);
+            widget.add_property (_("Read-only"), toggle);
             break;
         }
-
-        return list;
     }
 
     public override void send_keys (uint[] keyvals) {
diff --git a/src/wizard-window.vala b/src/wizard-window.vala
index 4c309e4..56045ef 100644
--- a/src/wizard-window.vala
+++ b/src/wizard-window.vala
@@ -21,10 +21,9 @@ private class Boxes.WizardWindow : Gtk.Window, Boxes.UI {
         get { return _page; }
         set {
             if (_page == WizardWindowPage.CUSTOMIZATION && value != WizardWindowPage.CUSTOMIZATION &&
-                resource_properties != null && resource_properties.length () > 0) {
-                foreach (var property in resource_properties)
-                    property.flush ();
-                resource_properties = null;
+                props_page_widget != null && !props_page_widget.empty) {
+                props_page_widget.flush_changes ();
+                props_page_widget  = null;
 
                 wizard.review.begin ();
             }
@@ -49,7 +48,7 @@ private class Boxes.WizardWindow : Gtk.Window, Boxes.UI {
     [GtkChild]
     public Notificationbar notificationbar;
 
-    private GLib.List<Boxes.Property> resource_properties;
+    private PropertiesPageWidget? props_page_widget;
 
     public WizardWindow (AppWindow app_window) {
         wizard.setup_ui (app_window, this);
@@ -67,30 +66,12 @@ private class Boxes.WizardWindow : Gtk.Window, Boxes.UI {
     }
 
     public async void show_customization_page (LibvirtMachine machine) {
-        resource_properties = new GLib.List<Boxes.Property> ();
-        machine.properties.get_resources_properties (ref resource_properties);
-
-        return_if_fail (resource_properties.length () > 0);
-
         foreach (var child in customization_grid.get_children ())
             customization_grid.remove (child);
 
-        var current_row = 0;
-        foreach (var property in resource_properties) {
-            if (property.widget == null || property.extra_widget == null) {
-                warn_if_reached ();
-
-                continue;
-            }
-
-            property.widget.hexpand = true;
-            customization_grid.attach (property.widget, 0, current_row, 1, 1);
-
-            property.extra_widget.hexpand = true;
-            customization_grid.attach (property.extra_widget, 0, current_row + 1, 1, 1);
-
-            current_row += 2;
-        }
+        var props_page_widget = new PropertiesPageWidget (PropertiesPage.SYSTEM);
+        customization_grid.add (props_page_widget);
+        yield machine.properties.add_resources_properties (props_page_widget);
         customization_grid.show_all ();
 
         page = WizardWindowPage.CUSTOMIZATION;


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