X-Git-Url: https://git.0d.be/?p=empathy.git;a=blobdiff_plain;f=libempathy-gtk%2Fempathy-roster-view.c;h=e463bd9f0ac539f53a2437b1c1e1112902f4213a;hp=d9b3c7bf284dccc984cf8c33c14ceaab9de85cf2;hb=ac5be92f345b767b423f70befdb9bfbb199474b4;hpb=5c440c4e08f8102a9b73244697e69ad4855dbdef diff --git a/libempathy-gtk/empathy-roster-view.c b/libempathy-gtk/empathy-roster-view.c index d9b3c7bf..e463bd9f 100644 --- a/libempathy-gtk/empathy-roster-view.c +++ b/libempathy-gtk/empathy-roster-view.c @@ -1,16 +1,14 @@ #include "config.h" - #include "empathy-roster-view.h" #include -#include "libempathy/empathy-contact-groups.h" - +#include "empathy-contact-groups.h" #include "empathy-roster-contact.h" #include "empathy-roster-group.h" #include "empathy-ui-utils.h" -G_DEFINE_TYPE (EmpathyRosterView, empathy_roster_view, EGG_TYPE_LIST_BOX) +G_DEFINE_TYPE (EmpathyRosterView, empathy_roster_view, GTK_TYPE_LIST_BOX) /* Flashing delay for icons (milliseconds). */ #define FLASH_TIMEOUT 500 @@ -69,11 +67,16 @@ struct _EmpathyRosterViewPriv gboolean show_groups; gboolean empty; - EmpathyLiveSearch *search; + TpawLiveSearch *search; EmpathyRosterModel *model; }; +/* Prototypes to break cycles */ +static void remove_from_group (EmpathyRosterView *self, + FolksIndividual *individual, + const gchar *group); + typedef struct { guint id; @@ -162,11 +165,11 @@ empathy_roster_view_set_property (GObject *object, } static void -roster_contact_changed_cb (GtkWidget *child, +roster_contact_changed_cb (GtkListBoxRow *child, GParamSpec *spec, EmpathyRosterView *self) { - egg_list_box_child_changed (EGG_LIST_BOX (self), child); + gtk_list_box_row_changed (child); } static GtkWidget * @@ -186,6 +189,10 @@ add_roster_contact (EmpathyRosterView *self, g_signal_connect (contact, "notify::alias", G_CALLBACK (roster_contact_changed_cb), self); + /* Need to resort if most recent event changed */ + g_signal_connect (contact, "notify::most-recent-event", + G_CALLBACK (roster_contact_changed_cb), self); + gtk_widget_show (contact); gtk_container_add (GTK_CONTAINER (self), contact); @@ -193,22 +200,22 @@ add_roster_contact (EmpathyRosterView *self, } static void -group_expanded_cb (EmpathyRosterGroup *group, +group_expanded_cb (GtkWidget *expander, GParamSpec *spec, - EmpathyRosterView *self) + EmpathyRosterGroup *group) { GList *widgets, *l; widgets = empathy_roster_group_get_widgets (group); for (l = widgets; l != NULL; l = g_list_next (l)) { - egg_list_box_child_changed (EGG_LIST_BOX (self), l->data); + gtk_list_box_row_changed (l->data); } g_list_free (widgets); empathy_contact_group_set_expanded (empathy_roster_group_get_name (group), - gtk_expander_get_expanded (GTK_EXPANDER (group))); + gtk_expander_get_expanded (group->expander)); } static EmpathyRosterGroup * @@ -235,11 +242,11 @@ ensure_roster_group (EmpathyRosterView *self, else roster_group = empathy_roster_group_new (group, NULL); - gtk_expander_set_expanded (GTK_EXPANDER (roster_group), + gtk_expander_set_expanded (EMPATHY_ROSTER_GROUP (roster_group)->expander, empathy_contact_group_get_expanded (group)); - g_signal_connect (roster_group, "notify::expanded", - G_CALLBACK (group_expanded_cb), self); + g_signal_connect (EMPATHY_ROSTER_GROUP (roster_group)->expander, + "notify::expanded", G_CALLBACK (group_expanded_cb), roster_group); gtk_widget_show (roster_group); gtk_container_add (GTK_CONTAINER (self), roster_group); @@ -314,7 +321,7 @@ update_group_widgets (EmpathyRosterView *self, if (count != old_count) { - egg_list_box_child_changed (EGG_LIST_BOX (self), GTK_WIDGET (group)); + gtk_list_box_row_changed (GTK_LIST_BOX_ROW (group)); check_if_empty (self); } @@ -347,6 +354,14 @@ add_to_group (EmpathyRosterView *self, update_group_widgets (self, roster_group, EMPATHY_ROSTER_CONTACT (contact), TRUE); } + + if (tp_strdiff (group, NO_GROUP) && + tp_strdiff (group, EMPATHY_ROSTER_MODEL_GROUP_UNGROUPED) && + g_hash_table_size (contacts) == 2 /* 1:Ungrouped and 2:first group */) + { + remove_from_group (self, individual, + EMPATHY_ROSTER_MODEL_GROUP_UNGROUPED); + } } static void @@ -372,7 +387,7 @@ individual_favourite_change_cb (FolksIndividual *individual, if (contact == NULL) return; - egg_list_box_child_changed (EGG_LIST_BOX (self), contact); + gtk_list_box_row_changed (GTK_LIST_BOX_ROW (contact)); } static void @@ -614,6 +629,20 @@ contact_in_top (EmpathyRosterView *self, return FALSE; } +static gint +compare_roster_contacts_by_conversation_time (EmpathyRosterContact *a, + EmpathyRosterContact *b) +{ + gint64 ts_a, ts_b; + + ts_a = empathy_roster_contact_get_most_recent_timestamp (a); + ts_b = empathy_roster_contact_get_most_recent_timestamp (b); + + if (ts_a == ts_b) return 0; + if (ts_a > ts_b) return -1; + return 1; +} + static gint compare_roster_contacts_by_alias (EmpathyRosterContact *a, EmpathyRosterContact *b) @@ -627,7 +656,7 @@ compare_roster_contacts_by_alias (EmpathyRosterContact *a, alias_a = folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (ind_a)); alias_b = folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (ind_b)); - return g_ascii_strcasecmp (alias_a, alias_b); + return g_utf8_collate (alias_a, alias_b); } static gint @@ -643,7 +672,7 @@ compare_roster_contacts_no_group (EmpathyRosterView *self, if (top_a == top_b) /* Both contacts are in the top of the roster (or not). Sort them * alphabetically */ - return compare_roster_contacts_by_alias (a, b); + return compare_roster_contacts_by_conversation_time (a, b); else if (top_a) return -1; else @@ -665,7 +694,7 @@ compare_group_names (const gchar *group_a, else if (!tp_strdiff (group_b, EMPATHY_ROSTER_MODEL_GROUP_UNGROUPED)) return -1; - return g_ascii_strcasecmp (group_a, group_b); + return g_utf8_collate (group_a, group_b); } static gint @@ -680,7 +709,7 @@ compare_roster_contacts_with_groups (EmpathyRosterView *self, if (!tp_strdiff (group_a, group_b)) /* Same group, compare the contacts */ - return compare_roster_contacts_by_alias (a, b); + return compare_roster_contacts_by_conversation_time (a, b); /* Sort by group */ return compare_group_names (group_a, group_b); @@ -727,8 +756,8 @@ compare_contact_group (EmpathyRosterContact *contact, } static gint -roster_view_sort (gconstpointer a, - gconstpointer b, +roster_view_sort (GtkListBoxRow *a, + GtkListBoxRow *b, gpointer user_data) { EmpathyRosterView *self = user_data; @@ -750,23 +779,22 @@ roster_view_sort (gconstpointer a, } static void -update_separator (GtkWidget **separator, - GtkWidget *child, - GtkWidget *before, +update_header (GtkListBoxRow *row, + GtkListBoxRow *before, gpointer user_data) { if (before == NULL) { /* No separator before the first row */ - g_clear_object (separator); + gtk_list_box_row_set_header (row, NULL); return; } - if (*separator != NULL) + if (gtk_list_box_row_get_header (row) != NULL) return; - *separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); - g_object_ref_sink (*separator); + gtk_list_box_row_set_header (row, + gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)); } static gboolean @@ -808,13 +836,13 @@ add_to_displayed (EmpathyRosterView *self, while (g_hash_table_iter_next (&iter, &k, NULL)) { const gchar *group_name = k; - GtkWidget *group; + GtkListBoxRow *group; group = g_hash_table_lookup (self->priv->roster_groups, group_name); if (group == NULL) continue; - egg_list_box_child_changed (EGG_LIST_BOX (self), group); + gtk_list_box_row_changed (group); } } @@ -853,8 +881,8 @@ contact_should_be_displayed (EmpathyRosterView *self, individual = empathy_roster_contact_get_individual (contact); return empathy_individual_match_string (individual, - empathy_live_search_get_text (self->priv->search), - empathy_live_search_get_words (self->priv->search)); + tpaw_live_search_get_text (self->priv->search), + tpaw_live_search_get_words (self->priv->search)); } if (self->priv->show_offline) @@ -889,7 +917,7 @@ filter_contact (EmpathyRosterView *self, { /* When searching, always display even if the group is closed */ if (!is_searching (self) && - !gtk_expander_get_expanded (GTK_EXPANDER (group))) + !gtk_expander_get_expanded (group->expander)) displayed = FALSE; } } @@ -932,7 +960,7 @@ filter_group (EmpathyRosterView *self, } static gboolean -filter_list (GtkWidget *child, +filter_list (GtkListBoxRow *child, gpointer user_data) { EmpathyRosterView *self = user_data; @@ -1006,7 +1034,7 @@ groups_changed_cb (EmpathyRosterModel *model, { if (!self->priv->show_groups) { - egg_list_box_resort (EGG_LIST_BOX (self)); + gtk_list_box_invalidate_sort (GTK_LIST_BOX (self)); return; } @@ -1044,15 +1072,14 @@ empathy_roster_view_constructed (GObject *object) tp_g_signal_connect_object (self->priv->model, "groups-changed", G_CALLBACK (groups_changed_cb), self, 0); - egg_list_box_set_sort_func (EGG_LIST_BOX (self), + gtk_list_box_set_sort_func (GTK_LIST_BOX (self), roster_view_sort, self, NULL); - egg_list_box_set_separator_funcs (EGG_LIST_BOX (self), update_separator, - self, NULL); + gtk_list_box_set_header_func (GTK_LIST_BOX (self), update_header, self, NULL); - egg_list_box_set_filter_func (EGG_LIST_BOX (self), filter_list, self, NULL); + gtk_list_box_set_filter_func (GTK_LIST_BOX (self), filter_list, self, NULL); - egg_list_box_set_activate_on_single_click (EGG_LIST_BOX (self), FALSE); + gtk_list_box_set_activate_on_single_click (GTK_LIST_BOX (self), FALSE); } static void @@ -1109,18 +1136,18 @@ empathy_roster_view_finalize (GObject *object) } static void -empathy_roster_view_child_activated (EggListBox *box, - GtkWidget *child) +empathy_roster_view_row_activated (GtkListBox *box, + GtkListBoxRow *row) { EmpathyRosterView *self = EMPATHY_ROSTER_VIEW (box); EmpathyRosterContact *contact; FolksIndividual *individual; GList *l; - if (!EMPATHY_IS_ROSTER_CONTACT (child)) + if (!EMPATHY_IS_ROSTER_CONTACT (row)) return; - contact = EMPATHY_ROSTER_CONTACT (child); + contact = EMPATHY_ROSTER_CONTACT (row); individual = empathy_roster_contact_get_individual (contact); /* Activate the oldest event associated with this contact, if any */ @@ -1142,21 +1169,23 @@ empathy_roster_view_child_activated (EggListBox *box, static void fire_popup_individual_menu (EmpathyRosterView *self, - GtkWidget *child, + GtkListBoxRow *row, guint button, guint time) { EmpathyRosterContact *contact; FolksIndividual *individual; + const gchar *active_group; - if (!EMPATHY_IS_ROSTER_CONTACT (child)) + if (!EMPATHY_IS_ROSTER_CONTACT (row)) return; - contact = EMPATHY_ROSTER_CONTACT (child); + contact = EMPATHY_ROSTER_CONTACT (row); individual = empathy_roster_contact_get_individual (contact); + active_group = empathy_roster_contact_get_group (contact); g_signal_emit (self, signals[SIG_POPUP_INDIVIDUAL_MENU], 0, - individual, button, time); + active_group, individual, button, time); } static gboolean @@ -1169,15 +1198,15 @@ empathy_roster_view_button_press_event (GtkWidget *widget, if (event->button == 3) { - GtkWidget *child; + GtkListBoxRow *row; - child = egg_list_box_get_child_at_y (EGG_LIST_BOX (self), event->y); + row = gtk_list_box_get_row_at_y (GTK_LIST_BOX (self), event->y); - if (child != NULL) + if (row != NULL) { - egg_list_box_select_child (EGG_LIST_BOX (self), child); + gtk_list_box_select_row (GTK_LIST_BOX (self), row); - fire_popup_individual_menu (self, child, event->button, event->time); + fire_popup_individual_menu (self, row, event->button, event->time); } } @@ -1194,53 +1223,50 @@ empathy_roster_view_key_press_event (GtkWidget *widget, if (event->keyval == GDK_KEY_Menu) { - GtkWidget *child; + GtkListBoxRow *row; - child = egg_list_box_get_selected_child (EGG_LIST_BOX (self)); + row = gtk_list_box_get_selected_row (GTK_LIST_BOX (self)); - if (child != NULL) - fire_popup_individual_menu (self, child, 0, event->time); + if (row != NULL) + fire_popup_individual_menu (self, row, 0, event->time); } return chain_up (widget, event); } /** - * @out_child: (out) (allow-none) + * @out_row: (out) (allow-none) */ FolksIndividual * empathy_roster_view_get_individual_at_y (EmpathyRosterView *self, gint y, - GtkWidget **out_child) + GtkListBoxRow **out_row) { - GtkWidget *child; + GtkListBoxRow *row; - child = egg_list_box_get_child_at_y (EGG_LIST_BOX (self), y); + row = gtk_list_box_get_row_at_y (GTK_LIST_BOX (self), y); - if (out_child != NULL) - *out_child = child; + if (out_row != NULL) + *out_row = row; - if (!EMPATHY_IS_ROSTER_CONTACT (child)) + if (!EMPATHY_IS_ROSTER_CONTACT (row)) return NULL; - return empathy_roster_contact_get_individual (EMPATHY_ROSTER_CONTACT (child)); + return empathy_roster_contact_get_individual (EMPATHY_ROSTER_CONTACT (row)); } -/** - * @out_child: (out) (allow-none) - */ const gchar * empathy_roster_view_get_group_at_y (EmpathyRosterView *self, gint y) { - GtkWidget *child; + GtkListBoxRow *row; - child = egg_list_box_get_child_at_y (EGG_LIST_BOX (self), y); + row = gtk_list_box_get_row_at_y (GTK_LIST_BOX (self), y); - if (EMPATHY_IS_ROSTER_CONTACT (child)) - return empathy_roster_contact_get_group (EMPATHY_ROSTER_CONTACT (child)); - else if (EMPATHY_IS_ROSTER_GROUP (child)) - return empathy_roster_group_get_name (EMPATHY_ROSTER_GROUP (child)); + if (EMPATHY_IS_ROSTER_CONTACT (row)) + return empathy_roster_contact_get_group (EMPATHY_ROSTER_CONTACT (row)); + else if (EMPATHY_IS_ROSTER_GROUP (row)) + return empathy_roster_group_get_name (EMPATHY_ROSTER_GROUP (row)); return NULL; } @@ -1255,9 +1281,9 @@ empathy_roster_view_query_tooltip (GtkWidget *widget, EmpathyRosterView *self = EMPATHY_ROSTER_VIEW (widget); FolksIndividual *individual; gboolean result; - GtkWidget *child; + GtkListBoxRow *row; - individual = empathy_roster_view_get_individual_at_y (self, y, &child); + individual = empathy_roster_view_get_individual_at_y (self, y, &row); if (individual == NULL) return FALSE; @@ -1268,7 +1294,7 @@ empathy_roster_view_query_tooltip (GtkWidget *widget, { GtkAllocation allocation; - gtk_widget_get_allocation (child, &allocation); + gtk_widget_get_allocation (GTK_WIDGET (row), &allocation); gtk_tooltip_set_tip_area (tooltip, (GdkRectangle *) &allocation); } @@ -1294,7 +1320,7 @@ empathy_roster_view_class_init ( EmpathyRosterViewClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); - EggListBoxClass *box_class = EGG_LIST_BOX_CLASS (klass); + GtkListBoxClass *box_class = GTK_LIST_BOX_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); GParamSpec *spec; @@ -1311,7 +1337,7 @@ empathy_roster_view_class_init ( container_class->remove = empathy_roster_view_remove; - box_class->child_activated = empathy_roster_view_child_activated; + box_class->row_activated = empathy_roster_view_row_activated; spec = g_param_spec_object ("model", "Model", "EmpathyRosterModel", @@ -1349,7 +1375,8 @@ empathy_roster_view_class_init ( G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, - 3, FOLKS_TYPE_INDIVIDUAL, G_TYPE_UINT, G_TYPE_UINT); + 4, G_TYPE_STRING, FOLKS_TYPE_INDIVIDUAL, G_TYPE_UINT, + G_TYPE_UINT); signals[SIG_EVENT_ACTIVATED] = g_signal_new ("event-activated", G_OBJECT_CLASS_TYPE (klass), @@ -1403,7 +1430,7 @@ empathy_roster_view_show_offline (EmpathyRosterView *self, return; self->priv->show_offline = show; - egg_list_box_refilter (EGG_LIST_BOX (self)); + gtk_list_box_invalidate_filter (GTK_LIST_BOX (self)); g_object_notify (G_OBJECT (self), "show-offline"); } @@ -1440,7 +1467,7 @@ select_first_contact (EmpathyRosterView *self) if (!EMPATHY_IS_ROSTER_CONTACT (child)) continue; - egg_list_box_select_child (EGG_LIST_BOX (self), child); + gtk_list_box_select_row (GTK_LIST_BOX (self), GTK_LIST_BOX_ROW (child)); break; } @@ -1450,7 +1477,7 @@ select_first_contact (EmpathyRosterView *self) static gboolean search_timeout_cb (EmpathyRosterView *self) { - egg_list_box_refilter (EGG_LIST_BOX (self)); + gtk_list_box_invalidate_filter (GTK_LIST_BOX (self)); select_first_contact (self); @@ -1459,7 +1486,7 @@ search_timeout_cb (EmpathyRosterView *self) } static void -search_text_notify_cb (EmpathyLiveSearch *search, +search_text_notify_cb (TpawLiveSearch *search, GParamSpec *pspec, EmpathyRosterView *self) { @@ -1474,19 +1501,19 @@ static void search_activate_cb (GtkWidget *search, EmpathyRosterView *self) { - EggListBox *box = EGG_LIST_BOX (self); - GtkWidget *child; + GtkListBox *box = GTK_LIST_BOX (self); + GtkListBoxRow *row; - child = egg_list_box_get_selected_child (box); - if (child == NULL) + row = gtk_list_box_get_selected_row (box); + if (row == NULL) return; - empathy_roster_view_child_activated (box, child); + empathy_roster_view_row_activated (box, row); } void empathy_roster_view_set_live_search (EmpathyRosterView *self, - EmpathyLiveSearch *search) + TpawLiveSearch *search) { if (self->priv->search != NULL) { @@ -1568,12 +1595,12 @@ empathy_roster_view_remove_event (EmpathyRosterView *self, FolksIndividual * empathy_roster_view_get_selected_individual (EmpathyRosterView *self) { - GtkWidget *child; + GtkListBoxRow *row; - child = egg_list_box_get_selected_child (EGG_LIST_BOX (self)); + row = gtk_list_box_get_selected_row (GTK_LIST_BOX (self)); - if (!EMPATHY_IS_ROSTER_CONTACT (child)) + if (!EMPATHY_IS_ROSTER_CONTACT (row)) return NULL; - return empathy_roster_contact_get_individual (EMPATHY_ROSTER_CONTACT (child)); + return empathy_roster_contact_get_individual (EMPATHY_ROSTER_CONTACT (row)); }