[gnome-boxes/decouple-shared-folders: 7/7] shared-folders: Decouple from SpiceDisplay



commit f34f415d2ba92e3aa2a797b861bfc8b48deb83c0
Author: Felipe Borges <felipeborges gnome org>
Date:   Fri Nov 16 10:20:26 2018 +0100

    shared-folders: Decouple from SpiceDisplay
    
    The current implementation of Shared Folders was strictly tied to
    the Spice Display, because spice-webdav is the bridge that makes
    this feature possible with libvirt machines. But now we could also
    have shared folders in RDP Remote Machines. Therefore decoupling
    the shared folders implementation from the spice-display class was
    a natural choice.
    
    The way it works now is that there's a central singleton object
    named SharedFoldersManager that interfaces everything that is
    necessary for the feature to work in the host side (saving the
    gsettings, creating the symlinks, etc...).
    
    The basic API for the SharedFoldersManager is to query for shared
    folders with SharedFoldersManager.get_folders (machine_uuid), and
    add/remove items, since SharedFoldersManager implements the
    Boxes.Collection interface.
    
    These changes also make the use of cleaner methods of implementing
    the functionality, such as decoupling the logic and view with Gtk
    widget templates, and the use of GLib.ListStore models to back the
    Gtk.ListBox views (giving us free ordering, sorting, and row
    updates).

 data/gnome-boxes.gresource.xml   |   1 +
 data/ui/shared-folder-popover.ui |   3 +-
 data/ui/shared-folders.ui        |  47 +++++++
 src/meson.build                  |   2 +-
 src/shared-folder-popover.vala   |  40 ------
 src/shared-folders.vala          | 283 +++++++++++++++++++++++++++++++++++++++
 src/spice-display.vala           | 269 +------------------------------------
 7 files changed, 336 insertions(+), 309 deletions(-)
---
diff --git a/data/gnome-boxes.gresource.xml b/data/gnome-boxes.gresource.xml
index d44415f3..47c2a917 100644
--- a/data/gnome-boxes.gresource.xml
+++ b/data/gnome-boxes.gresource.xml
@@ -28,6 +28,7 @@
     <file preprocess="xml-stripblanks">ui/searchbar.ui</file>
     <file preprocess="xml-stripblanks">ui/selectionbar.ui</file>
     <file preprocess="xml-stripblanks">ui/selection-toolbar.ui</file>
+    <file preprocess="xml-stripblanks">ui/shared-folders.ui</file>
     <file preprocess="xml-stripblanks">ui/shared-folder-popover.ui</file>
     <file preprocess="xml-stripblanks">ui/snapshot-list-row.ui</file>
     <file preprocess="xml-stripblanks">ui/topbar.ui</file>
diff --git a/data/ui/shared-folder-popover.ui b/data/ui/shared-folder-popover.ui
index a92a0e23..b6676512 100644
--- a/data/ui/shared-folder-popover.ui
+++ b/data/ui/shared-folder-popover.ui
@@ -1,5 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
 <interface>
   <requires lib="gtk+" version="3.19"/>
   <template class="BoxesSharedFolderPopover" parent="GtkPopover">
@@ -138,4 +137,4 @@
       </object>
     </child>
   </template>
-</interface>
+</interface>
\ No newline at end of file
diff --git a/data/ui/shared-folders.ui b/data/ui/shared-folders.ui
new file mode 100644
index 00000000..25431a8a
--- /dev/null
+++ b/data/ui/shared-folders.ui
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.19"/>
+  <template class="BoxesSharedFoldersWidget" parent="GtkFrame">
+    <property name="visible">True</property>
+
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+
+        <child>
+          <object class="GtkListBox" id="listbox">
+            <property name="visible">True</property>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+          </packing>
+        </child>
+
+        <child>
+          <object class="GtkButton">
+            <property name="visible">True</property>
+            <property name="halign">center</property>
+            <signal name="clicked" handler="on_add_button_clicked"/>
+
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="icon-name">list-add-symbolic</property>
+                <property name="icon-size">button</property>
+                <style>
+                  <class name="flat"/>
+                </style>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="padding">5</property>
+            <property name="fill">false</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/meson.build b/src/meson.build
index 533cbb25..805be584 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -87,7 +87,7 @@ vala_sources = [
   'searchbar.vala',
   'selectionbar.vala',
   'selection-toolbar.vala',
-  'shared-folder-popover.vala',
+  'shared-folders.vala',
   'spice-display.vala',
   'transfer-info-row.vala',
   'transfer-popover.vala',
diff --git a/src/shared-folders.vala b/src/shared-folders.vala
new file mode 100644
index 00000000..0157025e
--- /dev/null
+++ b/src/shared-folders.vala
@@ -0,0 +1,283 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+using Gtk;
+
+private class Boxes.SharedFolder: Boxes.CollectionItem {
+    public string path { set; get; }
+    public string machine_uuid { set; get; }
+
+    public SharedFolder (string machine_uuid, string path, string name = "") {
+        this.machine_uuid = machine_uuid;
+        this.path = path;
+        this.name = name;
+    }
+}
+
+private class Boxes.SharedFoldersManager: Boxes.Collection {
+    private static SharedFoldersManager shared_folders_manager;
+
+    private HashTable<string, GLib.ListStore> folders = new HashTable <string, GLib.ListStore> (str_hash, 
str_equal);
+
+    private GLib.Settings settings = new GLib.Settings ("org.gnome.boxes");
+
+    public static SharedFoldersManager get_default () {
+        if (shared_folders_manager == null)
+            shared_folders_manager = new SharedFoldersManager ();
+
+        return shared_folders_manager;
+    }
+
+    construct {
+        string serialized_list = settings.get_string ("shared-folders");
+        if (serialized_list == "")
+            return;
+
+        try {
+            GLib.Variant? entry = null;
+            string uuid, path, name;
+
+            var variant = Variant.parse (new GLib.VariantType.array (GLib.VariantType.VARIANT), 
serialized_list);
+            VariantIter iter = variant.iterator ();
+            while (iter.next ("v",  &entry)) {
+                entry.lookup ("uuid", "s", out uuid);
+                entry.lookup ("path", "s", out path);
+                entry.lookup ("name", "s", out name);
+
+                add_item (new SharedFolder (uuid, path, name));
+            }
+
+        } catch (VariantParseError err) {
+            warning (err.message);
+        }
+    }
+
+    public GLib.ListStore get_folders (string machine_uuid) {
+        var store = folders.get (machine_uuid);
+        if (store == null) {
+            store = new GLib.ListStore (typeof (SharedFolder));
+
+            folders[machine_uuid] = store;
+        }
+
+        return store;
+    }
+
+    public new bool add_item (SharedFolder folder) {
+        var model = get_folders (folder.machine_uuid);
+        model.append (folder);
+
+        var shared_folder = get_shared_folder_real_path (folder);
+        if (!FileUtils.test (shared_folder, FileTest.IS_DIR))
+            Posix.unlink (folder.path);
+
+        if (!FileUtils.test (shared_folder, FileTest.EXISTS)) {
+            if (Posix.mkdir (shared_folder, 0755) == -1) {
+                warning (strerror (errno));
+
+                return false;
+            }
+        }
+
+        var link_path = GLib.Path.build_filename (shared_folder, folder.name);
+        if (GLib.FileUtils.symlink (folder.path, link_path) == -1) {
+            warning (strerror (errno));
+
+            return false;
+        }
+
+        return add_to_gsetting (folder);
+    }
+
+    private bool add_to_gsetting (SharedFolder folder) {
+        var variant_builder = new GLib.VariantBuilder (new GLib.VariantType.array (VariantType.VARIANT));
+        string shared_folders = settings.get_string ("shared-folders");
+        if (shared_folders != "") {
+            try {
+                GLib.Variant? entry = null;
+
+                var variant = Variant.parse (new GLib.VariantType.array (GLib.VariantType.VARIANT), 
shared_folders);
+                VariantIter iter = variant.iterator ();
+                while (iter.next ("v",  &entry)) {
+                    variant_builder.add ("v",  entry);
+                }
+            } catch (VariantParseError err) {
+                warning (err.message);
+            }
+        }
+
+        var entry_variant_builder = new GLib.VariantBuilder (GLib.VariantType.VARDICT);
+
+        var uuid_variant = new GLib.Variant ("s", folder.machine_uuid);
+        var path_variant = new GLib.Variant ("s", folder.path);
+        var name_variant = new GLib.Variant ("s", folder.name);
+        entry_variant_builder.add ("{sv}", "uuid", uuid_variant);
+        entry_variant_builder.add ("{sv}", "path", path_variant);
+        entry_variant_builder.add ("{sv}", "name", name_variant);
+        var entry_variant = entry_variant_builder.end ();
+
+        variant_builder.add ("v",  entry_variant);
+        var variant = variant_builder.end ();
+
+        return settings.set_string ("shared-folders", variant.print (true));
+    }
+
+    public new void remove_item (SharedFolder folder) {
+        var list_model = folders.get (folder.machine_uuid);
+        for (var idx = 0; idx < list_model.get_n_items (); idx++) {
+            var item = list_model.get_item (idx) as SharedFolder;
+            if (item.name == folder.name) {
+                list_model.remove (idx);
+
+                break;
+            }
+        }
+
+        var shared_folder = get_shared_folder_real_path (folder);
+        if (!FileUtils.test (shared_folder, FileTest.EXISTS) || !FileUtils.test (shared_folder, 
FileTest.IS_DIR))
+            return;
+
+        var to_remove = GLib.Path.build_filename (shared_folder, folder.name);
+        Posix.unlink (to_remove);
+
+        remove_from_gsetting (folder);
+    }
+
+    private void remove_from_gsetting (SharedFolder folder) {
+        var variant_builder = new GLib.VariantBuilder (new GLib.VariantType.array (VariantType.VARIANT));
+
+        string shared_folders = settings.get_string ("shared-folders");
+        if (shared_folders == "")
+            return;
+
+        try {
+            GLib.Variant? entry = null;
+            string name_str;
+            string uuid_str;
+
+            var variant = Variant.parse (new GLib.VariantType.array (GLib.VariantType.VARIANT), 
shared_folders);
+            VariantIter iter = variant.iterator ();
+            while (iter.next ("v",  &entry)) {
+                entry.lookup ("uuid", "s", out uuid_str);
+                entry.lookup ("name", "s", out name_str);
+
+                if (uuid_str == folder.machine_uuid && name_str == folder.name)
+                    continue;
+
+                variant_builder.add ("v", entry);
+            }
+            variant = variant_builder.end ();
+
+            settings.set_string ("shared-folders", variant.print (true));
+        } catch (VariantParseError err) {
+            warning (err.message);
+        }
+
+    }
+
+    private static string get_shared_folder_real_path (SharedFolder folder) {
+        return GLib.Path.build_filename (GLib.Environment.get_user_config_dir (),
+                                         Config.PACKAGE_TARNAME,
+                                         folder.machine_uuid);
+    }
+}
+
+[GtkTemplate (ui = "/org/gnome/Boxes/ui/properties-shared-folder-row.ui")]
+private class Boxes.SharedFolderRow : Gtk.ListBoxRow {
+    public signal void removed (SharedFolder folder);
+    [GtkChild]
+    private Gtk.Label folder_path_label;
+    [GtkChild]
+    private Gtk.Label folder_name_label;
+
+    public SharedFolder folder { get; private set; }
+
+    public SharedFolderRow (SharedFolder folder) {
+        this.folder = folder;
+
+        folder.bind_property ("path", folder_path_label, "label", BindingFlags.SYNC_CREATE);
+        folder.bind_property ("name", folder_name_label, "label", BindingFlags.SYNC_CREATE);
+    }
+
+    [GtkCallback]
+    private void on_delete_button_clicked () {
+        removed (folder);
+    }
+}
+
+[GtkTemplate (ui = "/org/gnome/Boxes/ui/shared-folders.ui")]
+private class Boxes.SharedFoldersWidget: Gtk.Frame {
+    private string machine_uuid;
+
+    private SharedFoldersManager manager = SharedFoldersManager.get_default ();
+
+    private GLib.ListStore list_model;
+
+    private Boxes.SharedFolderPopover popover;
+    [GtkChild]
+    private Gtk.ListBox listbox;
+
+    public SharedFoldersWidget (string machine_uuid) {
+        this.machine_uuid = machine_uuid;
+
+        list_model = manager.get_folders (machine_uuid);
+        listbox.bind_model (list_model, create_shared_folder_row);
+
+        popover = new SharedFolderPopover ();
+        popover.saved.connect (on_popover_saved);
+    }
+
+    private bool on_popover_saved (string path, string? name) {
+        return manager.add_item (new SharedFolder (machine_uuid, path, name));
+    }
+
+    [GtkCallback]
+    private void on_add_button_clicked (Gtk.Button button) {
+        popover.relative_to = button;
+
+        popover.popup ();
+    }
+
+    private Gtk.Widget create_shared_folder_row (Object item) {
+        var folder = item as SharedFolder;
+        var row = new SharedFolderRow (folder);
+
+        row.removed.connect (manager.remove_item);
+
+        return row;
+    }
+}
+
+[GtkTemplate (ui = "/org/gnome/Boxes/ui/shared-folder-popover.ui")]
+private class Boxes.SharedFolderPopover: Gtk.Popover {
+    public signal bool saved (string path, string name);
+
+    [GtkChild]
+    public Gtk.FileChooserButton file_chooser_button;
+    [GtkChild]
+    public Gtk.Entry name_entry;
+
+    construct {
+        var default_path = Environment.get_user_special_dir (UserDirectory.PUBLIC_SHARE);
+        file_chooser_button.set_current_folder (default_path);
+    }
+
+    [GtkCallback]
+    public void on_cancel (Gtk.Button cancel_button) {
+        popdown ();
+    }
+
+    [GtkCallback]
+    public void on_save (Gtk.Button save_button) {
+        var uri = file_chooser_button.get_uri ();
+        File file = File.new_for_uri (uri);
+        var name = name_entry.get_text ();
+
+        if (uri != null) {
+            if (name == "")
+                name = file.get_basename ();
+
+            saved (file.get_path (), name);
+        }
+
+        popdown ();
+    }
+}
diff --git a/src/spice-display.vala b/src/spice-display.vala
index 5dc7af29..50f9b196 100644
--- a/src/spice-display.vala
+++ b/src/spice-display.vala
@@ -28,8 +28,6 @@
     private bool closed;
 
     private PortChannel webdav_channel;
-    private string shared_folder;
-    private GLib.Settings shared_folder_settings;
 
     private GLib.HashTable<Spice.Channel,SpiceChannelHandler> channel_handlers;
     private Display.OpenFDFunc? open_fd;
@@ -138,8 +136,6 @@ public SpiceDisplay (Machine machine, BoxConfig config, string host, int port, i
             session.cert_subject = GLib.Environment.get_variable ("BOXES_SPICE_HOST_SUBJECT");
 
         config.save_properties (gtk_session, gtk_session_saved_properties);
-
-        init_shared_folders ();
     }
 
     public SpiceDisplay.with_uri (Machine machine, BoxConfig config, string uri) {
@@ -151,8 +147,6 @@ public SpiceDisplay (Machine machine, BoxConfig config, string host, int port, i
         session.uri = uri;
 
         config.save_properties (gtk_session, gtk_session_saved_properties);
-
-        init_shared_folders ();
     }
 
     public SpiceDisplay.priv (Machine machine, BoxConfig config) {
@@ -162,8 +156,6 @@ public SpiceDisplay (Machine machine, BoxConfig config, string host, int port, i
         this.config = config;
 
         config.save_properties (gtk_session, gtk_session_saved_properties);
-
-        init_shared_folders ();
     }
 
     public override Gtk.Widget get_display (int n) {
@@ -297,173 +289,6 @@ private void on_channel_destroy (Spice.Session session, Spice.Channel channel) {
         access_finish ();
     }
 
-    private bool add_shared_folder (string path, string name) {
-        if (!FileUtils.test (shared_folder, FileTest.IS_DIR))
-            Posix.unlink (shared_folder);
-
-        if (!FileUtils.test (shared_folder, FileTest.EXISTS)) {
-            var ret = Posix.mkdir (shared_folder, 0755);
-
-            if (ret == -1) {
-                warning (strerror (errno));
-
-                return false;
-            }
-        }
-
-        var link_path = GLib.Path.build_filename (shared_folder, name);
-
-        var ret = GLib.FileUtils.symlink (path, link_path);
-        if (ret == -1) {
-            warning (strerror (errno));
-
-            return false;
-        }
-        add_gsetting_shared_folder (path, name);
-
-        return true;
-    }
-
-    private void remove_shared_folder (string name) {
-        if (!FileUtils.test (shared_folder, FileTest.EXISTS) || !FileUtils.test (shared_folder, 
FileTest.IS_DIR))
-            return;
-
-        var to_remove = GLib.Path.build_filename (shared_folder, name);
-        Posix.unlink (to_remove);
-
-        remove_gsetting_shared_folder (name);
-    }
-
-    private HashTable<string, string>? get_shared_folders () {
-        if (!FileUtils.test (shared_folder, FileTest.EXISTS) || !FileUtils.test (shared_folder, 
FileTest.IS_DIR))
-            return null;
-
-        var hash = new HashTable <string, string> (str_hash, str_equal);
-        try {
-            Dir dir = Dir.open (shared_folder, 0);
-            string? name = null;
-
-            while ((name = dir.read_name ()) != null) {
-                var path = Path.build_filename (shared_folder, name);
-                if (FileUtils.test (path, FileTest.IS_SYMLINK)) {
-                    var folder = GLib.FileUtils.read_link (path);
-
-                    hash[name] = folder;
-                }
-            }
-        } catch (GLib.FileError err) {
-            warning (err.message);
-        }
-
-        return hash;
-    }
-
-    private void init_shared_folders () {
-        shared_folder = GLib.Path.build_filename (GLib.Environment.get_user_config_dir (), "gnome-boxes", 
machine.config.uuid);
-
-        shared_folder_settings = new GLib.Settings ("org.gnome.boxes");
-        var hash = parse_shared_folders ();
-        var names = hash.get_keys ();
-        foreach (var name in names) {
-            add_shared_folder (hash[name], name);
-        }
-    }
-
-    private HashTable<string, string> parse_shared_folders () {
-        var hash = new HashTable <string, string> (str_hash, str_equal);
-
-        string shared_folders = shared_folder_settings.get_string("shared-folders");
-        if (shared_folders == "")
-            return hash;
-
-        try {
-            GLib.Variant? entry = null;
-            string uuid_str;
-            string path_str;
-            string name_str;
-
-            var variant = Variant.parse (new GLib.VariantType.array (GLib.VariantType.VARIANT), 
shared_folders);
-            VariantIter iter = variant.iterator ();
-            while (iter.next ("v",  &entry)) {
-                entry.lookup ("uuid", "s", out uuid_str);
-                entry.lookup ("path", "s", out path_str);
-                entry.lookup ("name", "s", out name_str);
-
-                if (machine.config.uuid == uuid_str)
-                    hash[name_str] = path_str;
-            }
-        } catch (VariantParseError err) {
-            warning (err.message);
-        }
-
-        return hash;
-    }
-
-    private void add_gsetting_shared_folder (string path, string name) {
-        var variant_builder = new GLib.VariantBuilder (new GLib.VariantType.array (VariantType.VARIANT));
-
-        string shared_folders = shared_folder_settings.get_string ("shared-folders");
-        if (shared_folders != "") {
-            try {
-                GLib.Variant? entry = null;
-
-                var variant = Variant.parse (new GLib.VariantType.array (GLib.VariantType.VARIANT), 
shared_folders);
-                VariantIter iter = variant.iterator ();
-                while (iter.next ("v",  &entry)) {
-                    variant_builder.add ("v",  entry);
-                }
-            } catch (VariantParseError err) {
-                warning (err.message);
-            }
-        }
-
-        var entry_variant_builder = new GLib.VariantBuilder (GLib.VariantType.VARDICT);
-
-        var uuid_variant = new GLib.Variant ("s", machine.config.uuid);
-        var path_variant = new GLib.Variant ("s", path);
-        var name_variant = new GLib.Variant ("s", name);
-        entry_variant_builder.add ("{sv}", "uuid", uuid_variant);
-        entry_variant_builder.add ("{sv}", "path", path_variant);
-        entry_variant_builder.add ("{sv}", "name", name_variant);
-        var entry_variant = entry_variant_builder.end ();
-
-        variant_builder.add ("v",  entry_variant);
-        var variant = variant_builder.end ();
-
-        shared_folder_settings.set_string ("shared-folders", variant.print (true));
-    }
-
-    private void remove_gsetting_shared_folder (string name) {
-        var variant_builder = new GLib.VariantBuilder (new GLib.VariantType.array (VariantType.VARIANT));
-
-        string shared_folders = shared_folder_settings.get_string ("shared-folders");
-        if (shared_folders == "")
-            return;
-
-        try {
-            GLib.Variant? entry = null;
-            string name_str;
-            string uuid_str;
-
-            var variant = Variant.parse (new GLib.VariantType.array (GLib.VariantType.VARIANT), 
shared_folders);
-            VariantIter iter = variant.iterator ();
-            while (iter.next ("v",  &entry)) {
-                entry.lookup ("uuid", "s", out uuid_str);
-                entry.lookup ("name", "s", out name_str);
-
-                if (uuid_str == machine.config.uuid && name_str == name)
-                    continue;
-
-                variant_builder.add ("v", entry);
-            }
-            variant = variant_builder.end ();
-
-            shared_folder_settings.set_string ("shared-folders", variant.print (true));
-        } catch (VariantParseError err) {
-            warning (err.message);
-        }
-    }
-
     private void main_event (ChannelEvent event) {
         switch (event) {
         case ChannelEvent.CLOSED:
@@ -565,7 +390,8 @@ private void on_new_file_transfer (Spice.MainChannel main_channel, Object transf
             if (webdav_channel == null || !webdav_channel.port_opened)
                 break;
 
-            session.shared_dir = shared_folder;
+            session.shared_dir = GLib.Path.build_filename (GLib.Environment.get_user_config_dir (),
+                                                           "gnome-boxes", machine.config.uuid);;
 
             var frame = create_shared_folders_frame ();
             add_property (ref list, _("Folder Shares"), new Gtk.Label (""), frame);
@@ -679,71 +505,7 @@ public override void send_keys (uint[] keyvals) {
     }
 
     private Gtk.Frame create_shared_folders_frame () {
-        var frame = new Gtk.Frame (null);
-        var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
-        var listbox = new Gtk.ListBox ();
-        var button_plus = new Gtk.Button.from_icon_name ("list-add-symbolic", IconSize.BUTTON);
-        button_plus.halign = Gtk.Align.CENTER;
-        button_plus.get_style_context ().add_class ("flat");
-
-        box.pack_start (listbox, true, true, 0);
-        box.pack_end (button_plus, false, false, 6);
-        frame.add (box);
-
-        var popover = new SharedFolderPopover ();
-
-        button_plus.clicked.connect (() => {
-            popover.relative_to = button_plus;
-            popover.target_position = -1;
-
-            popover.popup ();
-        });
-
-        listbox.row_activated.connect ((row) => {
-            popover.relative_to = row;
-            popover.target_position = row.get_index ();
-
-            var folder_row = row as SharedFolderRow;
-            popover.file_chooser_button.set_uri ("file://" + folder_row.folder_path);
-            popover.name_entry.set_text (folder_row.folder_name);
-
-            popover.popup ();
-        });
-
-        var hash = get_shared_folders ();
-        if (hash != null) {
-            var keys = hash.get_keys ();
-            foreach (var key in keys) {
-                add_listbox_row (listbox, hash[key], key, -1);
-            }
-        }
-
-        popover.saved.connect ((path, name, target_position) => {
-            // Update previous entry
-            if (target_position != - 1) {
-                var row = listbox.get_row_at_index (target_position) as Boxes.SharedFolderRow;
-                remove_shared_folder (row.folder_name);
-            }
-
-            if (add_shared_folder (path, name))
-                add_listbox_row (listbox, path, name, target_position);
-        });
-
-        return frame;
-    }
-
-    private void add_listbox_row (Gtk.ListBox listbox, string path, string name, int target_position) {
-        var listboxrow = new SharedFolderRow (path, name);
-
-        if (target_position != -1)
-            listbox.remove (listbox.get_row_at_index (target_position));
-
-        listbox.insert (listboxrow, target_position);
-
-        listboxrow.removed.connect (() => {
-            listbox.remove (listboxrow);
-            remove_shared_folder (name);
-        });
+        return new SharedFoldersWidget (machine.config.uuid);
     }
 
     private bool is_usb_kbd_or_mouse (uint8 class, uint8 subclass, uint8 protocol) {
@@ -861,28 +623,3 @@ static void spice_validate_uri (string uri_as_text,
         throw new Boxes.Error.INVALID (_("Invalid URL"));
     }
 }
-
-[GtkTemplate (ui = "/org/gnome/Boxes/ui/properties-shared-folder-row.ui")]
-private class Boxes.SharedFolderRow : Gtk.ListBoxRow {
-    public string folder_path { set; get; }
-    public string folder_name { set; get; }
-
-    public signal void removed ();
-    [GtkChild]
-    private Gtk.Label folder_path_label;
-    [GtkChild]
-    private Gtk.Label folder_name_label;
-
-    public SharedFolderRow (string path, string name) {
-        this.folder_path = path;
-        this.folder_name = name;
-
-        bind_property ("folder_path", folder_path_label, "label", BindingFlags.SYNC_CREATE);
-        bind_property ("folder_name", folder_name_label, "label", BindingFlags.SYNC_CREATE);
-    }
-
-    [GtkCallback]
-    private void on_delete_button_clicked () {
-        removed ();
-    }
-}


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