[empathy] Add support for marking contacts as favorites (which gives them a highlighted star next to their nam



commit b8657a61fe72be0da2d91325b0851dd4d7fd533c
Author: Travis Reitter <treitter gmail com>
Date:   Tue Feb 16 10:11:43 2010 -0800

    Add support for marking contacts as favorites (which gives them a highlighted
    star next to their name and adds them to the top of the contact list)

 libempathy-gtk/empathy-contact-list-store.c |   69 +++++++++++++++++++--
 libempathy-gtk/empathy-contact-list-store.h |    3 +-
 libempathy-gtk/empathy-contact-list-view.c  |   89 +++++++++++++++++++++++++++
 libempathy-gtk/empathy-images.h             |    2 +
 libempathy/empathy-contact-list.c           |   17 +++++
 libempathy/empathy-contact-list.h           |    7 ++
 6 files changed, 181 insertions(+), 6 deletions(-)
---
diff --git a/libempathy-gtk/empathy-contact-list-store.c b/libempathy-gtk/empathy-contact-list-store.c
index 53a0934..8592fe9 100644
--- a/libempathy-gtk/empathy-contact-list-store.c
+++ b/libempathy-gtk/empathy-contact-list-store.c
@@ -824,6 +824,7 @@ contact_list_store_setup (EmpathyContactListStore *store)
 		G_TYPE_BOOLEAN,       /* Can make audio calls */
 		G_TYPE_BOOLEAN,       /* Can make video calls */
 		EMPATHY_TYPE_CONTACT_LIST_FLAGS, /* Flags */
+		G_TYPE_BOOLEAN,       /* Is a favourite */
 	};
 
 	priv = GET_PRIV (store);
@@ -1095,6 +1096,17 @@ contact_list_store_remove_contact (EmpathyContactListStore *store,
 	g_list_free (iters);
 }
 
+static gboolean
+list_store_contact_is_favourite (EmpathyContactListStore *store,
+				 EmpathyContact          *contact)
+{
+	EmpathyContactListStorePriv *priv;
+
+	priv = GET_PRIV (store);
+
+	return empathy_contact_list_contact_is_favourite (priv->list, contact);
+}
+
 static void
 contact_list_store_contact_update (EmpathyContactListStore *store,
 				   EmpathyContact          *contact)
@@ -1210,6 +1222,7 @@ contact_list_store_contact_update (EmpathyContactListStore *store,
 	pixbuf_status = contact_list_store_get_contact_status_icon (store, contact);
 	for (l = iters; l && set_model; l = l->next) {
 		gtk_tree_store_set (GTK_TREE_STORE (store), l->data,
+				    EMPATHY_CONTACT_LIST_STORE_COL_IS_FAVOURITE, list_store_contact_is_favourite (store, contact),
 				    EMPATHY_CONTACT_LIST_STORE_COL_ICON_STATUS, pixbuf_status,
 				    EMPATHY_CONTACT_LIST_STORE_COL_PIXBUF_AVATAR, pixbuf_avatar,
 				    EMPATHY_CONTACT_LIST_STORE_COL_PIXBUF_AVATAR_VISIBLE, show_avatar,
@@ -1433,6 +1446,20 @@ contact_list_store_get_group (EmpathyContactListStore *store,
 				    EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, TRUE,
 				    -1);
 
+		/* add a second separator for the favourite contacts group, to
+		 * always be sorted at the end. This will provide a visual
+		 * distinction between the end of the favourites and the
+		 * beginning of the ungrouped contacts */
+		if (!g_strcmp0 (name, EMPATHY_GROUP_FAVOURITES)) {
+			gtk_tree_store_append (GTK_TREE_STORE (store),
+					&iter_separator,
+					&iter_group);
+			gtk_tree_store_set (GTK_TREE_STORE (store), &iter_separator,
+					EMPATHY_CONTACT_LIST_STORE_COL_NAME, EMPATHY_GROUP_FAVOURITES,
+					EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, TRUE,
+					-1);
+		}
+
 		if (iter_separator_to_set) {
 			*iter_separator_to_set = iter_separator;
 		}
@@ -1483,13 +1510,29 @@ contact_list_store_state_sort_func (GtkTreeModel *model,
 			    EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, &is_separator_b,
 			    -1);
 
-	/* Separator or group? */
+	/* Separator, favourites group, or other group? */
 	if (is_separator_a || is_separator_b) {
 		if (is_separator_a) {
-			ret_val = -1;
+			/* sort the special favourites group 2nd separator at
+			 * the end */
+			if (!g_strcmp0 (name_a, EMPATHY_GROUP_FAVOURITES)) {
+				ret_val = 1;
+			} else {
+				ret_val = -1;
+			}
 		} else if (is_separator_b) {
-			ret_val = 1;
+			if (!g_strcmp0 (name_b, EMPATHY_GROUP_FAVOURITES)) {
+				ret_val = -1;
+			} else {
+				ret_val = 1;
+			}
 		}
+	} else if (!contact_a && !g_strcmp0 (name_a,
+				EMPATHY_GROUP_FAVOURITES)) {
+		ret_val = -1;
+	} else if (!contact_b && !g_strcmp0 (name_b,
+				EMPATHY_GROUP_FAVOURITES)) {
+		ret_val = 1;
 	} else if (!contact_a && contact_b) {
 		ret_val = 1;
 	} else if (contact_a && !contact_b) {
@@ -1556,10 +1599,26 @@ contact_list_store_name_sort_func (GtkTreeModel *model,
 
 	if (is_separator_a || is_separator_b) {
 		if (is_separator_a) {
-			ret_val = -1;
+			/* sort the special favourites group 2nd separator at
+			 * the end */
+			if (!g_strcmp0 (name_a, EMPATHY_GROUP_FAVOURITES)) {
+				ret_val = 1;
+			} else {
+				ret_val = -1;
+			}
 		} else if (is_separator_b) {
-			ret_val = 1;
+			if (!g_strcmp0 (name_b, EMPATHY_GROUP_FAVOURITES)) {
+				ret_val = -1;
+			} else {
+				ret_val = 1;
+			}
 		}
+	} else if (!contact_a && !g_strcmp0 (name_a,
+				EMPATHY_GROUP_FAVOURITES)) {
+		ret_val = -1;
+	} else if (!contact_b && !g_strcmp0 (name_b,
+				EMPATHY_GROUP_FAVOURITES)) {
+		ret_val = 1;
 	} else if (!contact_a && contact_b) {
 		ret_val = 1;
 	} else if (contact_a && !contact_b) {
diff --git a/libempathy-gtk/empathy-contact-list-store.h b/libempathy-gtk/empathy-contact-list-store.h
index afefd28..b852a1b 100644
--- a/libempathy-gtk/empathy-contact-list-store.h
+++ b/libempathy-gtk/empathy-contact-list-store.h
@@ -63,7 +63,8 @@ typedef enum {
 	EMPATHY_CONTACT_LIST_STORE_COL_CAN_AUDIO_CALL,
 	EMPATHY_CONTACT_LIST_STORE_COL_CAN_VIDEO_CALL,
 	EMPATHY_CONTACT_LIST_STORE_COL_FLAGS,
-	EMPATHY_CONTACT_LIST_STORE_COL_COUNT
+	EMPATHY_CONTACT_LIST_STORE_COL_IS_FAVOURITE,
+	EMPATHY_CONTACT_LIST_STORE_COL_COUNT,
 } EmpathyContactListStoreCol;
 
 struct _EmpathyContactListStore {
diff --git a/libempathy-gtk/empathy-contact-list-view.c b/libempathy-gtk/empathy-contact-list-view.c
index 705494e..c952bb8 100644
--- a/libempathy-gtk/empathy-contact-list-view.c
+++ b/libempathy-gtk/empathy-contact-list-view.c
@@ -817,6 +817,41 @@ contact_list_view_call_activated_cb (
 }
 
 static void
+contact_list_view_favourite_toggled_cb (
+    EmpathyCellRendererActivatable *cell,
+    const gchar                    *path_string,
+    EmpathyContactListView         *view)
+{
+	EmpathyContactListViewPriv *priv = GET_PRIV (view);
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	EmpathyContact *contact;
+        EmpathyContactList *list;
+
+	model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+	if (!gtk_tree_model_get_iter_from_string (model, &iter, path_string))
+		return;
+
+	gtk_tree_model_get (model, &iter,
+			    EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, &contact,
+			    -1);
+	if (contact == NULL)
+		return;
+
+        list = empathy_contact_list_store_get_list_iface (priv->store);
+
+        if (empathy_contact_list_contact_is_favourite (list, contact)) {
+                empathy_contact_list_remove_from_group (list, contact,
+                                EMPATHY_GROUP_FAVOURITES);
+        } else {
+                empathy_contact_list_add_to_group (list, contact,
+                                EMPATHY_GROUP_FAVOURITES);
+        }
+
+	g_object_unref (contact);
+}
+
+static void
 contact_list_view_cell_set_background (EmpathyContactListView *view,
 				       GtkCellRenderer       *cell,
 				       gboolean               is_group,
@@ -955,6 +990,11 @@ contact_list_view_text_cell_data_func (GtkTreeViewColumn     *tree_column,
 			    EMPATHY_CONTACT_LIST_STORE_COL_NAME, &name,
 			    -1);
 
+        if (is_group && !g_strcmp0 (name, EMPATHY_GROUP_FAVOURITES)) {
+                g_free (name);
+                name = g_strdup (_(EMPATHY_GROUP_FAVOURITES));
+        }
+
 	g_object_set (cell,
 		      "show-status", show_status,
 		      "text", name,
@@ -999,6 +1039,39 @@ contact_list_view_expander_cell_data_func (GtkTreeViewColumn     *column,
 }
 
 static void
+contact_list_view_favourite_cell_data_func (
+				       GtkTreeViewColumn      *tree_column,
+				       GtkCellRenderer        *cell,
+				       GtkTreeModel           *model,
+				       GtkTreeIter            *iter,
+				       EmpathyContactListView *view)
+{
+	gboolean is_group;
+	gboolean is_active;
+	gboolean is_separator;
+	gboolean is_favourite;
+	const gchar *icon_name = NULL;
+
+	gtk_tree_model_get (model, iter,
+			    EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP, &is_group,
+			    EMPATHY_CONTACT_LIST_STORE_COL_IS_ACTIVE, &is_active,
+			    EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, &is_separator,
+			    EMPATHY_CONTACT_LIST_STORE_COL_IS_FAVOURITE, &is_favourite,
+			    -1);
+
+        if (!is_separator && !is_group)
+                icon_name = (is_favourite? EMPATHY_IMAGE_FAVOURITE :
+                                EMPATHY_IMAGE_UNFAVOURITE);
+
+	g_object_set (cell,
+		      "visible", (icon_name != NULL),
+		      "icon-name", icon_name,
+		      NULL);
+
+	contact_list_view_cell_set_background (view, cell, is_group, is_active);
+}
+
+static void
 contact_list_view_row_expand_or_collapse_cb (EmpathyContactListView *view,
 					     GtkTreeIter           *iter,
 					     GtkTreePath           *path,
@@ -1101,6 +1174,22 @@ contact_list_view_setup (EmpathyContactListView *view)
 
 	col = gtk_tree_view_column_new ();
 
+	/* Favourite Icon */
+	cell = empathy_cell_renderer_activatable_new ();
+	gtk_tree_view_column_pack_start (col, cell, FALSE);
+	gtk_tree_view_column_set_cell_data_func (
+		col, cell,
+		(GtkTreeCellDataFunc) contact_list_view_favourite_cell_data_func,
+		view, NULL);
+
+	g_object_set (cell,
+		      "visible", FALSE,
+		      NULL);
+
+	g_signal_connect (cell, "path-activated",
+			  G_CALLBACK (contact_list_view_favourite_toggled_cb),
+			  view);
+
 	/* State */
 	cell = gtk_cell_renderer_pixbuf_new ();
 	gtk_tree_view_column_pack_start (col, cell, FALSE);
diff --git a/libempathy-gtk/empathy-images.h b/libempathy-gtk/empathy-images.h
index c714f04..623774e 100644
--- a/libempathy-gtk/empathy-images.h
+++ b/libempathy-gtk/empathy-images.h
@@ -41,6 +41,8 @@ G_BEGIN_DECLS
 #define EMPATHY_IMAGE_VIDEO_CALL          "camera-web"
 #define EMPATHY_IMAGE_LOG                 "document-open-recent"
 #define EMPATHY_IMAGE_DOCUMENT_SEND       "document-send"
+#define EMPATHY_IMAGE_FAVOURITE           "empathy-starred"
+#define EMPATHY_IMAGE_UNFAVOURITE         "empathy-unstarred"
 
 G_END_DECLS
 
diff --git a/libempathy/empathy-contact-list.c b/libempathy/empathy-contact-list.c
index d485921..65a1ede 100644
--- a/libempathy/empathy-contact-list.c
+++ b/libempathy/empathy-contact-list.c
@@ -249,3 +249,20 @@ empathy_contact_list_get_flags (EmpathyContactList *list)
 		return 0;
 	}
 }
+
+/* XXX: this should be an EmpathyContact function, but it would likely require
+ * some awkward refactoring */
+gboolean
+empathy_contact_list_contact_is_favourite (EmpathyContactList *list,
+                                           EmpathyContact     *contact)
+{
+        GList *groups, *l;
+
+        groups = empathy_contact_list_get_groups (list, contact);
+        for (l = groups; l; l = l->next)
+                if (!g_strcmp0 (l->data, EMPATHY_GROUP_FAVOURITES))
+                        return TRUE;
+
+        return FALSE;
+}
+
diff --git a/libempathy/empathy-contact-list.h b/libempathy/empathy-contact-list.h
index 28238e4..c3fff72 100644
--- a/libempathy/empathy-contact-list.h
+++ b/libempathy/empathy-contact-list.h
@@ -34,6 +34,9 @@ G_BEGIN_DECLS
 #define EMPATHY_IS_CONTACT_LIST(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_CONTACT_LIST))
 #define EMPATHY_CONTACT_LIST_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), EMPATHY_TYPE_CONTACT_LIST, EmpathyContactListIface))
 
+/* The favourites are just in a specially-handled group */
+#define EMPATHY_GROUP_FAVOURITES "Favorites"
+
 typedef enum {
 	EMPATHY_CONTACT_LIST_CAN_ADD		= 1 << 0,
 	EMPATHY_CONTACT_LIST_CAN_REMOVE		= 1 << 1,
@@ -104,6 +107,10 @@ EmpathyContactMonitor *
 EmpathyContactListFlags
          empathy_contact_list_get_flags		(EmpathyContactList *list);
 
+gboolean empathy_contact_list_contact_is_favourite
+                                        (EmpathyContactList *list,
+                                         EmpathyContact     *contact);
+
 G_END_DECLS
 
 #endif /* __EMPATHY_CONTACT_LIST_H__ */



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