[gnome-contacts] Split out IndividualData to Contact class



commit 9f29e98d017709e9c5d4bdb8c17533949921238c
Author: Alexander Larsson <alexl redhat com>
Date:   Thu May 12 13:55:06 2011 +0200

    Split out IndividualData to Contact class

 src/Makefile.am           |    1 +
 src/contacts-app.vala     |  173 +++++----------------------------------
 src/contacts-contact.vala |  198 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 219 insertions(+), 153 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 21c6b72..19489bc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,6 +17,7 @@ bin_PROGRAMS = gnome-contacts
 
 gnome_contacts_SOURCES = \
 	contacts-app.vala \
+	contacts-contact.vala \
 	main.vala \
 	$(NULL)
 
diff --git a/src/contacts-app.vala b/src/contacts-app.vala
index cc074e3..bb96883 100644
--- a/src/contacts-app.vala
+++ b/src/contacts-app.vala
@@ -21,40 +21,8 @@ using Gtk;
 using Folks;
 
 public class Contacts.App : Window {
-  protected class IndividualData  {
-    public TreeIter iter;
-    public Gdk.Pixbuf? avatar;
-    public string filter_data;
-
-    public void update (Individual individual) {
-      var builder = new StringBuilder ();
-      if (individual.alias != null) {
-	builder.append (individual.alias.casefold ());
-	builder.append_unichar (' ');
-      }
-      if (individual.full_name != null) {
-	builder.append (individual.full_name.casefold ());
-	builder.append_unichar (' ');
-      }
-      if (individual.nickname != null) {
-	builder.append (individual.nickname.casefold ());
-	builder.append_unichar (' ');
-      }
-      var im_addresses = individual.im_addresses;
-      foreach (string addr in im_addresses.get_values ()) {
-	builder.append (addr.casefold ());
-	builder.append_unichar (' ');
-      }
-      var emails = individual.email_addresses;
-      foreach (var email in emails) {
-	builder.append (email.value.casefold ());
-	builder.append_unichar (' ');
-      }
-      filter_data = builder.str;
-    }
-  }
   private ListStore group_store;
-  private ListStore contacts_store;
+  private ContactStore contacts_store;
   private TreeModelFilter filter_model;
   private Entry filter_entry;
   string []? filter_values;
@@ -66,7 +34,6 @@ public class Contacts.App : Window {
 
   public IndividualAggregator aggregator { get; private set; }
   public BackendStore backend_store { get; private set; }
-  Gdk.Pixbuf fallback_avatar;
 
   private enum GroupColumns {
     TEXT,
@@ -110,69 +77,6 @@ public class Contacts.App : Window {
     tree_view.append_column (column);
   }
 
-  private void round_rect (Cairo.Context cr, int x, int y, int w, int h, int r) {
-    cr.move_to(x+r,y);
-    cr.line_to(x+w-r,y);
-    cr.curve_to(x+w,y,x+w,y,x+w,y+r);
-    cr.line_to(x+w,y+h-r);
-    cr.curve_to(x+w,y+h,x+w,y+h,x+w-r,y+h);
-    cr.line_to(x+r,y+h);
-    cr.curve_to(x,y+h,x,y+h,x,y+h-r);
-    cr.line_to(x,y+r);
-    cr.curve_to(x,y,x,y,x+r,y);
-  }
-
-  private Gdk.Pixbuf draw_fallback_avatar () {
-    var cst = new Cairo.ImageSurface (Cairo.Format.ARGB32, 48, 48);
-    var cr = new Cairo.Context (cst);
-
-    cr.save ();
-
-    var gradient = new Cairo.Pattern.linear (1,  1, 1, 1+48);
-    gradient.add_color_stop_rgb (0, 0.7098, 0.7098, 0.7098);
-    gradient.add_color_stop_rgb (1, 0.8901, 0.8901, 0.8901);
-    cr.set_source (gradient);
-    cr.rectangle (1, 1, 46, 46);
-    cr.fill ();
-
-    cr.restore ();
-
-    try {
-      var icon_info = IconTheme.get_default ().lookup_icon ("avatar-default", 48, IconLookupFlags.GENERIC_FALLBACK);
-      var image = icon_info.load_icon ();
-      if (image != null) {
-	Gdk.cairo_set_source_pixbuf (cr, image, 3, 3);
-	cr.paint();
-      }
-    } catch {
-    }
-
-
-    cr.push_group ();
-
-    cr.set_source_rgba (0, 0, 0, 0);
-    cr.paint ();
-    round_rect (cr, 0, 0, 48, 48, 5);
-    cr.set_source_rgb (0.74117, 0.74117, 0.74117);
-    cr.fill ();
-    round_rect (cr, 1, 1, 46, 46, 5);
-    cr.set_source_rgb (1, 1, 1);
-    cr.fill ();
-    round_rect (cr, 2, 2, 44, 44, 5);
-    cr.set_source_rgb (0.341176, 0.341176, 0.341176);
-    cr.fill ();
-    cr.set_operator (Cairo.Operator.CLEAR);
-    round_rect (cr, 3, 3, 42, 42, 5);
-    cr.set_source_rgba (0, 0, 0, 0);
-    cr.fill ();
-
-    var pattern = cr.pop_group ();
-    cr.set_source (pattern);
-    cr.paint ();
-
-    return Gdk.pixbuf_get_from_surface (cst, 0, 0, 48, 48);
-  }
-
   private void fill_group_model () {
     TreeIter iter;
     group_store.append (out iter);
@@ -183,20 +87,6 @@ public class Contacts.App : Window {
     group_store.set (iter, GroupColumns.IS_HEADER, false, GroupColumns.TEXT, "Work", GroupColumns.GROUP, "Buddies");
   }
 
-  // TODO: This should be async, but the vala bindings are broken (bug #649875)
-  private Gdk.Pixbuf load_icon (File ?file) {
-    Gdk.Pixbuf? res = fallback_avatar;
-    if (file != null) {
-      try {
-	var stream = file.read ();
-	Cancellable c = new Cancellable ();
-	res = new Gdk.Pixbuf.from_stream_at_scale (stream, 48, 48, true, c);
-      } catch (Error e) {
-      }
-    }
-    return res;
-  }
-
   private void setup_contacts_view (TreeView tree_view) {
     tree_view.set_headers_visible (false);
 
@@ -209,34 +99,32 @@ public class Contacts.App : Window {
     var icon = new CellRendererPixbuf ();
     column.pack_start (icon, false);
     column.set_cell_data_func (icon, (column, cell, model, iter) => {
-	Individual individual;
+	Contact contact;
 
-	model.get (iter, 0, out individual);
+	model.get (iter, 0, out contact);
 
-	IndividualData data = individual.get_data("contacts-data");
-	if (data.avatar == null)
-	  data.avatar = load_icon (individual.avatar);
-	cell.set ("pixbuf", data.avatar);
+	cell.set ("pixbuf", contact.avatar);
       });
 
     var text = new CellRendererText ();
     column.pack_start (text, true);
     text.set ("weight", Pango.Weight.BOLD);
     column.set_cell_data_func (text, (column, cell, model, iter) => {
-	Individual individual;
+	Contact contact;
 
-	model.get (iter, 0, out individual);
+	model.get (iter, 0, out contact);
 
-	string? alias = individual.alias;
+	string? alias = contact.individual.alias;
 	cell.set ("text", alias);
       });
 
     icon = new CellRendererPixbuf ();
     column.pack_start (icon, false);
     column.set_cell_data_func (icon, (column, cell, model, iter) => {
-	Individual individual;
+	Contact contact;
 
-	model.get (iter, 0, out individual);
+	model.get (iter, 0, out contact);
+	Individual individual = contact.individual;
 
 	string? iconname = null;
 	switch (individual.presence_type) {
@@ -262,32 +150,25 @@ public class Contacts.App : Window {
 
   private bool filter_row (TreeModel model,
 			   TreeIter iter) {
-    Individual individual;
+    Contact contact;
 
-    model.get (iter, 0, out individual);
+    model.get (iter, 0, out contact);
 
-    if (individual == null)
+    if (contact == null)
       return false;
 
-    IndividualData data = individual.get_data("contacts-data");
-
-    if (filter_favourites && !individual.is_favourite)
+    if (filter_favourites && !contact.individual.is_favourite)
       return false;
 
     if (filter_group != null) {
-      if (!(filter_group in individual.groups))
+      if (!(filter_group in contact.individual.groups))
 	return false;
     }
 
     if (filter_values == null || filter_values.length == 0)
       return true;
 
-
-    foreach (string i in filter_values) {
-      if (! (i in data.filter_data))
-	return false;
-    }
-    return true;
+    return contact.contains_strings (filter_values);
   }
 
   private void group_selected_changed (TreeSelection selection) {
@@ -331,31 +212,17 @@ public class Contacts.App : Window {
   }
 
   public App () {
-    fallback_avatar = draw_fallback_avatar ();
-
-    contacts_store = new ListStore(1, typeof (Folks.Individual));
-    filter_model = new TreeModelFilter(contacts_store, null);
+    contacts_store = new ContactStore ();
+    filter_model = new TreeModelFilter (contacts_store, null);
     filter_model.set_visible_func (filter_row);
 
     aggregator = new IndividualAggregator ();
     aggregator.individuals_changed.connect ((added, removed, m, a, r) =>   {
 	foreach (Individual i in removed) {
-	  IndividualData? data = i.get_data("contacts-data");
-	  if (data != null) {
-	    contacts_store.remove (data.iter);
-	  } else {
-	    stdout.printf("removed %p with no data!\n", i);
-	  }
+	  contacts_store.remove_individual (i);
 	}
 	foreach (Individual i in added) {
-	  var data = new IndividualData();
-	  i.set_data ("contacts-data", data);
-
-	  contacts_store.append (out data.iter);
-	  contacts_store.set (data.iter, 0, i);
-
-	  data.update (i);
-	  /* TODO: Connect to notify(?) for changes */
+	  contacts_store.insert_individual (i);
 	}
       });
     aggregator.prepare ();
diff --git a/src/contacts-contact.vala b/src/contacts-contact.vala
new file mode 100644
index 0000000..0774189
--- /dev/null
+++ b/src/contacts-contact.vala
@@ -0,0 +1,198 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 8 -*- */
+/*
+ * Copyright (C) 2011 Alexander Larsson <alexl redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+using Gtk;
+using Folks;
+
+public class Contacts.ContactStore : ListStore  {
+  public ContactStore () {
+    GLib.Type[] types = { typeof (Contact) };
+    
+    set_column_types (types);
+  }
+  public Contact insert_individual (Individual i) {
+    return new Contact (i, this);
+  }
+  public void remove_individual (Individual i) {
+    Contact contact = Contact.from_individual (i);
+    if (contact != null) {
+      contact.remove ();
+    } else {
+      stdout.printf("removed individual %p with no contact!\n", i);
+    }
+  }
+}
+
+public class Contacts.Contact : GLib.Object  {
+  static Gdk.Pixbuf fallback_avatar;
+
+  public Individual individual;
+  public ContactStore store;
+  private TreeIter iter;
+
+  private Gdk.Pixbuf? _avatar;
+  public Gdk.Pixbuf avatar { 
+    get {
+      if (_avatar == null)
+	_avatar = load_icon (individual.avatar);
+      return _avatar;
+    }
+  }
+
+  private string filter_data;
+
+  public static Contact from_individual (Individual i) {
+    return i.get_data ("contact");
+  }
+
+  static construct {
+    fallback_avatar = draw_fallback_avatar ();
+  }
+   
+  public Contact(Individual i, ContactStore s) {
+    individual = i;
+    store = s;
+    individual.set_data ("contact", this);
+    update ();
+
+    store.append (out iter);
+    store.set (iter, 0, this);
+
+    individual.notify.connect( (pspec) => {
+	update ();
+	stdout.printf ("changed: %s\n", pspec.get_name());
+      });
+  }
+
+  public void remove () {
+    store.remove (this.iter);
+  }
+
+  public bool contains_strings (string [] strings) {
+    foreach (string i in strings) {
+      if (! (i in filter_data))
+	return false;
+    }
+    return true;
+  }
+
+  private void update () {
+    var builder = new StringBuilder ();
+    if (individual.alias != null) {
+      builder.append (individual.alias.casefold ());
+      builder.append_unichar (' ');
+    }
+    if (individual.full_name != null) {
+      builder.append (individual.full_name.casefold ());
+      builder.append_unichar (' ');
+    }
+    if (individual.nickname != null) {
+      builder.append (individual.nickname.casefold ());
+      builder.append_unichar (' ');
+    }
+    var im_addresses = individual.im_addresses;
+    foreach (string addr in im_addresses.get_values ()) {
+      builder.append (addr.casefold ());
+      builder.append_unichar (' ');
+    }
+    var emails = individual.email_addresses;
+    foreach (var email in emails) {
+      builder.append (email.value.casefold ());
+      builder.append_unichar (' ');
+    }
+    filter_data = builder.str;
+  }
+
+  // TODO: This should be async, but the vala bindings are broken (bug #649875)
+  private Gdk.Pixbuf load_icon (File ?file) {
+    Gdk.Pixbuf? res = fallback_avatar;
+    if (file != null) {
+      try {
+	var stream = file.read ();
+	Cancellable c = new Cancellable ();
+	res = new Gdk.Pixbuf.from_stream_at_scale (stream, 48, 48, true, c);
+      } catch (Error e) {
+      }
+    }
+    return res;
+  }
+
+  private static void round_rect (Cairo.Context cr, int x, int y, int w, int h, int r) {
+    cr.move_to(x+r,y);
+    cr.line_to(x+w-r,y);
+    cr.curve_to(x+w,y,x+w,y,x+w,y+r);
+    cr.line_to(x+w,y+h-r);
+    cr.curve_to(x+w,y+h,x+w,y+h,x+w-r,y+h);
+    cr.line_to(x+r,y+h);
+    cr.curve_to(x,y+h,x,y+h,x,y+h-r);
+    cr.line_to(x,y+r);
+    cr.curve_to(x,y,x,y,x+r,y);
+  }
+
+  private static Gdk.Pixbuf draw_fallback_avatar () {
+    var cst = new Cairo.ImageSurface (Cairo.Format.ARGB32, 48, 48);
+    var cr = new Cairo.Context (cst);
+
+    cr.save ();
+
+    var gradient = new Cairo.Pattern.linear (1,  1, 1, 1+48);
+    gradient.add_color_stop_rgb (0, 0.7098, 0.7098, 0.7098);
+    gradient.add_color_stop_rgb (1, 0.8901, 0.8901, 0.8901);
+    cr.set_source (gradient);
+    cr.rectangle (1, 1, 46, 46);
+    cr.fill ();
+
+    cr.restore ();
+
+    try {
+      var icon_info = IconTheme.get_default ().lookup_icon ("avatar-default", 48, IconLookupFlags.GENERIC_FALLBACK);
+      var image = icon_info.load_icon ();
+      if (image != null) {
+	Gdk.cairo_set_source_pixbuf (cr, image, 3, 3);
+	cr.paint();
+      }
+    } catch {
+    }
+
+
+    cr.push_group ();
+
+    cr.set_source_rgba (0, 0, 0, 0);
+    cr.paint ();
+    round_rect (cr, 0, 0, 48, 48, 5);
+    cr.set_source_rgb (0.74117, 0.74117, 0.74117);
+    cr.fill ();
+    round_rect (cr, 1, 1, 46, 46, 5);
+    cr.set_source_rgb (1, 1, 1);
+    cr.fill ();
+    round_rect (cr, 2, 2, 44, 44, 5);
+    cr.set_source_rgb (0.341176, 0.341176, 0.341176);
+    cr.fill ();
+    cr.set_operator (Cairo.Operator.CLEAR);
+    round_rect (cr, 3, 3, 42, 42, 5);
+    cr.set_source_rgba (0, 0, 0, 0);
+    cr.fill ();
+
+    var pattern = cr.pop_group ();
+    cr.set_source (pattern);
+    cr.paint ();
+
+    return Gdk.pixbuf_get_from_surface (cst, 0, 0, 48, 48);
+  }
+}



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