1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2007-2010 Collabora Ltd.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library 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 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Authors: Xavier Claessens <xclaesse@gmail.com>
20 * Philip Withnall <philip.withnall@collabora.co.uk>
21 * Travis Reitter <travis.reitter@collabora.co.uk>
30 #include <glib/gi18n-lib.h>
31 #include <gio/gdesktopappinfo.h>
33 #include <telepathy-glib/telepathy-glib.h>
34 #include <folks/folks.h>
35 #include <folks/folks-telepathy.h>
37 #include <libempathy/empathy-individual-manager.h>
38 #include <libempathy/empathy-utils.h>
39 #include <libempathy/empathy-pkg-kit.h>
41 #include "empathy-individual-information-dialog.h"
42 #include "empathy-individual-widget.h"
43 #include "empathy-ui-utils.h"
45 #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
46 #include <libempathy/empathy-debug.h>
48 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIndividualInformationDialog)
50 FolksIndividual
*individual
;
51 GtkWidget
*individual_widget
; /* child widget */
52 GtkWidget
*label
; /* child widget */
53 } EmpathyIndividualInformationDialogPriv
;
60 /* Info dialogs currently open.
61 * Each dialog contains a referenced pointer to its Individual */
62 static GList
*information_dialogs
= NULL
;
64 static void individual_information_dialog_set_individual (
65 EmpathyIndividualInformationDialog
*dialog
,
66 FolksIndividual
*individual
);
68 G_DEFINE_TYPE (EmpathyIndividualInformationDialog
,
69 empathy_individual_information_dialog
, GTK_TYPE_DIALOG
);
72 individual_dialogs_response_cb (GtkDialog
*dialog
,
76 *dialogs
= g_list_remove (*dialogs
, dialog
);
77 gtk_widget_destroy (GTK_WIDGET (dialog
));
81 individual_dialogs_find (GObject
*object
,
82 FolksIndividual
*individual
)
84 EmpathyIndividualInformationDialogPriv
*priv
= GET_PRIV (object
);
86 return individual
!= priv
->individual
;
90 empathy_individual_information_dialog_show (FolksIndividual
*individual
,
96 g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual
));
97 g_return_if_fail (parent
== NULL
|| GTK_IS_WINDOW (parent
));
99 l
= g_list_find_custom (information_dialogs
, individual
,
100 (GCompareFunc
) individual_dialogs_find
);
104 gtk_window_present (GTK_WINDOW (l
->data
));
109 dialog
= g_object_new (EMPATHY_TYPE_INDIVIDUAL_INFORMATION_DIALOG
,
110 "individual", individual
,
113 information_dialogs
= g_list_prepend (information_dialogs
, dialog
);
114 gtk_widget_show (dialog
);
118 individual_removed_cb (FolksIndividual
*individual
,
119 FolksIndividual
*replacement_individual
,
120 EmpathyIndividualInformationDialog
*self
)
122 individual_information_dialog_set_individual (self
,
123 replacement_individual
);
125 /* Destroy the dialogue */
126 if (replacement_individual
== NULL
)
128 individual_dialogs_response_cb (GTK_DIALOG (self
),
129 GTK_RESPONSE_DELETE_EVENT
, &information_dialogs
);
134 set_label_visibility (EmpathyIndividualInformationDialog
*dialog
)
136 EmpathyIndividualInformationDialogPriv
*priv
= GET_PRIV (dialog
);
137 guint num_personas
= 0;
139 /* Count how many Telepathy personas we have, to see whether we can
141 if (priv
->individual
!= NULL
)
146 personas
= folks_individual_get_personas (priv
->individual
);
147 iter
= gee_iterable_iterator (GEE_ITERABLE (personas
));
148 while (gee_iterator_next (iter
))
150 FolksPersona
*persona
= gee_iterator_get (iter
);
151 if (empathy_folks_persona_is_interesting (persona
))
154 g_clear_object (&persona
);
156 g_clear_object (&iter
);
159 /* Only make the label visible if we have enough personas */
160 gtk_widget_set_visible (priv
->label
, (num_personas
> 1) ? TRUE
: FALSE
);
164 individual_information_dialog_set_individual (
165 EmpathyIndividualInformationDialog
*dialog
,
166 FolksIndividual
*individual
)
168 EmpathyIndividualInformationDialogPriv
*priv
;
170 g_return_if_fail (EMPATHY_INDIVIDUAL_INFORMATION_DIALOG (dialog
));
171 g_return_if_fail (individual
== NULL
|| FOLKS_IS_INDIVIDUAL (individual
));
173 priv
= GET_PRIV (dialog
);
175 /* Remove the old Individual */
176 if (priv
->individual
!= NULL
)
178 g_signal_handlers_disconnect_by_func (priv
->individual
,
179 (GCallback
) individual_removed_cb
, dialog
);
182 tp_clear_object (&priv
->individual
);
184 /* Add the new Individual */
185 priv
->individual
= individual
;
187 if (individual
!= NULL
)
189 g_object_ref (individual
);
190 g_signal_connect (individual
, "removed",
191 (GCallback
) individual_removed_cb
, dialog
);
194 gtk_window_set_title (GTK_WINDOW (dialog
),
195 folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual
)));
196 empathy_individual_widget_set_individual (
197 EMPATHY_INDIVIDUAL_WIDGET (priv
->individual_widget
), individual
);
198 set_label_visibility (dialog
);
203 individual_information_dialog_get_property (GObject
*object
,
208 EmpathyIndividualInformationDialogPriv
*priv
= GET_PRIV (object
);
211 case PROP_INDIVIDUAL
:
212 g_value_set_object (value
, priv
->individual
);
215 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
221 individual_information_dialog_set_property (GObject
*object
,
226 EmpathyIndividualInformationDialog
*dialog
=
227 EMPATHY_INDIVIDUAL_INFORMATION_DIALOG (object
);
230 case PROP_INDIVIDUAL
:
231 individual_information_dialog_set_individual (dialog
,
232 FOLKS_INDIVIDUAL (g_value_get_object (value
)));
235 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
241 individual_information_dialog_dispose (GObject
*object
)
243 individual_information_dialog_set_individual (
244 EMPATHY_INDIVIDUAL_INFORMATION_DIALOG (object
), NULL
);
247 empathy_individual_information_dialog_parent_class
)->dispose (object
);
251 empathy_individual_information_dialog_class_init (
252 EmpathyIndividualInformationDialogClass
*klass
)
254 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
256 object_class
->dispose
= individual_information_dialog_dispose
;
257 object_class
->get_property
= individual_information_dialog_get_property
;
258 object_class
->set_property
= individual_information_dialog_set_property
;
260 g_object_class_install_property (object_class
,
262 g_param_spec_object ("individual",
264 "Folks Individual to base the dialog upon",
265 FOLKS_TYPE_INDIVIDUAL
,
268 G_PARAM_STATIC_STRINGS
));
270 g_type_class_add_private (object_class
,
271 sizeof (EmpathyIndividualInformationDialogPriv
));
275 empathy_individual_information_dialog_init (
276 EmpathyIndividualInformationDialog
*dialog
)
279 GtkBox
*content_area
;
281 EmpathyIndividualInformationDialogPriv
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (
282 dialog
, EMPATHY_TYPE_INDIVIDUAL_INFORMATION_DIALOG
,
283 EmpathyIndividualInformationDialogPriv
);
286 priv
->individual
= NULL
;
288 gtk_window_set_resizable (GTK_WINDOW (dialog
), TRUE
);
290 content_area
= GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog
)));
292 /* Translators: the heading at the top of the Information dialogue */
293 label_string
= g_strdup_printf ("<b>%s</b>", _("Linked Contacts"));
294 priv
->label
= gtk_label_new (NULL
);
295 gtk_label_set_markup (GTK_LABEL (priv
->label
), label_string
);
296 g_free (label_string
);
298 gtk_misc_set_alignment (GTK_MISC (priv
->label
), 0.0, 0.5);
299 gtk_misc_set_padding (GTK_MISC (priv
->label
), 6, 6);
300 gtk_box_pack_start (content_area
, priv
->label
, FALSE
, TRUE
, 0);
301 gtk_widget_show (priv
->label
);
303 /* Individual widget */
304 priv
->individual_widget
= empathy_individual_widget_new (priv
->individual
,
305 EMPATHY_INDIVIDUAL_WIDGET_SHOW_LOCATION
|
306 EMPATHY_INDIVIDUAL_WIDGET_SHOW_DETAILS
|
307 EMPATHY_INDIVIDUAL_WIDGET_SHOW_PERSONAS
);
308 gtk_container_set_border_width (GTK_CONTAINER (priv
->individual_widget
), 6);
309 gtk_box_pack_start (content_area
, priv
->individual_widget
, TRUE
, TRUE
, 0);
310 gtk_widget_show (priv
->individual_widget
);
313 button
= gtk_button_new_with_label (GTK_STOCK_CLOSE
);
314 gtk_button_set_use_stock (GTK_BUTTON (button
), TRUE
);
315 gtk_dialog_add_action_widget (GTK_DIALOG (dialog
), button
,
317 gtk_widget_set_can_default (button
, TRUE
);
318 gtk_window_set_default (GTK_WINDOW (dialog
), button
);
319 gtk_widget_show (button
);
321 g_signal_connect (dialog
, "response",
322 G_CALLBACK (individual_dialogs_response_cb
), &information_dialogs
);
326 show_gnome_contacts_error_dialog (void)
330 dialog
= gtk_message_dialog_new (NULL
, GTK_DIALOG_MODAL
,
331 GTK_MESSAGE_ERROR
, GTK_BUTTONS_CLOSE
,
332 _("gnome-contacts not installed"));
334 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog
),
335 _("Please install gnome-contacts to access contacts details."));
337 g_signal_connect_swapped (dialog
, "response",
338 G_CALLBACK (gtk_widget_destroy
), dialog
);
340 gtk_widget_show (dialog
);
344 start_gnome_contacts (FolksIndividual
*individual
,
345 gboolean try_installing
);
348 install_gnome_contacts_cb (GObject
*source
,
349 GAsyncResult
*result
,
352 FolksIndividual
*individual
= user_data
;
353 GError
*error
= NULL
;
355 if (!empathy_pkg_kit_install_packages_finish (result
, &error
))
357 DEBUG ("Failed to install gnome-contacts: %s", error
->message
);
358 g_error_free (error
);
360 show_gnome_contacts_error_dialog ();
364 DEBUG ("gnome-contacts installed");
366 start_gnome_contacts (individual
, FALSE
);
369 g_object_unref (individual
);
373 start_gnome_contacts (FolksIndividual
*individual
,
374 gboolean try_installing
)
377 GError
*error
= NULL
;
379 g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual
));
381 args
= g_strdup_printf ("-i %s", folks_individual_get_id (individual
));
383 if (!empathy_launch_external_app ("gnome-contacts.desktop", args
, &error
))
385 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
))
389 const gchar
*packages
[] = { "gnome-contacts", NULL
};
391 DEBUG ("gnome-contacts not installed; try to install it");
393 empathy_pkg_kit_install_packages_async (0, packages
, NULL
,
394 NULL
, install_gnome_contacts_cb
, g_object_ref (individual
));
398 show_gnome_contacts_error_dialog ();
406 /* Use gnome-contacts to display @individual or fallback to
407 * EmpathyIndividualInformationDialog if user is not not in Folks.
410 empathy_display_individual_info (FolksIndividual
*individual
)
412 EmpathyIndividualManager
*mgr
;
414 mgr
= empathy_individual_manager_dup_singleton ();
416 /* Only use gnome-contacts if that's a 'real' individual we got from
417 * Folks (and so the individual manager knows about it). If not that's a
418 * MUC contact and we use the simple dialog. */
419 if (empathy_individual_manager_lookup_member (mgr
,
420 folks_individual_get_id (individual
)) != NULL
)
422 start_gnome_contacts (individual
, TRUE
);
426 empathy_individual_information_dialog_show (individual
, NULL
);
429 g_object_unref (mgr
);