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 */
71 GtkWidget *search_widget; /* child widget */
73 FolksIndividual *start_individual; /* owned, allow-none */
74 FolksIndividual *new_individual; /* owned, allow-none */
76 /* Stores the Individuals whose Personas have been added to the
78 /* unowned Individual (borrowed from EmpathyIndividualStore) -> bool */
79 GHashTable *changed_individuals;
80 } EmpathyIndividualLinkerPriv;
83 PROP_START_INDIVIDUAL = 1,
87 G_DEFINE_TYPE (EmpathyIndividualLinker, empathy_individual_linker,
91 contact_toggle_cell_data_func (GtkTreeViewColumn *tree_column,
92 GtkCellRenderer *cell,
93 GtkTreeModel *tree_model,
95 EmpathyIndividualLinker *self)
97 EmpathyIndividualLinkerPriv *priv;
98 FolksIndividual *individual;
99 gboolean is_group, individual_added;
101 priv = GET_PRIV (self);
103 gtk_tree_model_get (tree_model, iter,
104 EMPATHY_INDIVIDUAL_STORE_COL_IS_GROUP, &is_group,
105 EMPATHY_INDIVIDUAL_STORE_COL_INDIVIDUAL, &individual,
108 individual_added = GPOINTER_TO_UINT (g_hash_table_lookup (
109 priv->changed_individuals, individual));
111 /* We don't want to show checkboxes next to the group rows.
112 * All checkboxes should be sensitive except the checkbox for the start
113 * individual, which should be permanently active and insensitive */
115 "visible", !is_group,
116 "sensitive", individual != priv->start_individual,
117 "activatable", individual != priv->start_individual,
118 "active", individual_added || individual == priv->start_individual,
121 tp_clear_object (&individual);
125 update_toggle_renderers (EmpathyIndividualLinker *self)
127 EmpathyIndividualLinkerPriv *priv = GET_PRIV (self);
129 /* Re-setting the cell data func to the same function causes a refresh of the
130 * entire column, ensuring that each toggle button is correctly active or
131 * inactive. This is necessary because one Individual might appear multiple
132 * times in the list (in different groups), so toggling one instance of the
133 * Individual should toggle all of them. */
134 gtk_tree_view_column_set_cell_data_func (priv->toggle_column,
135 priv->toggle_renderer,
136 (GtkTreeCellDataFunc) contact_toggle_cell_data_func, self, NULL);
140 link_individual (EmpathyIndividualLinker *self,
141 FolksIndividual *individual)
143 EmpathyIndividualLinkerPriv *priv = GET_PRIV (self);
144 GList *new_persona_list;
146 /* Add the individual to the link */
147 g_hash_table_insert (priv->changed_individuals, individual,
148 GUINT_TO_POINTER (TRUE));
150 /* Add personas which are in @individual to priv->new_individual, appending
151 * them to the list of personas.
152 * This is rather slow. */
153 new_persona_list = g_list_copy (folks_individual_get_personas (
154 priv->new_individual));
155 new_persona_list = g_list_concat (new_persona_list,
156 g_list_copy (folks_individual_get_personas (individual)));
157 folks_individual_set_personas (priv->new_individual, new_persona_list);
158 g_list_free (new_persona_list);
160 /* Update the toggle renderers, so that if this Individual is listed in
161 * another group in the EmpathyIndividualView, the toggle button for that
162 * group is updated. */
163 update_toggle_renderers (self);
165 g_object_notify (G_OBJECT (self), "has-changed");
169 unlink_individual (EmpathyIndividualLinker *self,
170 FolksIndividual *individual)
172 EmpathyIndividualLinkerPriv *priv = GET_PRIV (self);
173 GList *new_persona_list, *old_persona_list, *removing_personas, *l;
175 /* Remove the individual from the link */
176 g_hash_table_remove (priv->changed_individuals, individual);
178 /* Remove personas which are in @individual from priv->new_individual.
179 * This is rather slow. */
180 old_persona_list = folks_individual_get_personas (priv->new_individual);
181 removing_personas = folks_individual_get_personas (individual);
182 new_persona_list = NULL;
184 for (l = old_persona_list; l != NULL; l = l->next)
186 GList *removing = g_list_find (removing_personas, l->data);
188 if (removing == NULL)
189 new_persona_list = g_list_prepend (new_persona_list, l->data);
192 new_persona_list = g_list_reverse (new_persona_list);
193 folks_individual_set_personas (priv->new_individual, new_persona_list);
194 g_list_free (new_persona_list);
196 /* Update the toggle renderers, so that if this Individual is listed in
197 * another group in the EmpathyIndividualView, the toggle button for that
198 * group is updated. */
199 update_toggle_renderers (self);
201 g_object_notify (G_OBJECT (self), "has-changed");
205 toggle_individual_row (EmpathyIndividualLinker *self,
208 EmpathyIndividualLinkerPriv *priv = GET_PRIV (self);
209 FolksIndividual *individual;
211 GtkTreeModel *tree_model;
212 gboolean individual_added;
214 tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->individual_view));
216 gtk_tree_model_get_iter (tree_model, &iter, path);
217 gtk_tree_model_get (tree_model, &iter,
218 EMPATHY_INDIVIDUAL_STORE_COL_INDIVIDUAL, &individual,
221 if (individual == NULL)
224 individual_added = GPOINTER_TO_UINT (g_hash_table_lookup (
225 priv->changed_individuals, individual));
227 /* Toggle the Individual's linked status */
228 if (individual_added)
229 unlink_individual (self, individual);
231 link_individual (self, individual);
233 g_object_unref (individual);
237 row_activated_cb (EmpathyIndividualView *view,
239 GtkTreeViewColumn *column,
240 EmpathyIndividualLinker *self)
242 toggle_individual_row (self, path);
246 row_toggled_cb (GtkCellRendererToggle *cell_renderer,
248 EmpathyIndividualLinker *self)
250 GtkTreePath *tree_path = gtk_tree_path_new_from_string (path);
251 toggle_individual_row (self, tree_path);
252 gtk_tree_path_free (tree_path);
256 individual_view_drag_motion_cb (GtkWidget *widget,
257 GdkDragContext *context,
262 EmpathyIndividualView *view = EMPATHY_INDIVIDUAL_VIEW (widget);
265 target = gtk_drag_dest_find_target (GTK_WIDGET (view), context, NULL);
267 if (target == gdk_atom_intern_static_string ("text/persona-id"))
271 /* FIXME: It doesn't make sense for us to highlight a specific row or
272 * position to drop a Persona in, so just highlight the entire widget.
273 * Since I can't find a way to do this, just highlight the first possible
274 * position in the tree. */
275 gdk_drag_status (context, gdk_drag_context_get_suggested_action (context),
278 path = gtk_tree_path_new_first ();
279 gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (view), path,
280 GTK_TREE_VIEW_DROP_BEFORE);
281 gtk_tree_path_free (path);
286 /* Unknown or unhandled drag target */
287 gdk_drag_status (context, GDK_ACTION_DEFAULT, time_);
288 gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (view), NULL, 0);
294 individual_view_drag_persona_received_cb (EmpathyIndividualView *view,
295 GdkDragAction action,
296 FolksPersona *persona,
297 FolksIndividual *individual,
298 EmpathyIndividualLinker *self)
300 EmpathyIndividualLinkerPriv *priv = GET_PRIV (self);
302 /* A Persona has been dragged onto the EmpathyIndividualView (from the
303 * EmpathyPersonaView), so we try to remove the Individual which contains
304 * the Persona from the link. */
305 if (individual != priv->start_individual)
307 unlink_individual (self, individual);
315 persona_view_drag_individual_received_cb (EmpathyPersonaView *view,
316 GdkDragAction action,
317 FolksIndividual *individual,
318 EmpathyIndividualLinker *self)
320 /* An Individual has been dragged onto the EmpathyPersonaView (from the
321 * EmpathyIndividualView), so we try to add the Individual to the link. */
322 link_individual (self, individual);
328 set_up (EmpathyIndividualLinker *self)
330 EmpathyIndividualLinkerPriv *priv;
331 EmpathyIndividualManager *individual_manager;
334 GtkWidget *label, *scrolled_window;
336 EmpathyPersonaView *persona_view;
338 GtkWidget *alignment;
340 priv = GET_PRIV (self);
342 top_vbox = gtk_vbox_new (FALSE, 6);
345 paned = GTK_PANED (gtk_hpaned_new ());
347 /* Left column heading */
348 alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
349 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 0, 6);
350 gtk_widget_show (alignment);
352 vbox = GTK_BOX (gtk_vbox_new (FALSE, 6));
353 label = gtk_label_new (NULL);
354 tmp = g_strdup_printf ("<b>%s</b>", _("Select contacts to link"));
355 gtk_label_set_markup (GTK_LABEL (label), tmp);
357 gtk_box_pack_start (vbox, label, FALSE, TRUE, 0);
358 gtk_widget_show (label);
360 /* Individual selector */
361 individual_manager = empathy_individual_manager_dup_singleton ();
362 priv->individual_store = empathy_individual_store_new (individual_manager);
363 g_object_unref (individual_manager);
365 empathy_individual_store_set_show_protocols (priv->individual_store, FALSE);
367 priv->individual_view = empathy_individual_view_new (priv->individual_store,
368 EMPATHY_INDIVIDUAL_VIEW_FEATURE_INDIVIDUAL_DRAG |
369 EMPATHY_INDIVIDUAL_VIEW_FEATURE_INDIVIDUAL_DROP |
370 EMPATHY_INDIVIDUAL_VIEW_FEATURE_PERSONA_DROP,
371 EMPATHY_INDIVIDUAL_FEATURE_NONE);
372 empathy_individual_view_set_show_offline (priv->individual_view, TRUE);
373 empathy_individual_view_set_show_untrusted (priv->individual_view, FALSE);
375 g_signal_connect (priv->individual_view, "row-activated",
376 (GCallback) row_activated_cb, self);
377 g_signal_connect (priv->individual_view, "drag-motion",
378 (GCallback) individual_view_drag_motion_cb, self);
379 g_signal_connect (priv->individual_view, "drag-persona-received",
380 (GCallback) individual_view_drag_persona_received_cb, self);
382 /* Add a checkbox column to the selector */
383 priv->toggle_renderer = gtk_cell_renderer_toggle_new ();
384 g_signal_connect (priv->toggle_renderer, "toggled",
385 (GCallback) row_toggled_cb, self);
387 priv->toggle_column = gtk_tree_view_column_new ();
388 gtk_tree_view_column_pack_start (priv->toggle_column, priv->toggle_renderer,
390 gtk_tree_view_column_set_cell_data_func (priv->toggle_column,
391 priv->toggle_renderer,
392 (GtkTreeCellDataFunc) contact_toggle_cell_data_func, self, NULL);
394 gtk_tree_view_insert_column (GTK_TREE_VIEW (priv->individual_view),
395 priv->toggle_column, 0);
397 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
398 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
399 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
400 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
402 gtk_container_add (GTK_CONTAINER (scrolled_window),
403 GTK_WIDGET (priv->individual_view));
404 gtk_widget_show (GTK_WIDGET (priv->individual_view));
406 gtk_box_pack_start (vbox, scrolled_window, TRUE, TRUE, 0);
407 gtk_widget_show (scrolled_window);
410 priv->search_widget = empathy_live_search_new (
411 GTK_WIDGET (priv->individual_view));
412 empathy_individual_view_set_live_search (priv->individual_view,
413 EMPATHY_LIVE_SEARCH (priv->search_widget));
415 gtk_box_pack_end (vbox, priv->search_widget, FALSE, TRUE, 0);
417 gtk_container_add (GTK_CONTAINER (alignment), GTK_WIDGET (vbox));
418 gtk_paned_pack1 (paned, alignment, TRUE, FALSE);
419 gtk_widget_show (GTK_WIDGET (vbox));
421 /* Right column heading */
422 alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
423 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 6, 0);
424 gtk_widget_show (alignment);
426 vbox = GTK_BOX (gtk_vbox_new (FALSE, 6));
427 label = gtk_label_new (NULL);
428 tmp = g_strdup_printf ("<b>%s</b>", _("New contact preview"));
429 gtk_label_set_markup (GTK_LABEL (label), tmp);
431 gtk_box_pack_start (vbox, label, FALSE, TRUE, 0);
432 gtk_widget_show (label);
434 /* New individual preview */
435 priv->preview_widget = empathy_individual_widget_new (priv->new_individual,
436 EMPATHY_INDIVIDUAL_WIDGET_SHOW_DETAILS);
437 gtk_box_pack_start (vbox, priv->preview_widget, FALSE, TRUE, 0);
438 gtk_widget_show (priv->preview_widget);
441 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
442 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
443 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
444 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
447 priv->persona_store = empathy_persona_store_new (priv->new_individual);
448 empathy_persona_store_set_show_protocols (priv->persona_store, TRUE);
449 persona_view = empathy_persona_view_new (priv->persona_store,
450 EMPATHY_PERSONA_VIEW_FEATURE_ALL);
451 empathy_persona_view_set_show_offline (persona_view, TRUE);
453 g_signal_connect (persona_view, "drag-individual-received",
454 (GCallback) persona_view_drag_individual_received_cb, self);
456 gtk_container_add (GTK_CONTAINER (scrolled_window),
457 GTK_WIDGET (persona_view));
458 gtk_widget_show (GTK_WIDGET (persona_view));
460 gtk_box_pack_start (vbox, scrolled_window, TRUE, TRUE, 0);
461 gtk_widget_show (scrolled_window);
463 gtk_container_add (GTK_CONTAINER (alignment), GTK_WIDGET (vbox));
464 gtk_paned_pack2 (paned, alignment, TRUE, FALSE);
465 gtk_widget_show (GTK_WIDGET (vbox));
467 gtk_widget_show (GTK_WIDGET (paned));
470 label = gtk_label_new (NULL);
471 tmp = g_strdup_printf ("<i>%s</i>",
472 _("Contacts selected in the list on the left will be linked together."));
473 gtk_label_set_markup (GTK_LABEL (label), tmp);
475 gtk_widget_show (label);
477 gtk_box_pack_start (GTK_BOX (top_vbox), GTK_WIDGET (paned), TRUE, TRUE, 0);
478 gtk_box_pack_start (GTK_BOX (top_vbox), label, FALSE, TRUE, 0);
480 /* Add the main vbox to the bin */
481 gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (top_vbox));
482 gtk_widget_show (GTK_WIDGET (top_vbox));
486 empathy_individual_linker_init (EmpathyIndividualLinker *self)
488 EmpathyIndividualLinkerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
489 EMPATHY_TYPE_INDIVIDUAL_LINKER, EmpathyIndividualLinkerPriv);
493 priv->changed_individuals = g_hash_table_new (NULL, NULL);
499 get_property (GObject *object,
504 EmpathyIndividualLinkerPriv *priv;
506 priv = GET_PRIV (object);
510 case PROP_START_INDIVIDUAL:
511 g_value_set_object (value, priv->start_individual);
513 case PROP_HAS_CHANGED:
514 g_value_set_boolean (value, empathy_individual_linker_get_has_changed (
515 EMPATHY_INDIVIDUAL_LINKER (object)));
518 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
524 set_property (GObject *object,
529 EmpathyIndividualLinkerPriv *priv;
531 priv = GET_PRIV (object);
535 case PROP_START_INDIVIDUAL:
536 empathy_individual_linker_set_start_individual (
537 EMPATHY_INDIVIDUAL_LINKER (object), g_value_get_object (value));
540 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
546 dispose (GObject *object)
548 EmpathyIndividualLinkerPriv *priv = GET_PRIV (object);
550 tp_clear_object (&priv->individual_store);
551 tp_clear_object (&priv->persona_store);
552 tp_clear_object (&priv->start_individual);
553 tp_clear_object (&priv->new_individual);
555 G_OBJECT_CLASS (empathy_individual_linker_parent_class)->dispose (object);
559 finalize (GObject *object)
561 EmpathyIndividualLinkerPriv *priv = GET_PRIV (object);
563 g_hash_table_destroy (priv->changed_individuals);
565 G_OBJECT_CLASS (empathy_individual_linker_parent_class)->finalize (object);
569 size_allocate (GtkWidget *widget,
570 GtkAllocation *allocation)
572 GtkBin *bin = GTK_BIN (widget);
573 GtkAllocation child_allocation;
576 gtk_widget_set_allocation (widget, allocation);
578 child = gtk_bin_get_child (bin);
580 if (child && gtk_widget_get_visible (child))
582 child_allocation.x = allocation->x +
583 gtk_container_get_border_width (GTK_CONTAINER (widget));
584 child_allocation.y = allocation->y +
585 gtk_container_get_border_width (GTK_CONTAINER (widget));
586 child_allocation.width = MAX (allocation->width -
587 gtk_container_get_border_width (GTK_CONTAINER (widget)) * 2, 0);
588 child_allocation.height = MAX (allocation->height -
589 gtk_container_get_border_width (GTK_CONTAINER (widget)) * 2, 0);
591 gtk_widget_size_allocate (child, &child_allocation);
596 empathy_individual_linker_class_init (EmpathyIndividualLinkerClass *klass)
598 GObjectClass *object_class = G_OBJECT_CLASS (klass);
599 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
601 object_class->get_property = get_property;
602 object_class->set_property = set_property;
603 object_class->dispose = dispose;
604 object_class->finalize = finalize;
606 widget_class->size_allocate = size_allocate;
609 * EmpathyIndividualLinker:start-individual:
611 * The #FolksIndividual to link other individuals to. This individual is
612 * selected by default in the list of individuals, and cannot be unselected.
613 * This ensures that empathy_individual_linker_get_linked_personas() will
614 * always return at least one persona to link.
616 g_object_class_install_property (object_class, PROP_START_INDIVIDUAL,
617 g_param_spec_object ("start-individual",
619 "The #FolksIndividual to link other individuals to.",
620 FOLKS_TYPE_INDIVIDUAL,
621 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
624 * EmpathyIndividualLinker:has-changed:
626 * Whether #FolksIndividual<!-- -->s have been added to or removed from
627 * the linked individual currently displayed in the widget.
629 * This will be %FALSE after the widget is initialised, and set to %TRUE when
630 * an individual is checked in the individual view on the left of the widget.
631 * If the individual is later unchecked, this will be reset to %FALSE, etc.
633 g_object_class_install_property (object_class, PROP_HAS_CHANGED,
634 g_param_spec_boolean ("has-changed",
636 "Whether individuals have been added to or removed from the linked "
637 "individual currently displayed in the widget.",
639 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
641 g_type_class_add_private (object_class, sizeof (EmpathyIndividualLinkerPriv));
645 * empathy_individual_linker_new:
646 * @start_individual: (allow-none): the #FolksIndividual to link to, or %NULL
648 * Creates a new #EmpathyIndividualLinker.
650 * Return value: a new #EmpathyIndividualLinker
653 empathy_individual_linker_new (FolksIndividual *start_individual)
655 g_return_val_if_fail (start_individual == NULL ||
656 FOLKS_IS_INDIVIDUAL (start_individual), NULL);
658 return g_object_new (EMPATHY_TYPE_INDIVIDUAL_LINKER,
659 "start-individual", start_individual,
664 * empathy_individual_linker_get_start_individual:
665 * @self: an #EmpathyIndividualLinker
667 * Get the value of #EmpathyIndividualLinker:start-individual.
669 * Return value: (transfer none): the start individual for linking, or %NULL
672 empathy_individual_linker_get_start_individual (EmpathyIndividualLinker *self)
674 g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_LINKER (self), NULL);
676 return GET_PRIV (self)->start_individual;
680 * empathy_individual_linker_set_start_individual:
681 * @self: an #EmpathyIndividualLinker
682 * @individual: (allow-none): the start individual, or %NULL
684 * Set the value of #EmpathyIndividualLinker:start-individual to @individual.
687 empathy_individual_linker_set_start_individual (EmpathyIndividualLinker *self,
688 FolksIndividual *individual)
690 EmpathyIndividualLinkerPriv *priv;
692 g_return_if_fail (EMPATHY_IS_INDIVIDUAL_LINKER (self));
693 g_return_if_fail (individual == NULL || FOLKS_IS_INDIVIDUAL (individual));
695 priv = GET_PRIV (self);
697 tp_clear_object (&priv->start_individual);
698 tp_clear_object (&priv->new_individual);
699 g_hash_table_remove_all (priv->changed_individuals);
701 if (individual != NULL)
703 priv->start_individual = g_object_ref (individual);
704 priv->new_individual = folks_individual_new (
705 folks_individual_get_personas (individual));
706 empathy_individual_view_set_store (priv->individual_view,
707 priv->individual_store);
711 priv->start_individual = NULL;
712 priv->new_individual = NULL;
714 /* We only display Individuals in the individual view if we have a
715 * new_individual to link them into */
716 empathy_individual_view_set_store (priv->individual_view, NULL);
719 empathy_individual_widget_set_individual (
720 EMPATHY_INDIVIDUAL_WIDGET (priv->preview_widget), priv->new_individual);
721 empathy_persona_store_set_individual (priv->persona_store,
722 priv->new_individual);
724 g_object_freeze_notify (G_OBJECT (self));
725 g_object_notify (G_OBJECT (self), "start-individual");
726 g_object_notify (G_OBJECT (self), "has-changed");
727 g_object_thaw_notify (G_OBJECT (self));
731 * empathy_individual_linker_get_linked_personas:
732 * @self: an #EmpathyIndividualLinker
734 * Return a list of the #FolksPersona<!-- -->s which comprise the linked
735 * individual currently displayed in the widget.
737 * The return value is guaranteed to contain at least one element.
739 * Return value: (transfer none) (element-type Folks.Persona): a list of
740 * #FolksPersona<!-- -->s to link together
743 empathy_individual_linker_get_linked_personas (EmpathyIndividualLinker *self)
745 EmpathyIndividualLinkerPriv *priv;
748 g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_LINKER (self), NULL);
750 priv = GET_PRIV (self);
752 if (priv->new_individual == NULL)
755 personas = folks_individual_get_personas (priv->new_individual);
756 g_assert (personas != NULL);
761 * empathy_individual_linker_get_has_changed:
762 * @self: an #EmpathyIndividualLinker
764 * Return whether #FolksIndividual<!-- -->s have been added to or removed from
765 * the linked individual currently displayed in the widget.
767 * This will be %FALSE after the widget is initialised, and set to %TRUE when
768 * an individual is checked in the individual view on the left of the widget.
769 * If the individual is later unchecked, this will be reset to %FALSE, etc.
771 * Return value: %TRUE if the linked individual has been changed, %FALSE
775 empathy_individual_linker_get_has_changed (EmpathyIndividualLinker *self)
777 EmpathyIndividualLinkerPriv *priv;
779 g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_LINKER (self), FALSE);
781 priv = GET_PRIV (self);
783 return (g_hash_table_size (priv->changed_individuals) > 0) ? TRUE : FALSE;
787 empathy_individual_linker_set_search_text (EmpathyIndividualLinker *self,
788 const gchar *search_text)
790 g_return_if_fail (EMPATHY_IS_INDIVIDUAL_LINKER (self));
792 empathy_live_search_set_text (
793 EMPATHY_LIVE_SEARCH (GET_PRIV (self)->search_widget), search_text);