[gnome-clocks] Bind the model to the content view



commit 2347d0eb039ecdeac65a64bd83f2f6fc36df99b0
Author: Paolo Borelli <pborelli gnome org>
Date:   Sun Feb 7 17:32:36 2016 +0100

    Bind the model to the content view

 src/alarm.vala   |    5 +--
 src/widgets.vala |  119 +++++++++++------------------------------------------
 src/world.vala   |    6 +--
 3 files changed, 27 insertions(+), 103 deletions(-)
---
diff --git a/src/alarm.vala b/src/alarm.vala
index 0674ab8..63de629 100644
--- a/src/alarm.vala
+++ b/src/alarm.vala
@@ -569,6 +569,7 @@ public class Face : Gtk.Stack, Clocks.Clock {
         new_button.action_name = "win.new";
         header_bar.pack_start (new_button);
 
+        content_view.bind_model (alarms);
         content_view.set_header_bar (header_bar);
 
         load ();
@@ -630,9 +631,6 @@ public class Face : Gtk.Stack, Clocks.Clock {
 
     private void load () {
         alarms.deserialize (settings.get_value ("alarms"), Item.deserialize);
-        alarms.foreach ((item) => {
-            content_view.add_item (item);
-        });
     }
 
     private void save () {
@@ -676,7 +674,6 @@ public class Face : Gtk.Stack, Clocks.Clock {
                 var alarm = new Item ();
                 ((SetupDialog) dialog).apply_to_alarm (alarm);
                 alarms.append (alarm);
-                content_view.add_item (alarm);
                 alarm.reset();
                 save ();
             }
diff --git a/src/widgets.vala b/src/widgets.vala
index 8cec1cd..7cdab93 100644
--- a/src/widgets.vala
+++ b/src/widgets.vala
@@ -479,11 +479,9 @@ private class IconView : Gtk.IconView {
         store.set (i, Column.SELECTED, false, Column.ITEM, item);
     }
 
-    public void prepend (Object item) {
-        var store = (Gtk.ListStore) model;
-        Gtk.TreeIter i;
-        store.insert (out i, 0);
-        store.set (i, Column.SELECTED, false, Column.ITEM, item);
+    public new void clear () {
+        var model = get_model () as Gtk.ListStore;
+        model.clear ();
     }
 
     // Redefine selection handling methods since we handle selection manually
@@ -524,18 +522,6 @@ private class IconView : Gtk.IconView {
         });
         selection_changed ();
     }
-
-    public void remove_selected () {
-        var paths =  get_selected_items ();
-        paths.reverse ();
-        foreach (Gtk.TreePath path in paths) {
-            Gtk.TreeIter i;
-            if (((Gtk.ListStore) model).get_iter (out i, path)) {
-                ((Gtk.ListStore) model).remove (i);
-            }
-        }
-        selection_changed ();
-    }
 }
 
 public class ContentView : Gtk.Bin {
@@ -559,6 +545,7 @@ public class ContentView : Gtk.Bin {
     }
 
     private bool _can_select;
+    private ContentStore model;
     private IconView icon_view;
     private Gtk.Button select_button;
     private Gtk.Button cancel_button;
@@ -648,83 +635,27 @@ public class ContentView : Gtk.Bin {
     }
 
     public signal void item_activated (ContentItem item);
-
-    public virtual signal void delete_selected () {
-        icon_view.remove_selected ();
-        update_props_on_remove ();
-    }
-
-    public void add_item (ContentItem item) {
-        icon_view.add_item (item);
-        update_props_on_insert (item);
-    }
-
-    public void prepend (ContentItem item) {
-        icon_view.prepend (item);
-        update_props_on_insert (item);
-    }
-
-    private void update_props_on_remove () {
-        Gtk.TreeIter iter;
-
-        var local_empty = true;
-        var local_can_select = false;
-        if (icon_view.model.get_iter_first (out iter)) {
-            local_empty = false;
-
-            // Looping is not efficient in theory, but in practice the only
-            // cases we have are:
-            //  - only the geolocation item
-            //  - at least one other item
-            // so we always break out of the loop at the first or second item
-            do {
-                ContentItem item;
-                icon_view.model.get (iter, IconView.Column.ITEM, out item);
-                if (item.selectable) {
-                   local_can_select = true;
-                   break;
-                }
-            } while (icon_view.model.iter_next (ref iter));
-        }
-
-        if (local_empty != empty) {
-            empty = local_empty;
-        }
-
-        if (local_can_select != can_select) {
-            can_select = local_can_select;
-        }
-    }
-
-    // We cannot connect to the row-inserted signal because the row is
-    // still empty so we cannot check item.selectable
-    private void update_props_on_insert (ContentItem item) {
-        if (empty) {
-            empty = false;
-        }
-        if (!can_select && item.selectable) {
-            can_select = true;
-        }
-    }
-
-    // Note: this is not efficient: we first walk the model to collect
-    // a list then the caller has to walk this list and then it has to
-    // delete the items from the view, which walks the model again...
-    // Our models are small enough that it does not matter and hopefully
-    // we will get rid of GtkListStore/GtkIconView soon.
-    public List<Object>? get_selected_items () {
-        var items = new List<Object> ();
-        var store = (Gtk.ListStore) icon_view.model;
-        foreach (Gtk.TreePath path in icon_view.get_selected_items ()) {
-            Gtk.TreeIter i;
-            if (store.get_iter (out i, path)) {
-                Object item;
-                store.get (i, IconView.Column.ITEM, out item);
-                items.prepend (item);
-            }
-        }
-        items.reverse ();
-        return (owned) items;
+    public signal void delete_selected ();
+
+    public void bind_model (ContentStore store) {
+        model = store;
+        model.items_changed.connect ((position, removed, added) => {
+            empty = model.get_n_items () == 0;
+
+            var first_selectable = model.find ((i) => {
+                return i.selectable;
+            });
+
+            can_select = first_selectable != null;
+
+            // Just clear and repopulate the GtkTreeModel...
+            // it sucks, but there is no easy way to sync to a GListMode
+            // and we always have few items.
+            icon_view.clear ();
+            model.foreach ((item) => {
+                icon_view.add_item (item);
+            });
+        });
     }
 
     public void select_all () {
diff --git a/src/world.vala b/src/world.vala
index c4d42f5..e0af119 100644
--- a/src/world.vala
+++ b/src/world.vala
@@ -283,6 +283,7 @@ public class Face : Gtk.Stack, Clocks.Clock {
         });
         header_bar.pack_start (back_button);
 
+        content_view.bind_model (locations);
         content_view.set_header_bar (header_bar);
         content_view.set_sorting(Gtk.SortType.ASCENDING, (item1, item2) => {
             var offset1 = ((Item) item1).location.get_timezone().get_offset();
@@ -357,9 +358,6 @@ public class Face : Gtk.Stack, Clocks.Clock {
 
     private void load () {
         locations.deserialize (settings.get_value ("world-clocks"), Item.deserialize);
-        locations.foreach ((item) => {
-            content_view.add_item (item);
-        });
     }
 
     private void save () {
@@ -383,7 +381,6 @@ public class Face : Gtk.Stack, Clocks.Clock {
             item.selectable = false;
             item.title_icon = "find-location-symbolic";
             locations.append (item);
-            content_view.prepend (item);
         });
 
         yield geo_info.seek ();
@@ -391,7 +388,6 @@ public class Face : Gtk.Stack, Clocks.Clock {
 
     private void add_location_item (Item item) {
         locations.append (item);
-        content_view.add_item (item);
         save ();
     }
 


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