2 * Copyright (C) 2010 Collabora Ltd.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301 USA
19 * Authors: Philip Withnall <philip.withnall@collabora.co.uk>
26 #include <glib/gi18n-lib.h>
29 #include <telepathy-glib/util.h>
31 #include <folks/folks.h>
33 #include <libempathy/empathy-individual-manager.h>
34 #include <libempathy/empathy-utils.h>
36 #include "empathy-individual-linker.h"
37 #include "empathy-individual-store.h"
38 #include "empathy-individual-view.h"
39 #include "empathy-individual-widget.h"
40 #include "empathy-persona-store.h"
41 #include "empathy-persona-view.h"
44 * SECTION:empathy-individual-linker
45 * @title:EmpathyIndividualLinker
46 * @short_description: A widget used to link together #FolksIndividual<!-- -->s
47 * @include: libempathy-gtk/empathy-individual-linker.h
49 * #EmpathyIndividualLinker is a widget which allows selection of several
50 * #FolksIndividual<!-- -->s to link together to form a single new individual.
51 * The widget provides a preview of the linked individual.
55 * EmpathyIndividualLinker:
56 * @parent: parent object
58 * Widget which extends #GtkBin to provide a list of #FolksIndividual<!-- -->s
62 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIndividualLinker)
65 EmpathyIndividualStore *individual_store; /* owned */
66 EmpathyIndividualView *individual_view; /* child widget */
67 GtkWidget *preview_widget; /* child widget */
68 EmpathyPersonaStore *persona_store; /* owned */
69 GtkTreeViewColumn *toggle_column; /* child widget */
70 GtkCellRenderer *toggle_renderer; /* child widget */
72 FolksIndividual *start_individual; /* owned, allow-none */
73 FolksIndividual *new_individual; /* owned, allow-none */
75 /* Stores the Individuals whose Personas have been added to the
77 /* unowned Individual (borrowed from EmpathyIndividualStore) -> bool */
78 GHashTable *changed_individuals;
79 } EmpathyIndividualLinkerPriv;
82 PROP_START_INDIVIDUAL = 1,
85 G_DEFINE_TYPE (EmpathyIndividualLinker, empathy_individual_linker,
89 contact_toggle_cell_data_func (GtkTreeViewColumn *tree_column,
90 GtkCellRenderer *cell,
91 GtkTreeModel *tree_model,
93 EmpathyIndividualLinker *self)
95 EmpathyIndividualLinkerPriv *priv;
96 FolksIndividual *individual;
97 gboolean is_group, individual_added;
99 priv = GET_PRIV (self);
101 gtk_tree_model_get (tree_model, iter,
102 EMPATHY_INDIVIDUAL_STORE_COL_IS_GROUP, &is_group,
103 EMPATHY_INDIVIDUAL_STORE_COL_INDIVIDUAL, &individual,
106 individual_added = GPOINTER_TO_UINT (g_hash_table_lookup (
107 priv->changed_individuals, individual));
109 /* We don't want to show checkboxes next to the group rows.
110 * All checkboxes should be sensitive except the checkbox for the start
111 * individual, which should be permanently active and insensitive */
113 "visible", !is_group,
114 "sensitive", individual != priv->start_individual,
115 "activatable", individual != priv->start_individual,
116 "active", individual_added || individual == priv->start_individual,
119 tp_clear_object (&individual);
123 update_toggle_renderers (EmpathyIndividualLinker *self)
125 EmpathyIndividualLinkerPriv *priv = GET_PRIV (self);
127 /* Re-setting the cell data func to the same function causes a refresh of the
128 * entire column, ensuring that each toggle button is correctly active or
129 * inactive. This is necessary because one Individual might appear multiple
130 * times in the list (in different groups), so toggling one instance of the
131 * Individual should toggle all of them. */
132 gtk_tree_view_column_set_cell_data_func (priv->toggle_column,
133 priv->toggle_renderer,
134 (GtkTreeCellDataFunc) contact_toggle_cell_data_func, self, NULL);
138 link_individual (EmpathyIndividualLinker *self,
139 FolksIndividual *individual)
141 EmpathyIndividualLinkerPriv *priv = GET_PRIV (self);
142 GList *new_persona_list;
144 /* Add the individual to the link */
145 g_hash_table_insert (priv->changed_individuals, individual,
146 GUINT_TO_POINTER (TRUE));
148 /* Add personas which are in @individual to priv->new_individual, appending
149 * them to the list of personas.
150 * This is rather slow. */
151 new_persona_list = g_list_copy (folks_individual_get_personas (
152 priv->new_individual));
153 new_persona_list = g_list_concat (new_persona_list,
154 g_list_copy (folks_individual_get_personas (individual)));
155 folks_individual_set_personas (priv->new_individual, new_persona_list);
156 g_list_free (new_persona_list);
158 /* Update the toggle renderers, so that if this Individual is listed in
159 * another group in the EmpathyIndividualView, the toggle button for that
160 * group is updated. */
161 update_toggle_renderers (self);
165 unlink_individual (EmpathyIndividualLinker *self,
166 FolksIndividual *individual)
168 EmpathyIndividualLinkerPriv *priv = GET_PRIV (self);
169 GList *new_persona_list, *old_persona_list, *removing_personas, *l;
171 /* Remove the individual from the link */
172 g_hash_table_remove (priv->changed_individuals, individual);
174 /* Remove personas which are in @individual from priv->new_individual.
175 * This is rather slow. */
176 old_persona_list = folks_individual_get_personas (priv->new_individual);
177 removing_personas = folks_individual_get_personas (individual);
178 new_persona_list = NULL;
180 for (l = old_persona_list; l != NULL; l = l->next)
182 GList *removing = g_list_find (removing_personas, l->data);
184 if (removing == NULL)
185 new_persona_list = g_list_prepend (new_persona_list, l->data);
188 new_persona_list = g_list_reverse (new_persona_list);
189 folks_individual_set_personas (priv->new_individual, new_persona_list);
190 g_list_free (new_persona_list);
192 /* Update the toggle renderers, so that if this Individual is listed in
193 * another group in the EmpathyIndividualView, the toggle button for that
194 * group is updated. */
195 update_toggle_renderers (self);
199 toggle_individual_row (EmpathyIndividualLinker *self,
202 EmpathyIndividualLinkerPriv *priv = GET_PRIV (self);
203 FolksIndividual *individual;
205 GtkTreeModel *tree_model;
206 gboolean individual_added;
208 tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->individual_view));
210 gtk_tree_model_get_iter (tree_model, &iter, path);
211 gtk_tree_model_get (tree_model, &iter,
212 EMPATHY_INDIVIDUAL_STORE_COL_INDIVIDUAL, &individual,
215 if (individual == NULL)
218 individual_added = GPOINTER_TO_UINT (g_hash_table_lookup (
219 priv->changed_individuals, individual));
221 /* Toggle the Individual's linked status */
222 if (individual_added)
223 unlink_individual (self, individual);
225 link_individual (self, individual);
227 g_object_unref (individual);
231 row_activated_cb (EmpathyIndividualView *view,
233 GtkTreeViewColumn *column,
234 EmpathyIndividualLinker *self)
236 toggle_individual_row (self, path);
240 row_toggled_cb (GtkCellRendererToggle *cell_renderer,
242 EmpathyIndividualLinker *self)
244 GtkTreePath *tree_path = gtk_tree_path_new_from_string (path);
245 toggle_individual_row (self, tree_path);
246 gtk_tree_path_free (tree_path);
250 individual_view_drag_motion_cb (GtkWidget *widget,
251 GdkDragContext *context,
256 EmpathyIndividualView *view = EMPATHY_INDIVIDUAL_VIEW (widget);
259 target = gtk_drag_dest_find_target (GTK_WIDGET (view), context, NULL);
261 if (target == gdk_atom_intern_static_string ("text/persona-id"))
265 /* FIXME: It doesn't make sense for us to highlight a specific row or
266 * position to drop a Persona in, so just highlight the entire widget.
267 * Since I can't find a way to do this, just highlight the first possible
268 * position in the tree. */
269 gdk_drag_status (context, gdk_drag_context_get_suggested_action (context),
272 path = gtk_tree_path_new_first ();
273 gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (view), path,
274 GTK_TREE_VIEW_DROP_BEFORE);
275 gtk_tree_path_free (path);
280 /* Unknown or unhandled drag target */
281 gdk_drag_status (context, GDK_ACTION_DEFAULT, time_);
282 gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (view), NULL, 0);
288 individual_view_drag_persona_received_cb (EmpathyIndividualView *view,
289 GdkDragAction action,
290 FolksPersona *persona,
291 FolksIndividual *individual,
292 EmpathyIndividualLinker *self)
294 EmpathyIndividualLinkerPriv *priv = GET_PRIV (self);
296 /* A Persona has been dragged onto the EmpathyIndividualView (from the
297 * EmpathyPersonaView), so we try to remove the Individual which contains
298 * the Persona from the link. */
299 if (individual != priv->start_individual)
301 unlink_individual (self, individual);
309 persona_view_drag_individual_received_cb (EmpathyPersonaView *view,
310 GdkDragAction action,
311 FolksIndividual *individual,
312 EmpathyIndividualLinker *self)
314 /* An Individual has been dragged onto the EmpathyPersonaView (from the
315 * EmpathyIndividualView), so we try to add the Individual to the link. */
316 link_individual (self, individual);
322 set_up (EmpathyIndividualLinker *self)
324 EmpathyIndividualLinkerPriv *priv;
325 EmpathyIndividualManager *individual_manager;
328 GtkWidget *label, *scrolled_window, *search_bar;
330 EmpathyPersonaView *persona_view;
332 GtkWidget *alignment;
334 priv = GET_PRIV (self);
336 top_vbox = gtk_vbox_new (FALSE, 6);
339 paned = GTK_PANED (gtk_hpaned_new ());
341 /* Left column heading */
342 alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
343 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 0, 6);
344 gtk_widget_show (alignment);
346 vbox = GTK_BOX (gtk_vbox_new (FALSE, 6));
347 label = gtk_label_new (NULL);
348 tmp = g_strdup_printf ("<b>%s</b>", _("Select contacts to link"));
349 gtk_label_set_markup (GTK_LABEL (label), tmp);
351 gtk_box_pack_start (vbox, label, FALSE, TRUE, 0);
352 gtk_widget_show (label);
354 /* Individual selector */
355 individual_manager = empathy_individual_manager_dup_singleton ();
356 priv->individual_store = empathy_individual_store_new (individual_manager);
357 g_object_unref (individual_manager);
359 empathy_individual_store_set_show_protocols (priv->individual_store, FALSE);
361 priv->individual_view = empathy_individual_view_new (priv->individual_store,
362 EMPATHY_INDIVIDUAL_VIEW_FEATURE_INDIVIDUAL_DRAG |
363 EMPATHY_INDIVIDUAL_VIEW_FEATURE_INDIVIDUAL_DROP |
364 EMPATHY_INDIVIDUAL_VIEW_FEATURE_PERSONA_DROP,
365 EMPATHY_INDIVIDUAL_FEATURE_NONE);
366 empathy_individual_view_set_show_offline (priv->individual_view, TRUE);
367 empathy_individual_view_set_show_untrusted (priv->individual_view, FALSE);
369 g_signal_connect (priv->individual_view, "row-activated",
370 (GCallback) row_activated_cb, self);
371 g_signal_connect (priv->individual_view, "drag-motion",
372 (GCallback) individual_view_drag_motion_cb, self);
373 g_signal_connect (priv->individual_view, "drag-persona-received",
374 (GCallback) individual_view_drag_persona_received_cb, self);
376 /* Add a checkbox column to the selector */
377 priv->toggle_renderer = gtk_cell_renderer_toggle_new ();
378 g_signal_connect (priv->toggle_renderer, "toggled",
379 (GCallback) row_toggled_cb, self);
381 priv->toggle_column = gtk_tree_view_column_new ();
382 gtk_tree_view_column_pack_start (priv->toggle_column, priv->toggle_renderer,
384 gtk_tree_view_column_set_cell_data_func (priv->toggle_column,
385 priv->toggle_renderer,
386 (GtkTreeCellDataFunc) contact_toggle_cell_data_func, self, NULL);
388 gtk_tree_view_insert_column (GTK_TREE_VIEW (priv->individual_view),
389 priv->toggle_column, 0);
391 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
392 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
393 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
394 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
396 gtk_container_add (GTK_CONTAINER (scrolled_window),
397 GTK_WIDGET (priv->individual_view));
398 gtk_widget_show (GTK_WIDGET (priv->individual_view));
400 gtk_box_pack_start (vbox, scrolled_window, TRUE, TRUE, 0);
401 gtk_widget_show (scrolled_window);
404 search_bar = empathy_live_search_new (GTK_WIDGET (priv->individual_view));
405 empathy_individual_view_set_live_search (priv->individual_view,
406 EMPATHY_LIVE_SEARCH (search_bar));
408 gtk_box_pack_end (vbox, search_bar, FALSE, TRUE, 0);
410 gtk_container_add (GTK_CONTAINER (alignment), GTK_WIDGET (vbox));
411 gtk_paned_pack1 (paned, alignment, TRUE, FALSE);
412 gtk_widget_show (GTK_WIDGET (vbox));
414 /* Right column heading */
415 alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
416 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 6, 0);
417 gtk_widget_show (alignment);
419 vbox = GTK_BOX (gtk_vbox_new (FALSE, 6));
420 label = gtk_label_new (NULL);
421 tmp = g_strdup_printf ("<b>%s</b>", _("New contact preview"));
422 gtk_label_set_markup (GTK_LABEL (label), tmp);
424 gtk_box_pack_start (vbox, label, FALSE, TRUE, 0);
425 gtk_widget_show (label);
427 /* New individual preview */
428 priv->preview_widget = empathy_individual_widget_new (priv->new_individual,
429 EMPATHY_INDIVIDUAL_WIDGET_SHOW_DETAILS);
430 gtk_box_pack_start (vbox, priv->preview_widget, FALSE, TRUE, 0);
431 gtk_widget_show (priv->preview_widget);
434 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
435 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
436 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
437 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
440 priv->persona_store = empathy_persona_store_new (priv->new_individual);
441 empathy_persona_store_set_show_protocols (priv->persona_store, TRUE);
442 persona_view = empathy_persona_view_new (priv->persona_store,
443 EMPATHY_PERSONA_VIEW_FEATURE_ALL);
444 empathy_persona_view_set_show_offline (persona_view, TRUE);
446 g_signal_connect (persona_view, "drag-individual-received",
447 (GCallback) persona_view_drag_individual_received_cb, self);
449 gtk_container_add (GTK_CONTAINER (scrolled_window),
450 GTK_WIDGET (persona_view));
451 gtk_widget_show (GTK_WIDGET (persona_view));
453 gtk_box_pack_start (vbox, scrolled_window, TRUE, TRUE, 0);
454 gtk_widget_show (scrolled_window);
456 gtk_container_add (GTK_CONTAINER (alignment), GTK_WIDGET (vbox));
457 gtk_paned_pack2 (paned, alignment, TRUE, FALSE);
458 gtk_widget_show (GTK_WIDGET (vbox));
460 gtk_widget_show (GTK_WIDGET (paned));
463 label = gtk_label_new (NULL);
464 tmp = g_strdup_printf ("<i>%s</i>",
465 _("Contacts selected in the list on the left will be linked together."));
466 gtk_label_set_markup (GTK_LABEL (label), tmp);
468 gtk_widget_show (label);
470 gtk_box_pack_start (GTK_BOX (top_vbox), GTK_WIDGET (paned), TRUE, TRUE, 0);
471 gtk_box_pack_start (GTK_BOX (top_vbox), label, FALSE, TRUE, 0);
473 /* Add the main vbox to the bin */
474 gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (top_vbox));
475 gtk_widget_show (GTK_WIDGET (top_vbox));
479 empathy_individual_linker_init (EmpathyIndividualLinker *self)
481 EmpathyIndividualLinkerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
482 EMPATHY_TYPE_INDIVIDUAL_LINKER, EmpathyIndividualLinkerPriv);
486 priv->changed_individuals = g_hash_table_new (NULL, NULL);
492 get_property (GObject *object,
497 EmpathyIndividualLinkerPriv *priv;
499 priv = GET_PRIV (object);
503 case PROP_START_INDIVIDUAL:
504 g_value_set_object (value, priv->start_individual);
507 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
513 set_property (GObject *object,
518 EmpathyIndividualLinkerPriv *priv;
520 priv = GET_PRIV (object);
524 case PROP_START_INDIVIDUAL:
525 empathy_individual_linker_set_start_individual (
526 EMPATHY_INDIVIDUAL_LINKER (object), g_value_get_object (value));
529 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
535 dispose (GObject *object)
537 EmpathyIndividualLinkerPriv *priv = GET_PRIV (object);
539 tp_clear_object (&priv->individual_store);
540 tp_clear_object (&priv->persona_store);
541 tp_clear_object (&priv->start_individual);
542 tp_clear_object (&priv->new_individual);
544 G_OBJECT_CLASS (empathy_individual_linker_parent_class)->dispose (object);
548 finalize (GObject *object)
550 EmpathyIndividualLinkerPriv *priv = GET_PRIV (object);
552 g_hash_table_destroy (priv->changed_individuals);
554 G_OBJECT_CLASS (empathy_individual_linker_parent_class)->finalize (object);
558 size_request (GtkWidget *widget,
559 GtkRequisition *requisition)
561 GtkBin *bin = GTK_BIN (widget);
565 gtk_container_get_border_width (GTK_CONTAINER (widget)) * 2;
566 requisition->height =
567 gtk_container_get_border_width (GTK_CONTAINER (widget)) * 2;
569 child = gtk_bin_get_child (bin);
571 if (child && gtk_widget_get_visible (child))
573 GtkRequisition child_requisition;
575 gtk_widget_size_request (child, &child_requisition);
577 requisition->width += child_requisition.width;
578 requisition->height += child_requisition.height;
583 size_allocate (GtkWidget *widget,
584 GtkAllocation *allocation)
586 GtkBin *bin = GTK_BIN (widget);
587 GtkAllocation child_allocation;
590 gtk_widget_set_allocation (widget, allocation);
592 child = gtk_bin_get_child (bin);
594 if (child && gtk_widget_get_visible (child))
596 child_allocation.x = allocation->x +
597 gtk_container_get_border_width (GTK_CONTAINER (widget));
598 child_allocation.y = allocation->y +
599 gtk_container_get_border_width (GTK_CONTAINER (widget));
600 child_allocation.width = MAX (allocation->width -
601 gtk_container_get_border_width (GTK_CONTAINER (widget)) * 2, 0);
602 child_allocation.height = MAX (allocation->height -
603 gtk_container_get_border_width (GTK_CONTAINER (widget)) * 2, 0);
605 gtk_widget_size_allocate (child, &child_allocation);
610 empathy_individual_linker_class_init (EmpathyIndividualLinkerClass *klass)
612 GObjectClass *object_class = G_OBJECT_CLASS (klass);
613 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
615 object_class->get_property = get_property;
616 object_class->set_property = set_property;
617 object_class->dispose = dispose;
618 object_class->finalize = finalize;
620 widget_class->size_request = size_request;
621 widget_class->size_allocate = size_allocate;
624 * EmpathyIndividualLinker:start-individual:
626 * The #FolksIndividual to link other individuals to. This individual is
627 * selected by default in the list of individuals, and cannot be unselected.
628 * This ensures that empathy_individual_linker_get_linked_personas() will
629 * always return at least one persona to link.
631 g_object_class_install_property (object_class, PROP_START_INDIVIDUAL,
632 g_param_spec_object ("start-individual",
634 "The #FolksIndividual to link other individuals to.",
635 FOLKS_TYPE_INDIVIDUAL,
636 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
638 g_type_class_add_private (object_class, sizeof (EmpathyIndividualLinkerPriv));
642 * empathy_individual_linker_new:
643 * @start_individual: (allow-none): the #FolksIndividual to link to, or %NULL
645 * Creates a new #EmpathyIndividualLinker.
647 * Return value: a new #EmpathyIndividualLinker
650 empathy_individual_linker_new (FolksIndividual *start_individual)
652 g_return_val_if_fail (start_individual == NULL ||
653 FOLKS_IS_INDIVIDUAL (start_individual), NULL);
655 return g_object_new (EMPATHY_TYPE_INDIVIDUAL_LINKER,
656 "start-individual", start_individual,
661 * empathy_individual_linker_get_start_individual:
662 * @self: an #EmpathyIndividualLinker
664 * Get the value of #EmpathyIndividualLinker:start-individual.
666 * Return value: (transfer none): the start individual for linking, or %NULL
669 empathy_individual_linker_get_start_individual (EmpathyIndividualLinker *self)
671 g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_LINKER (self), NULL);
673 return GET_PRIV (self)->start_individual;
677 * empathy_individual_linker_set_start_individual:
678 * @self: an #EmpathyIndividualLinker
679 * @individual: (allow-none): the start individual, or %NULL
681 * Set the value of #EmpathyIndividualLinker:start-individual to @individual.
684 empathy_individual_linker_set_start_individual (EmpathyIndividualLinker *self,
685 FolksIndividual *individual)
687 EmpathyIndividualLinkerPriv *priv;
689 g_return_if_fail (EMPATHY_IS_INDIVIDUAL_LINKER (self));
690 g_return_if_fail (individual == NULL || FOLKS_IS_INDIVIDUAL (individual));
692 priv = GET_PRIV (self);
694 tp_clear_object (&priv->start_individual);
695 tp_clear_object (&priv->new_individual);
696 g_hash_table_remove_all (priv->changed_individuals);
698 if (individual != NULL)
700 priv->start_individual = g_object_ref (individual);
701 priv->new_individual = folks_individual_new (
702 folks_individual_get_personas (individual));
703 empathy_individual_view_set_store (priv->individual_view,
704 priv->individual_store);
708 priv->start_individual = NULL;
709 priv->new_individual = NULL;
711 /* We only display Individuals in the individual view if we have a
712 * new_individual to link them into */
713 empathy_individual_view_set_store (priv->individual_view, NULL);
716 empathy_individual_widget_set_individual (
717 EMPATHY_INDIVIDUAL_WIDGET (priv->preview_widget), priv->new_individual);
718 empathy_persona_store_set_individual (priv->persona_store,
719 priv->new_individual);
721 g_object_notify (G_OBJECT (self), "start-individual");
725 * empathy_individual_linker_get_linked_personas:
726 * @self: an #EmpathyIndividualLinker
728 * Return a list of the #FolksPersona<!-- -->s which comprise the linked
729 * individual currently displayed in the widget.
731 * The return value is guaranteed to contain at least one element.
733 * Return value: (transfer none) (element-type Folks.Persona): a list of
734 * #FolksPersona<!-- -->s to link together
737 empathy_individual_linker_get_linked_personas (EmpathyIndividualLinker *self)
739 EmpathyIndividualLinkerPriv *priv;
742 g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_LINKER (self), NULL);
744 priv = GET_PRIV (self);
746 if (priv->new_individual == NULL)
749 personas = folks_individual_get_personas (priv->new_individual);
750 g_assert (personas != NULL);