/** * cinnamon_contact_system_get_email_for_display: * @self: A #CinnamonContactSystem * @individual A #FolksIndividual * * Get an email address (either from IM addresses or email), which can be * used to represent @individual. * * Return: (transfer full): a newly allocated string or %NULL if no address * was found */ char * cinnamon_contact_system_get_email_for_display (CinnamonContactSystem *self, FolksIndividual *individual) { GeeMultiMap *im_addr_map = folks_im_details_get_im_addresses (FOLKS_IM_DETAILS (individual)); GeeCollection *im_addrs = gee_multi_map_get_values (im_addr_map); GeeSet *email_addrs = folks_email_details_get_email_addresses (FOLKS_EMAIL_DETAILS (individual)); GeeIterator *addrs_iter; char *email = NULL; addrs_iter = gee_iterable_iterator (GEE_ITERABLE (im_addrs)); if (gee_iterator_first (addrs_iter)) { FolksImFieldDetails *field = gee_iterator_get (addrs_iter); email = g_strdup (folks_abstract_field_details_get_value ((FolksAbstractFieldDetails*)field)); g_object_unref (field); } g_object_unref (addrs_iter); g_object_unref (im_addrs); if (email != NULL) return email; addrs_iter = gee_iterable_iterator (GEE_ITERABLE (email_addrs)); if (gee_iterator_first (addrs_iter)) { FolksEmailFieldDetails *field = gee_iterator_get (addrs_iter); email = g_strdup (folks_abstract_field_details_get_value ((FolksAbstractFieldDetails*)field)); g_object_unref (field); } g_object_unref (addrs_iter); return email; }
static guint do_match (CinnamonContactSystem *self, FolksIndividual *individual, GSList *terms) { GSList *term_iter; guint weight = 0; char *alias = cinnamon_util_normalize_and_casefold (folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual))); char *name = cinnamon_util_normalize_and_casefold (folks_name_details_get_full_name (FOLKS_NAME_DETAILS (individual))); char *nick = cinnamon_util_normalize_and_casefold (folks_name_details_get_nickname (FOLKS_NAME_DETAILS (individual))); GeeMultiMap *im_addr_map = folks_im_details_get_im_addresses (FOLKS_IM_DETAILS (individual)); GeeCollection *im_addrs = gee_multi_map_get_values (im_addr_map); GeeSet *email_addrs = folks_email_details_get_email_addresses (FOLKS_EMAIL_DETAILS (individual)); GeeIterator *addrs_iter; gboolean have_name_prefix = FALSE; gboolean have_name_substring = FALSE; gboolean have_addr_prefix = FALSE; gboolean have_addr_substring = FALSE; for (term_iter = terms; term_iter; term_iter = term_iter->next) { const char *term = term_iter->data; const char *p; gboolean matched; matched = FALSE; /* Match on alias, name, nickname */ if (alias != NULL) { p = strstr (alias, term); if (p == alias) { have_name_prefix = TRUE; matched = TRUE; } else if (p != NULL) { have_name_substring = TRUE; matched = TRUE; } } if (name != NULL) { p = strstr (name, term); if (p == name) { have_name_prefix = TRUE; matched = TRUE; } else if (p != NULL) { have_name_substring = TRUE; matched = TRUE; } } if (nick != NULL) { p = strstr (nick, term); if (p == nick) { have_name_prefix = TRUE; matched = TRUE; } else if (p != NULL) { have_name_substring = TRUE; matched = TRUE; } } /* Match on one or more IM or email addresses */ addrs_iter = gee_iterable_iterator (GEE_ITERABLE (im_addrs)); while (gee_iterator_next (addrs_iter)) { FolksImFieldDetails *field = gee_iterator_get (addrs_iter); const gchar *addr = folks_abstract_field_details_get_value ((FolksAbstractFieldDetails*)field); p = strstr (addr, term); if (p == addr) { have_addr_prefix = TRUE; matched = TRUE; } else if (p != NULL) { have_addr_substring = TRUE; matched = TRUE; } g_object_unref (field); } g_object_unref (addrs_iter); addrs_iter = gee_iterable_iterator (GEE_ITERABLE (email_addrs)); while (gee_iterator_next (addrs_iter)) { FolksEmailFieldDetails *field = gee_iterator_get (addrs_iter); const gchar *addr = folks_abstract_field_details_get_value ((FolksAbstractFieldDetails*)field); p = strstr (addr, term); if (p == addr) { have_addr_prefix = TRUE; matched = TRUE; } else if (p != NULL) { have_addr_substring = TRUE; matched = TRUE; } g_object_unref (field); } g_object_unref (addrs_iter); if (!matched) { have_name_prefix = FALSE; have_name_substring = FALSE; have_addr_prefix = FALSE; have_addr_substring = FALSE; break; } } if (have_name_prefix) weight += NAME_PREFIX_MATCH_WEIGHT; else if (have_name_substring) weight += NAME_SUBSTRING_MATCH_WEIGHT; if (have_addr_prefix) weight += ADDR_PREFIX_MATCH_WEIGHT; else if (have_addr_substring) weight += ADDR_SUBSTRING_MATCH_WEIGHT; g_free (alias); g_free (name); g_free (nick); g_object_unref (im_addrs); return weight; }
static void aggregator_individuals_changed_cb (FolksIndividualAggregator *aggregator, GeeMultiMap *changes, EmpathyIndividualManager *self) { EmpathyIndividualManagerPriv *priv = GET_PRIV (self); GeeIterator *iter; GeeSet *removed; GeeCollection *added; GList *added_set = NULL, *added_filtered = NULL, *removed_list = NULL; /* We're not interested in the relationships between the added and removed * individuals, so just extract collections of them. Note that the added * collection may contain duplicates, while the removed set won't. */ removed = gee_multi_map_get_keys (changes); added = gee_multi_map_get_values (changes); /* Handle the removals first, as one of the added Individuals might have the * same ID as one of the removed Individuals (due to linking). */ iter = gee_iterable_iterator (GEE_ITERABLE (removed)); while (gee_iterator_next (iter)) { FolksIndividual *ind = gee_iterator_get (iter); if (ind == NULL) continue; g_signal_handlers_disconnect_by_func (ind, individual_notify_personas_cb, self); if (g_hash_table_lookup (priv->individuals, folks_individual_get_id (ind)) != NULL) { remove_individual (self, ind); removed_list = g_list_prepend (removed_list, ind); } g_clear_object (&ind); } g_clear_object (&iter); /* Filter the individuals for ones which contain EmpathyContacts */ iter = gee_iterable_iterator (GEE_ITERABLE (added)); while (gee_iterator_next (iter)) { FolksIndividual *ind = gee_iterator_get (iter); /* Make sure we handle each added individual only once. */ if (ind == NULL || g_list_find (added_set, ind) != NULL) continue; added_set = g_list_prepend (added_set, ind); g_signal_connect (ind, "notify::personas", G_CALLBACK (individual_notify_personas_cb), self); if (empathy_folks_individual_contains_contact (ind) == TRUE) { add_individual (self, ind); added_filtered = g_list_prepend (added_filtered, ind); } g_clear_object (&ind); } g_clear_object (&iter); g_list_free (added_set); g_object_unref (added); g_object_unref (removed); /* Bail if we have no individuals left */ if (added_filtered == NULL && removed == NULL) return; added_filtered = g_list_reverse (added_filtered); g_signal_emit (self, signals[MEMBERS_CHANGED], 0, NULL, added_filtered, removed_list, TP_CHANNEL_GROUP_CHANGE_REASON_NONE, TRUE); g_list_free (added_filtered); g_list_free (removed_list); }