#include <gtk/gtk.h>
#include <glade/glade.h>
-#include <libtelepathy/tp-helpers.h>
-
#include <libmissioncontrol/mc-account.h>
#include <libmissioncontrol/mission-control.h>
+#include <libempathy/empathy-contact-list.h>
#include <libempathy/empathy-contact-manager.h>
#include <libempathy/gossip-debug.h>
+#include <libempathy/gossip-utils.h>
#include "empathy-images.h"
#include "gossip-contact-list.h"
#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CONTACT_LIST, GossipContactListPriv))
struct _GossipContactListPriv {
- EmpathyContactManager *manager;
+ EmpathyContactList *list;
GHashTable *groups;
gboolean show_avatars;
gboolean is_compact;
gboolean show_active;
+
+ GossipContactListSort sort_criterium;
};
typedef struct {
gpointer data);
static void contact_list_contact_update (GossipContactList *list,
GossipContact *contact);
-static void contact_list_contact_added_cb (EmpathyContactManager *manager,
+static void contact_list_contact_added_cb (EmpathyContactList *list_iface,
GossipContact *contact,
GossipContactList *list);
static void contact_list_contact_updated_cb (GossipContact *contact,
static void contact_list_contact_groups_updated_cb (GossipContact *contact,
GParamSpec *param,
GossipContactList *list);
-static void contact_list_contact_removed_cb (EmpathyContactManager *manager,
+static void contact_list_contact_removed_cb (EmpathyContactList *list_iface,
GossipContact *contact,
GossipContactList *list);
static void contact_list_contact_set_active (GossipContactList *list,
GtkTreeIter *iter,
GtkTreePath *path,
gpointer user_data);
-static gint contact_list_sort_func (GtkTreeModel *model,
+static gint contact_list_name_sort_func (GtkTreeModel *model,
+ GtkTreeIter *iter_a,
+ GtkTreeIter *iter_b,
+ gpointer user_data);
+static gint contact_list_state_sort_func (GtkTreeModel *model,
GtkTreeIter *iter_a,
GtkTreeIter *iter_b,
gpointer user_data);
PROP_SHOW_OFFLINE,
PROP_SHOW_AVATARS,
PROP_IS_COMPACT,
- PROP_FILTER
+ PROP_FILTER,
+ PROP_SORT_CRITERIUM
};
static const GtkActionEntry entries[] = {
static GdkAtom drag_atoms_dest[G_N_ELEMENTS (drag_types_dest)];
static GdkAtom drag_atoms_source[G_N_ELEMENTS (drag_types_source)];
+GType
+gossip_contact_list_sort_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ { GOSSIP_CONTACT_LIST_SORT_NAME,
+ "GOSSIP_CONTACT_LIST_SORT_NAME",
+ "name" },
+ { GOSSIP_CONTACT_LIST_SORT_STATE,
+ "GOSSIP_CONTACT_LIST_SORT_STATE",
+ "state" },
+ { 0, NULL, NULL }
+ };
+
+ etype = g_enum_register_static ("GossipContactListSort", values);
+ }
+
+ return etype;
+}
+
G_DEFINE_TYPE (GossipContactList, gossip_contact_list, GTK_TYPE_TREE_VIEW);
static void
NULL,
G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_SORT_CRITERIUM,
+ g_param_spec_enum ("sort-criterium",
+ "Sort citerium",
+ "The sort criterium to use for sorting the contact list",
+ GOSSIP_TYPE_CONTACT_LIST_SORT,
+ GOSSIP_CONTACT_LIST_SORT_NAME,
+ G_PARAM_READWRITE));
+
g_type_class_add_private (object_class, sizeof (GossipContactListPriv));
}
priv = GET_PRIV (list);
- priv->manager = empathy_contact_manager_new ();
+ priv->list = EMPATHY_CONTACT_LIST (empathy_contact_manager_new ());
priv->is_compact = FALSE;
priv->show_active = TRUE;
priv->show_avatars = TRUE;
contact_list_create_model (list);
contact_list_setup_view (list);
- empathy_contact_manager_setup (priv->manager);
+ empathy_contact_list_setup (priv->list);
/* Get saved group states. */
gossip_contact_groups_get_all ();
NULL, NULL);
/* Signal connection. */
- g_signal_connect (priv->manager,
+ g_signal_connect (priv->list,
"contact-added",
G_CALLBACK (contact_list_contact_added_cb),
list);
- g_signal_connect (priv->manager,
+ g_signal_connect (priv->list,
"contact-removed",
G_CALLBACK (contact_list_contact_removed_cb),
list);
GINT_TO_POINTER (FALSE));
/* Add contacts already created */
- contacts = empathy_contact_manager_get_contacts (priv->manager);
+ contacts = empathy_contact_list_get_contacts (priv->list);
for (l = contacts; l; l = l->next) {
GossipContact *contact;
contact = l->data;
- contact_list_contact_added_cb (priv->manager, contact, list);
+ contact_list_contact_added_cb (priv->list, contact, list);
g_object_unref (contact);
}
priv = GET_PRIV (object);
- /* FIXME: disconnect all signals on the manager and contacts */
+ /* FIXME: disconnect all signals on the list and contacts */
- g_object_unref (priv->manager);
+ g_object_unref (priv->list);
g_object_unref (priv->ui);
g_object_unref (priv->store);
g_object_unref (priv->filter);
case PROP_FILTER:
g_value_set_string (value, priv->filter_text);
break;
+ case PROP_SORT_CRITERIUM:
+ g_value_set_enum (value, priv->sort_criterium);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
gossip_contact_list_set_filter (GOSSIP_CONTACT_LIST (object),
g_value_get_string (value));
break;
+ case PROP_SORT_CRITERIUM:
+ gossip_contact_list_set_sort_criterium (GOSSIP_CONTACT_LIST (object),
+ g_value_get_enum (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
}
static void
-contact_list_contact_added_cb (EmpathyContactManager *manager,
- GossipContact *contact,
- GossipContactList *list)
+contact_list_contact_added_cb (EmpathyContactList *list_iface,
+ GossipContact *contact,
+ GossipContactList *list)
{
GossipContactListPriv *priv;
}
static void
-contact_list_contact_removed_cb (EmpathyContactManager *manager,
- GossipContact *contact,
- GossipContactList *list)
+contact_list_contact_removed_cb (EmpathyContactList *list_iface,
+ GossipContact *contact,
+ GossipContactList *list)
{
gossip_debug (DEBUG_DOMAIN, "Contact:'%s' removed",
gossip_contact_get_name (contact));
/* Set up sorting */
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
COL_NAME,
- contact_list_sort_func,
+ contact_list_name_sort_func,
+ list, NULL);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
+ COL_STATUS,
+ contact_list_state_sort_func,
list, NULL);
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
- COL_NAME,
- GTK_SORT_ASCENDING);
+ gossip_contact_list_set_sort_criterium (list, priv->sort_criterium);
/* Create filter */
priv->filter = gtk_tree_model_filter_new (model, NULL);
id);
/* FIXME: This is ambigous, an id can come from multiple accounts */
- contact = empathy_contact_manager_find (priv->manager, id);
+ contact = empathy_contact_list_find (priv->list, id);
if (!contact) {
gossip_debug (DEBUG_DOMAIN, "No contact found associated with drag & drop");
return;
}
static gint
-contact_list_sort_func (GtkTreeModel *model,
- GtkTreeIter *iter_a,
- GtkTreeIter *iter_b,
- gpointer user_data)
+contact_list_state_sort_func (GtkTreeModel *model,
+ GtkTreeIter *iter_a,
+ GtkTreeIter *iter_b,
+ gpointer user_data)
+{
+ gint ret_val = 0;
+ gchar *name_a, *name_b;
+ gboolean is_separator_a, is_separator_b;
+ GossipContact *contact_a, *contact_b;
+ GossipPresence *presence_a, *presence_b;
+ McPresence state_a, state_b;
+
+ gtk_tree_model_get (model, iter_a,
+ COL_NAME, &name_a,
+ COL_CONTACT, &contact_a,
+ COL_IS_SEPARATOR, &is_separator_a,
+ -1);
+ gtk_tree_model_get (model, iter_b,
+ COL_NAME, &name_b,
+ COL_CONTACT, &contact_b,
+ COL_IS_SEPARATOR, &is_separator_b,
+ -1);
+
+ /* Separator or group? */
+ if (is_separator_a || is_separator_b) {
+ if (is_separator_a) {
+ ret_val = -1;
+ } else if (is_separator_b) {
+ ret_val = 1;
+ }
+ } else if (!contact_a && contact_b) {
+ ret_val = 1;
+ } else if (contact_a && !contact_b) {
+ ret_val = -1;
+ } else if (!contact_a && !contact_b) {
+ /* Handle groups */
+ ret_val = g_utf8_collate (name_a, name_b);
+ }
+
+ if (ret_val) {
+ goto free_and_out;
+ }
+
+ /* If we managed to get this far, we can start looking at
+ * the presences.
+ */
+ presence_a = gossip_contact_get_presence (GOSSIP_CONTACT (contact_a));
+ presence_b = gossip_contact_get_presence (GOSSIP_CONTACT (contact_b));
+
+ if (!presence_a && presence_b) {
+ ret_val = 1;
+ } else if (presence_a && !presence_b) {
+ ret_val = -1;
+ } else if (!presence_a && !presence_b) {
+ /* Both offline, sort by name */
+ ret_val = g_utf8_collate (name_a, name_b);
+ } else {
+ state_a = gossip_presence_get_state (presence_a);
+ state_b = gossip_presence_get_state (presence_b);
+
+ if (state_a < state_b) {
+ ret_val = -1;
+ } else if (state_a > state_b) {
+ ret_val = 1;
+ } else {
+ /* Fallback: compare by name */
+ ret_val = g_utf8_collate (name_a, name_b);
+ }
+ }
+
+free_and_out:
+ g_free (name_a);
+ g_free (name_b);
+
+ if (contact_a) {
+ g_object_unref (contact_a);
+ }
+
+ if (contact_b) {
+ g_object_unref (contact_b);
+ }
+
+ return ret_val;
+}
+
+static gint
+contact_list_name_sort_func (GtkTreeModel *model,
+ GtkTreeIter *iter_a,
+ GtkTreeIter *iter_b,
+ gpointer user_data)
{
gchar *name_a, *name_b;
GossipContact *contact_a, *contact_b;
* group should be shown because a contact we want to
* show exists in it.
*/
- contacts = empathy_contact_manager_get_contacts (priv->manager);
+ contacts = empathy_contact_list_get_contacts (priv->list);
for (l = contacts; l && !show_group; l = l->next) {
if (!gossip_contact_is_in_group (l->data, group)) {
continue;
{
MissionControl *mc;
- mc = mission_control_new (tp_get_bus ());
+ mc = gossip_mission_control_new ();
mission_control_request_channel (mc,
gossip_contact_get_account (contact),
TP_IFACE_CHANNEL_TYPE_TEXT,
return priv->is_compact;
}
+GossipContactListSort
+gossip_contact_list_get_sort_criterium (GossipContactList *list)
+{
+ GossipContactListPriv *priv;
+
+ g_return_val_if_fail (GOSSIP_IS_CONTACT_LIST (list), 0);
+
+ priv = GET_PRIV (list);
+
+ return priv->sort_criterium;
+}
+
void
gossip_contact_list_set_show_offline (GossipContactList *list,
gboolean show_offline)
/* Disable temporarily. */
priv->show_active = FALSE;
- contacts = empathy_contact_manager_get_contacts (priv->manager);
+ contacts = empathy_contact_list_get_contacts (priv->list);
for (l = contacts; l; l = l->next) {
GossipContact *contact;
list);
}
+void
+gossip_contact_list_set_sort_criterium (GossipContactList *list,
+ GossipContactListSort sort_criterium)
+{
+ GossipContactListPriv *priv;
+
+ g_return_if_fail (GOSSIP_IS_CONTACT_LIST (list));
+
+ priv = GET_PRIV (list);
+
+ priv->sort_criterium = sort_criterium;
+
+ switch (sort_criterium) {
+ case GOSSIP_CONTACT_LIST_SORT_STATE:
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->store),
+ COL_STATUS,
+ GTK_SORT_ASCENDING);
+ break;
+
+ case GOSSIP_CONTACT_LIST_SORT_NAME:
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->store),
+ COL_NAME,
+ GTK_SORT_ASCENDING);
+ break;
+ }
+}
+
void
gossip_contact_list_set_filter (GossipContactList *list,
const gchar *filter)