LogWindow: better logic for the buttons sensitivity
[empathy-mirror.git] / libempathy-gtk / empathy-persona-view.c
blob6d1629651f6e6cb5d0f49d89dc3f58670cee5c40
1 /*
2 * Copyright (C) 2005-2007 Imendio AB
3 * Copyright (C) 2007-2008, 2010 Collabora Ltd.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301 USA
20 * Authors: Mikael Hallendal <micke@imendio.com>
21 * Martyn Russell <martyn@imendio.com>
22 * Xavier Claessens <xclaesse@gmail.com>
23 * Philip Withnall <philip.withnall@collabora.co.uk>
25 * Based off EmpathyContactListView.
28 #include "config.h"
30 #include <string.h>
32 #include <glib/gi18n-lib.h>
33 #include <gtk/gtk.h>
35 #include <telepathy-glib/util.h>
37 #include <folks/folks.h>
38 #include <folks/folks-telepathy.h>
40 #include <libempathy/empathy-individual-manager.h>
41 #include <libempathy/empathy-utils.h>
43 #include "empathy-persona-view.h"
44 #include "empathy-contact-widget.h"
45 #include "empathy-images.h"
46 #include "empathy-cell-renderer-text.h"
47 #include "empathy-cell-renderer-activatable.h"
48 #include "empathy-gtk-enum-types.h"
49 #include "empathy-gtk-marshal.h"
50 #include "empathy-ui-utils.h"
52 #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
53 #include <libempathy/empathy-debug.h>
55 /**
56 * SECTION:empathy-persona-view
57 * @title: EmpathyPersonaView
58 * @short_description: A tree view which displays personas from an individual
59 * @include: libempathy-gtk/empathy-persona-view.h
61 * #EmpathyPersonaView is a tree view widget which displays the personas from
62 * a given #EmpathyPersonaStore.
64 * It supports hiding offline personas and highlighting active personas. Active
65 * personas are those which have recently changed state (e.g. online, offline or
66 * from normal to a busy state).
69 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyPersonaView)
71 typedef struct
73 GtkTreeModelFilter *filter;
74 GtkWidget *tooltip_widget;
75 gboolean show_offline;
76 EmpathyPersonaViewFeatureFlags features;
77 } EmpathyPersonaViewPriv;
79 enum
81 PROP_0,
82 PROP_MODEL,
83 PROP_SHOW_OFFLINE,
84 PROP_FEATURES,
87 typedef enum
89 DND_DRAG_TYPE_UNKNOWN = -1,
90 DND_DRAG_TYPE_INDIVIDUAL_ID = 0,
91 DND_DRAG_TYPE_PERSONA_ID,
92 DND_DRAG_TYPE_STRING,
93 } DndDragType;
95 #define DRAG_TYPE(T,I) \
96 { (gchar *) T, 0, I }
98 static const GtkTargetEntry drag_types_dest[] = {
99 DRAG_TYPE ("text/individual-id", DND_DRAG_TYPE_INDIVIDUAL_ID),
100 DRAG_TYPE ("text/plain", DND_DRAG_TYPE_STRING),
101 DRAG_TYPE ("STRING", DND_DRAG_TYPE_STRING),
104 static const GtkTargetEntry drag_types_source[] = {
105 DRAG_TYPE ("text/persona-id", DND_DRAG_TYPE_PERSONA_ID),
108 #undef DRAG_TYPE
110 static GdkAtom drag_atoms_dest[G_N_ELEMENTS (drag_types_dest)];
112 enum
114 DRAG_INDIVIDUAL_RECEIVED,
115 LAST_SIGNAL
118 static guint signals[LAST_SIGNAL];
120 G_DEFINE_TYPE (EmpathyPersonaView, empathy_persona_view, GTK_TYPE_TREE_VIEW);
122 static gboolean
123 filter_visible_func (GtkTreeModel *model,
124 GtkTreeIter *iter,
125 EmpathyPersonaView *self)
127 EmpathyPersonaViewPriv *priv = GET_PRIV (self);
128 gboolean is_online;
130 gtk_tree_model_get (model, iter,
131 EMPATHY_PERSONA_STORE_COL_IS_ONLINE, &is_online,
132 -1);
134 return (priv->show_offline || is_online);
137 static void
138 set_model (EmpathyPersonaView *self,
139 GtkTreeModel *model)
141 EmpathyPersonaViewPriv *priv = GET_PRIV (self);
143 tp_clear_object (&priv->filter);
145 priv->filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model,
146 NULL));
147 gtk_tree_model_filter_set_visible_func (priv->filter,
148 (GtkTreeModelFilterVisibleFunc) filter_visible_func, self, NULL);
150 gtk_tree_view_set_model (GTK_TREE_VIEW (self), GTK_TREE_MODEL (priv->filter));
153 static void
154 tooltip_destroy_cb (GtkWidget *widget,
155 EmpathyPersonaView *self)
157 EmpathyPersonaViewPriv *priv = GET_PRIV (self);
159 if (priv->tooltip_widget)
161 DEBUG ("Tooltip destroyed");
162 g_object_unref (priv->tooltip_widget);
163 priv->tooltip_widget = NULL;
167 static gboolean
168 query_tooltip_cb (EmpathyPersonaView *self,
169 gint x,
170 gint y,
171 gboolean keyboard_mode,
172 GtkTooltip *tooltip,
173 gpointer user_data)
175 EmpathyPersonaViewPriv *priv = GET_PRIV (self);
176 FolksPersona *persona;
177 EmpathyContact *contact;
178 GtkTreeModel *model;
179 GtkTreeIter iter;
180 GtkTreePath *path;
181 static gint running = 0;
182 gboolean ret = FALSE;
184 /* Avoid an infinite loop. See GNOME bug #574377 */
185 if (running > 0)
186 return FALSE;
187 running++;
189 if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (self), &x, &y,
190 keyboard_mode, &model, &path, &iter))
192 goto OUT;
195 gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (self), tooltip, path);
196 gtk_tree_path_free (path);
198 gtk_tree_model_get (model, &iter,
199 EMPATHY_PERSONA_STORE_COL_PERSONA, &persona,
200 -1);
201 if (persona == NULL)
202 goto OUT;
204 contact = empathy_contact_dup_from_tp_contact (tpf_persona_get_contact (
205 TPF_PERSONA (persona)));
207 if (priv->tooltip_widget == NULL)
209 priv->tooltip_widget = empathy_contact_widget_new (contact,
210 EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP |
211 EMPATHY_CONTACT_WIDGET_SHOW_LOCATION);
212 gtk_container_set_border_width (GTK_CONTAINER (priv->tooltip_widget), 8);
213 g_object_ref (priv->tooltip_widget);
214 g_signal_connect (priv->tooltip_widget, "destroy",
215 (GCallback) tooltip_destroy_cb, self);
216 gtk_widget_show (priv->tooltip_widget);
218 else
220 empathy_contact_widget_set_contact (priv->tooltip_widget, contact);
223 gtk_tooltip_set_custom (tooltip, priv->tooltip_widget);
224 ret = TRUE;
226 g_object_unref (contact);
227 g_object_unref (persona);
229 OUT:
230 running--;
232 return ret;
235 static void
236 cell_set_background (EmpathyPersonaView *self,
237 GtkCellRenderer *cell,
238 gboolean is_active)
240 if (is_active)
242 GdkRGBA color;
243 GtkStyleContext *style;
245 style = gtk_widget_get_style_context (GTK_WIDGET (self));
247 gtk_style_context_get_background_color (style, GTK_STATE_FLAG_SELECTED,
248 &color);
250 /* Here we take the current theme colour and add it to
251 * the colour for white and average the two. This
252 * gives a colour which is inline with the theme but
253 * slightly whiter.
255 empathy_make_color_whiter (&color);
257 g_object_set (cell, "cell-background-rgba", &color, NULL);
259 else
261 g_object_set (cell, "cell-background-rgba", NULL, NULL);
265 static void
266 pixbuf_cell_data_func (GtkTreeViewColumn *tree_column,
267 GtkCellRenderer *cell,
268 GtkTreeModel *model,
269 GtkTreeIter *iter,
270 EmpathyPersonaView *self)
272 GdkPixbuf *pixbuf;
273 gboolean is_active;
275 gtk_tree_model_get (model, iter,
276 EMPATHY_PERSONA_STORE_COL_IS_ACTIVE, &is_active,
277 EMPATHY_PERSONA_STORE_COL_ICON_STATUS, &pixbuf,
278 -1);
280 g_object_set (cell, "pixbuf", pixbuf, NULL);
281 tp_clear_object (&pixbuf);
283 cell_set_background (self, cell, is_active);
286 static void
287 audio_call_cell_data_func (GtkTreeViewColumn *tree_column,
288 GtkCellRenderer *cell,
289 GtkTreeModel *model,
290 GtkTreeIter *iter,
291 EmpathyPersonaView *self)
293 gboolean is_active;
294 gboolean can_audio, can_video;
296 gtk_tree_model_get (model, iter,
297 EMPATHY_PERSONA_STORE_COL_IS_ACTIVE, &is_active,
298 EMPATHY_PERSONA_STORE_COL_CAN_AUDIO_CALL, &can_audio,
299 EMPATHY_PERSONA_STORE_COL_CAN_VIDEO_CALL, &can_video,
300 -1);
302 g_object_set (cell,
303 "visible", (can_audio || can_video),
304 "icon-name", can_video? EMPATHY_IMAGE_VIDEO_CALL : EMPATHY_IMAGE_VOIP,
305 NULL);
307 cell_set_background (self, cell, is_active);
310 static void
311 avatar_cell_data_func (GtkTreeViewColumn *tree_column,
312 GtkCellRenderer *cell,
313 GtkTreeModel *model,
314 GtkTreeIter *iter,
315 EmpathyPersonaView *self)
317 GdkPixbuf *pixbuf;
318 gboolean show_avatar, is_active;
320 gtk_tree_model_get (model, iter,
321 EMPATHY_PERSONA_STORE_COL_PIXBUF_AVATAR, &pixbuf,
322 EMPATHY_PERSONA_STORE_COL_PIXBUF_AVATAR_VISIBLE, &show_avatar,
323 EMPATHY_PERSONA_STORE_COL_IS_ACTIVE, &is_active,
324 -1);
326 g_object_set (cell,
327 "visible", show_avatar,
328 "pixbuf", pixbuf,
329 NULL);
331 tp_clear_object (&pixbuf);
333 cell_set_background (self, cell, is_active);
336 static void
337 text_cell_data_func (GtkTreeViewColumn *tree_column,
338 GtkCellRenderer *cell,
339 GtkTreeModel *model,
340 GtkTreeIter *iter,
341 EmpathyPersonaView *self)
343 gboolean is_active;
345 gtk_tree_model_get (model, iter,
346 EMPATHY_PERSONA_STORE_COL_IS_ACTIVE, &is_active,
347 -1);
349 cell_set_background (self, cell, is_active);
352 static gboolean
353 individual_drag_received (EmpathyPersonaView *self,
354 GdkDragContext *context,
355 GtkSelectionData *selection)
357 EmpathyIndividualManager *manager = NULL;
358 FolksIndividual *individual;
359 const gchar *individual_id;
360 gboolean success = FALSE;
362 individual_id = (const gchar *) gtk_selection_data_get_data (selection);
363 manager = empathy_individual_manager_dup_singleton ();
364 individual = empathy_individual_manager_lookup_member (manager,
365 individual_id);
367 if (individual == NULL)
369 DEBUG ("Failed to find drag event individual with ID '%s'",
370 individual_id);
371 g_object_unref (manager);
372 return FALSE;
375 /* Emit a signal notifying of the drag. */
376 g_signal_emit (self, signals[DRAG_INDIVIDUAL_RECEIVED], 0,
377 gdk_drag_context_get_selected_action (context), individual, &success);
379 g_object_unref (manager);
381 return success;
384 static void
385 drag_data_received (GtkWidget *widget,
386 GdkDragContext *context,
387 gint x,
388 gint y,
389 GtkSelectionData *selection,
390 guint info,
391 guint time_)
393 EmpathyPersonaView *self = EMPATHY_PERSONA_VIEW (widget);
394 gboolean success = TRUE;
396 if (info == DND_DRAG_TYPE_INDIVIDUAL_ID || info == DND_DRAG_TYPE_STRING)
397 success = individual_drag_received (self, context, selection);
399 gtk_drag_finish (context, success, FALSE, GDK_CURRENT_TIME);
402 static gboolean
403 drag_motion (GtkWidget *widget,
404 GdkDragContext *context,
405 gint x,
406 gint y,
407 guint time_)
409 EmpathyPersonaView *self = EMPATHY_PERSONA_VIEW (widget);
410 GdkAtom target;
411 guint i;
412 DndDragType drag_type = DND_DRAG_TYPE_UNKNOWN;
414 target = gtk_drag_dest_find_target (GTK_WIDGET (self), context, NULL);
416 /* Determine the DndDragType of the data */
417 for (i = 0; i < G_N_ELEMENTS (drag_atoms_dest); i++)
419 if (target == drag_atoms_dest[i])
421 drag_type = drag_types_dest[i].info;
422 break;
426 if (drag_type == DND_DRAG_TYPE_INDIVIDUAL_ID)
428 GtkTreePath *path;
430 /* FIXME: It doesn't make sense for us to highlight a specific row or
431 * position to drop an Individual in, so just highlight the entire
432 * widget.
433 * Since I can't find a way to do this, just highlight the first possible
434 * position in the tree. */
435 gdk_drag_status (context, gdk_drag_context_get_suggested_action (context),
436 time_);
438 path = gtk_tree_path_new_first ();
439 gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (self), path,
440 GTK_TREE_VIEW_DROP_BEFORE);
441 gtk_tree_path_free (path);
443 return TRUE;
446 /* Unknown or unhandled drag target */
447 gdk_drag_status (context, GDK_ACTION_DEFAULT, time_);
448 gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (self), NULL, 0);
450 return FALSE;
453 static void
454 drag_data_get (GtkWidget *widget,
455 GdkDragContext *context,
456 GtkSelectionData *selection,
457 guint info,
458 guint time_)
460 EmpathyPersonaView *self = EMPATHY_PERSONA_VIEW (widget);
461 FolksPersona *persona;
462 const gchar *persona_uid;
464 if (info != DND_DRAG_TYPE_PERSONA_ID)
465 return;
467 persona = empathy_persona_view_dup_selected (self);
468 if (persona == NULL)
469 return;
471 persona_uid = folks_persona_get_uid (persona);
472 gtk_selection_data_set (selection,
473 gdk_atom_intern ("text/persona-id", FALSE), 8,
474 (guchar *) persona_uid, strlen (persona_uid) + 1);
476 g_object_unref (persona);
479 static gboolean
480 drag_drop (GtkWidget *widget,
481 GdkDragContext *drag_context,
482 gint x,
483 gint y,
484 guint time_)
486 return FALSE;
489 static void
490 set_features (EmpathyPersonaView *self,
491 EmpathyPersonaViewFeatureFlags features)
493 EmpathyPersonaViewPriv *priv = GET_PRIV (self);
495 priv->features = features;
497 /* Setting reorderable is a hack that gets us row previews as drag icons
498 for free. We override all the drag handlers. It's tricky to get the
499 position of the drag icon right in drag_begin. GtkTreeView has special
500 voodoo for it, so we let it do the voodoo that he do (but only if dragging
501 is enabled). */
502 gtk_tree_view_set_reorderable (GTK_TREE_VIEW (self),
503 (features & EMPATHY_PERSONA_VIEW_FEATURE_PERSONA_DRAG));
505 /* Update DnD source/dest */
506 if (features & EMPATHY_PERSONA_VIEW_FEATURE_PERSONA_DRAG)
508 gtk_drag_source_set (GTK_WIDGET (self),
509 GDK_BUTTON1_MASK,
510 drag_types_source,
511 G_N_ELEMENTS (drag_types_source),
512 GDK_ACTION_MOVE | GDK_ACTION_COPY);
514 else
516 gtk_drag_source_unset (GTK_WIDGET (self));
519 if (features & EMPATHY_PERSONA_VIEW_FEATURE_PERSONA_DROP)
521 gtk_drag_dest_set (GTK_WIDGET (self),
522 GTK_DEST_DEFAULT_ALL,
523 drag_types_dest,
524 G_N_ELEMENTS (drag_types_dest), GDK_ACTION_MOVE | GDK_ACTION_COPY);
526 else
528 gtk_drag_dest_unset (GTK_WIDGET (self));
531 g_object_notify (G_OBJECT (self), "features");
534 static void
535 empathy_persona_view_init (EmpathyPersonaView *self)
537 EmpathyPersonaViewPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
538 EMPATHY_TYPE_PERSONA_VIEW, EmpathyPersonaViewPriv);
540 self->priv = priv;
542 /* Connect to tree view signals rather than override. */
543 g_signal_connect (self, "query-tooltip", (GCallback) query_tooltip_cb, NULL);
546 static void
547 constructed (GObject *object)
549 EmpathyPersonaView *self = EMPATHY_PERSONA_VIEW (object);
550 GtkCellRenderer *cell;
551 GtkTreeViewColumn *col;
552 guint i;
554 /* Set up view */
555 g_object_set (self,
556 "headers-visible", FALSE,
557 "show-expanders", FALSE,
558 NULL);
560 col = gtk_tree_view_column_new ();
562 /* State */
563 cell = gtk_cell_renderer_pixbuf_new ();
564 gtk_tree_view_column_pack_start (col, cell, FALSE);
565 gtk_tree_view_column_set_cell_data_func (col, cell,
566 (GtkTreeCellDataFunc) pixbuf_cell_data_func, self, NULL);
568 g_object_set (cell,
569 "xpad", 5,
570 "ypad", 1,
571 "visible", TRUE,
572 NULL);
574 /* Name */
575 cell = empathy_cell_renderer_text_new ();
576 gtk_tree_view_column_pack_start (col, cell, TRUE);
577 gtk_tree_view_column_set_cell_data_func (col, cell,
578 (GtkTreeCellDataFunc) text_cell_data_func, self, NULL);
580 /* We (ab)use the name and status properties here to display display ID and
581 * account name, respectively. Harmless. */
582 gtk_tree_view_column_add_attribute (col, cell,
583 "name", EMPATHY_PERSONA_STORE_COL_DISPLAY_ID);
584 gtk_tree_view_column_add_attribute (col, cell,
585 "text", EMPATHY_PERSONA_STORE_COL_DISPLAY_ID);
586 gtk_tree_view_column_add_attribute (col, cell,
587 "presence-type", EMPATHY_PERSONA_STORE_COL_PRESENCE_TYPE);
588 gtk_tree_view_column_add_attribute (col, cell,
589 "status", EMPATHY_PERSONA_STORE_COL_ACCOUNT_NAME);
591 /* Audio Call Icon */
592 cell = empathy_cell_renderer_activatable_new ();
593 gtk_tree_view_column_pack_start (col, cell, FALSE);
594 gtk_tree_view_column_set_cell_data_func (col, cell,
595 (GtkTreeCellDataFunc) audio_call_cell_data_func, self, NULL);
597 g_object_set (cell,
598 "visible", FALSE,
599 NULL);
601 /* Avatar */
602 cell = gtk_cell_renderer_pixbuf_new ();
603 gtk_tree_view_column_pack_start (col, cell, FALSE);
604 gtk_tree_view_column_set_cell_data_func (col, cell,
605 (GtkTreeCellDataFunc) avatar_cell_data_func, self, NULL);
607 g_object_set (cell,
608 "xpad", 0,
609 "ypad", 0,
610 "visible", FALSE,
611 "width", 32,
612 "height", 32,
613 NULL);
615 /* Actually add the column now we have added all cell renderers */
616 gtk_tree_view_append_column (GTK_TREE_VIEW (self), col);
618 /* Drag & Drop. */
619 for (i = 0; i < G_N_ELEMENTS (drag_types_dest); ++i)
620 drag_atoms_dest[i] = gdk_atom_intern (drag_types_dest[i].target, FALSE);
623 static void
624 get_property (GObject *object,
625 guint param_id,
626 GValue *value,
627 GParamSpec *pspec)
629 EmpathyPersonaViewPriv *priv = GET_PRIV (object);
631 switch (param_id)
633 case PROP_MODEL:
634 g_value_set_object (value, priv->filter);
635 break;
636 case PROP_SHOW_OFFLINE:
637 g_value_set_boolean (value, priv->show_offline);
638 break;
639 case PROP_FEATURES:
640 g_value_set_flags (value, priv->features);
641 break;
642 default:
643 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
644 break;
648 static void
649 set_property (GObject *object,
650 guint param_id,
651 const GValue *value,
652 GParamSpec *pspec)
654 EmpathyPersonaView *self = EMPATHY_PERSONA_VIEW (object);
656 switch (param_id)
658 case PROP_MODEL:
659 set_model (self, g_value_get_object (value));
660 break;
661 case PROP_SHOW_OFFLINE:
662 empathy_persona_view_set_show_offline (self,
663 g_value_get_boolean (value));
664 break;
665 case PROP_FEATURES:
666 set_features (self, g_value_get_flags (value));
667 break;
668 default:
669 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
670 break;
674 static void
675 dispose (GObject *object)
677 EmpathyPersonaView *self = EMPATHY_PERSONA_VIEW (object);
678 EmpathyPersonaViewPriv *priv = GET_PRIV (self);
680 tp_clear_object (&priv->filter);
682 if (priv->tooltip_widget)
683 gtk_widget_destroy (priv->tooltip_widget);
684 priv->tooltip_widget = NULL;
686 G_OBJECT_CLASS (empathy_persona_view_parent_class)->dispose (object);
689 static void
690 empathy_persona_view_class_init (EmpathyPersonaViewClass *klass)
692 GObjectClass *object_class = G_OBJECT_CLASS (klass);
693 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
695 object_class->constructed = constructed;
696 object_class->dispose = dispose;
697 object_class->get_property = get_property;
698 object_class->set_property = set_property;
700 widget_class->drag_data_received = drag_data_received;
701 widget_class->drag_drop = drag_drop;
702 widget_class->drag_data_get = drag_data_get;
703 widget_class->drag_motion = drag_motion;
705 signals[DRAG_INDIVIDUAL_RECEIVED] =
706 g_signal_new ("drag-individual-received",
707 G_OBJECT_CLASS_TYPE (klass),
708 G_SIGNAL_RUN_LAST,
709 G_STRUCT_OFFSET (EmpathyPersonaViewClass, drag_individual_received),
710 NULL, NULL,
711 _empathy_gtk_marshal_BOOLEAN__UINT_OBJECT,
712 G_TYPE_BOOLEAN, 2, G_TYPE_UINT, FOLKS_TYPE_INDIVIDUAL);
714 /* We override the "model" property so that we can wrap it in a
715 * GtkTreeModelFilter for showing/hiding offline personas. */
716 g_object_class_override_property (object_class, PROP_MODEL, "model");
719 * EmpathyPersonaStore:show-offline:
721 * Whether to display offline personas.
723 g_object_class_install_property (object_class, PROP_SHOW_OFFLINE,
724 g_param_spec_boolean ("show-offline",
725 "Show Offline",
726 "Whether to display offline personas.",
727 FALSE,
728 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
731 * EmpathyPersonaStore:features:
733 * Features of the view, such as whether drag and drop is enabled.
735 g_object_class_install_property (object_class, PROP_FEATURES,
736 g_param_spec_flags ("features",
737 "Features",
738 "Flags for all enabled features.",
739 EMPATHY_TYPE_PERSONA_VIEW_FEATURE_FLAGS,
740 EMPATHY_PERSONA_VIEW_FEATURE_NONE,
741 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
743 g_type_class_add_private (object_class, sizeof (EmpathyPersonaViewPriv));
747 * empathy_persona_view_new:
748 * @store: an #EmpathyPersonaStore
749 * @features: a set of flags specifying the view's functionality, or
750 * %EMPATHY_PERSONA_VIEW_FEATURE_NONE
752 * Create a new #EmpathyPersonaView displaying the personas in
753 * #EmpathyPersonaStore.
755 * Return value: a new #EmpathyPersonaView
757 EmpathyPersonaView *
758 empathy_persona_view_new (EmpathyPersonaStore *store,
759 EmpathyPersonaViewFeatureFlags features)
761 g_return_val_if_fail (EMPATHY_IS_PERSONA_STORE (store), NULL);
763 return g_object_new (EMPATHY_TYPE_PERSONA_VIEW,
764 "model", store,
765 "features", features,
766 NULL);
770 * empathy_persona_view_dup_selected:
771 * @self: an #EmpathyPersonaView
773 * Return the #FolksPersona associated with the currently selected row. The
774 * persona is referenced before being returned. If no row is selected, %NULL is
775 * returned.
777 * Return value: the currently selected #FolksPersona, or %NULL; unref with
778 * g_object_unref()
780 FolksPersona *
781 empathy_persona_view_dup_selected (EmpathyPersonaView *self)
783 GtkTreeSelection *selection;
784 GtkTreeIter iter;
785 GtkTreeModel *model;
786 FolksPersona *persona;
788 g_return_val_if_fail (EMPATHY_IS_PERSONA_VIEW (self), NULL);
790 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self));
791 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
792 return NULL;
794 gtk_tree_model_get (model, &iter,
795 EMPATHY_PERSONA_STORE_COL_PERSONA, &persona,
796 -1);
798 return persona;
802 * empathy_persona_view_get_show_offline:
803 * @self: an #EmpathyPersonaView
805 * Get the value of the #EmpathyPersonaView:show-offline property.
807 * Return value: %TRUE if offline personas are being shown, %FALSE otherwise
809 gboolean
810 empathy_persona_view_get_show_offline (EmpathyPersonaView *self)
812 g_return_val_if_fail (EMPATHY_IS_PERSONA_VIEW (self), FALSE);
814 return GET_PRIV (self)->show_offline;
818 * empathy_persona_view_set_show_offline:
819 * @self: an #EmpathyPersonaView
820 * @show_offline: %TRUE to show personas which are offline, %FALSE otherwise
822 * Set the #EmpathyPersonaView:show-offline property to @show_offline.
824 void
825 empathy_persona_view_set_show_offline (EmpathyPersonaView *self,
826 gboolean show_offline)
828 EmpathyPersonaViewPriv *priv;
830 g_return_if_fail (EMPATHY_IS_PERSONA_VIEW (self));
832 priv = GET_PRIV (self);
833 priv->show_offline = show_offline;
835 gtk_tree_model_filter_refilter (priv->filter);
837 g_object_notify (G_OBJECT (self), "show-offline");