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>
25 #include "empathy-individual-information-dialog.h"
27 #include <glib/gi18n-lib.h>
29 #include "empathy-individual-manager.h"
30 #include "empathy-individual-widget.h"
31 #include "empathy-pkg-kit.h"
32 #include "empathy-ui-utils.h"
33 #include "empathy-utils.h"
35 #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
36 #include "empathy-debug.h"
38 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIndividualInformationDialog)
40 FolksIndividual
*individual
;
41 GtkWidget
*individual_widget
; /* child widget */
42 GtkWidget
*label
; /* child widget */
43 } EmpathyIndividualInformationDialogPriv
;
50 /* Info dialogs currently open.
51 * Each dialog contains a referenced pointer to its Individual */
52 static GList
*information_dialogs
= NULL
;
54 static void individual_information_dialog_set_individual (
55 EmpathyIndividualInformationDialog
*dialog
,
56 FolksIndividual
*individual
);
58 G_DEFINE_TYPE (EmpathyIndividualInformationDialog
,
59 empathy_individual_information_dialog
, GTK_TYPE_DIALOG
);
62 individual_dialogs_response_cb (GtkDialog
*dialog
,
66 *dialogs
= g_list_remove (*dialogs
, dialog
);
67 gtk_widget_destroy (GTK_WIDGET (dialog
));
71 individual_dialogs_find (GObject
*object
,
72 FolksIndividual
*individual
)
74 EmpathyIndividualInformationDialogPriv
*priv
= GET_PRIV (object
);
76 return individual
!= priv
->individual
;
80 empathy_individual_information_dialog_show (FolksIndividual
*individual
,
86 g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual
));
87 g_return_if_fail (parent
== NULL
|| GTK_IS_WINDOW (parent
));
89 l
= g_list_find_custom (information_dialogs
, individual
,
90 (GCompareFunc
) individual_dialogs_find
);
94 gtk_window_present (GTK_WINDOW (l
->data
));
99 dialog
= g_object_new (EMPATHY_TYPE_INDIVIDUAL_INFORMATION_DIALOG
,
100 "individual", individual
,
103 information_dialogs
= g_list_prepend (information_dialogs
, dialog
);
104 gtk_widget_show (dialog
);
108 individual_removed_cb (FolksIndividual
*individual
,
109 FolksIndividual
*replacement_individual
,
110 EmpathyIndividualInformationDialog
*self
)
112 individual_information_dialog_set_individual (self
,
113 replacement_individual
);
115 /* Destroy the dialogue */
116 if (replacement_individual
== NULL
)
118 individual_dialogs_response_cb (GTK_DIALOG (self
),
119 GTK_RESPONSE_DELETE_EVENT
, &information_dialogs
);
124 set_label_visibility (EmpathyIndividualInformationDialog
*dialog
)
126 EmpathyIndividualInformationDialogPriv
*priv
= GET_PRIV (dialog
);
127 guint num_personas
= 0;
129 /* Count how many Telepathy personas we have, to see whether we can
131 if (priv
->individual
!= NULL
)
136 personas
= folks_individual_get_personas (priv
->individual
);
137 iter
= gee_iterable_iterator (GEE_ITERABLE (personas
));
138 while (gee_iterator_next (iter
))
140 FolksPersona
*persona
= gee_iterator_get (iter
);
141 if (empathy_folks_persona_is_interesting (persona
))
144 g_clear_object (&persona
);
146 g_clear_object (&iter
);
149 /* Only make the label visible if we have enough personas */
150 gtk_widget_set_visible (priv
->label
, (num_personas
> 1) ? TRUE
: FALSE
);
154 individual_information_dialog_set_individual (
155 EmpathyIndividualInformationDialog
*dialog
,
156 FolksIndividual
*individual
)
158 EmpathyIndividualInformationDialogPriv
*priv
;
160 g_return_if_fail (EMPATHY_INDIVIDUAL_INFORMATION_DIALOG (dialog
));
161 g_return_if_fail (individual
== NULL
|| FOLKS_IS_INDIVIDUAL (individual
));
163 priv
= GET_PRIV (dialog
);
165 /* Remove the old Individual */
166 if (priv
->individual
!= NULL
)
168 g_signal_handlers_disconnect_by_func (priv
->individual
,
169 (GCallback
) individual_removed_cb
, dialog
);
172 tp_clear_object (&priv
->individual
);
174 /* Add the new Individual */
175 priv
->individual
= individual
;
177 if (individual
!= NULL
)
179 g_object_ref (individual
);
180 g_signal_connect (individual
, "removed",
181 (GCallback
) individual_removed_cb
, dialog
);
184 gtk_window_set_title (GTK_WINDOW (dialog
),
185 folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual
)));
186 empathy_individual_widget_set_individual (
187 EMPATHY_INDIVIDUAL_WIDGET (priv
->individual_widget
), individual
);
188 set_label_visibility (dialog
);
193 individual_information_dialog_get_property (GObject
*object
,
198 EmpathyIndividualInformationDialogPriv
*priv
= GET_PRIV (object
);
201 case PROP_INDIVIDUAL
:
202 g_value_set_object (value
, priv
->individual
);
205 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
211 individual_information_dialog_set_property (GObject
*object
,
216 EmpathyIndividualInformationDialog
*dialog
=
217 EMPATHY_INDIVIDUAL_INFORMATION_DIALOG (object
);
220 case PROP_INDIVIDUAL
:
221 individual_information_dialog_set_individual (dialog
,
222 FOLKS_INDIVIDUAL (g_value_get_object (value
)));
225 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
231 individual_information_dialog_dispose (GObject
*object
)
233 individual_information_dialog_set_individual (
234 EMPATHY_INDIVIDUAL_INFORMATION_DIALOG (object
), NULL
);
237 empathy_individual_information_dialog_parent_class
)->dispose (object
);
241 empathy_individual_information_dialog_class_init (
242 EmpathyIndividualInformationDialogClass
*klass
)
244 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
246 object_class
->dispose
= individual_information_dialog_dispose
;
247 object_class
->get_property
= individual_information_dialog_get_property
;
248 object_class
->set_property
= individual_information_dialog_set_property
;
250 g_object_class_install_property (object_class
,
252 g_param_spec_object ("individual",
254 "Folks Individual to base the dialog upon",
255 FOLKS_TYPE_INDIVIDUAL
,
258 G_PARAM_STATIC_STRINGS
));
260 g_type_class_add_private (object_class
,
261 sizeof (EmpathyIndividualInformationDialogPriv
));
265 empathy_individual_information_dialog_init (
266 EmpathyIndividualInformationDialog
*dialog
)
269 GtkBox
*content_area
;
271 EmpathyIndividualInformationDialogPriv
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (
272 dialog
, EMPATHY_TYPE_INDIVIDUAL_INFORMATION_DIALOG
,
273 EmpathyIndividualInformationDialogPriv
);
276 priv
->individual
= NULL
;
278 gtk_window_set_resizable (GTK_WINDOW (dialog
), TRUE
);
280 content_area
= GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog
)));
282 /* Translators: the heading at the top of the Information dialogue */
283 label_string
= g_strdup_printf ("<b>%s</b>", _("Linked Contacts"));
284 priv
->label
= gtk_label_new (NULL
);
285 gtk_label_set_markup (GTK_LABEL (priv
->label
), label_string
);
286 g_free (label_string
);
288 gtk_misc_set_alignment (GTK_MISC (priv
->label
), 0.0, 0.5);
289 gtk_misc_set_padding (GTK_MISC (priv
->label
), 6, 6);
290 gtk_box_pack_start (content_area
, priv
->label
, FALSE
, TRUE
, 0);
291 gtk_widget_show (priv
->label
);
293 /* Individual widget */
294 priv
->individual_widget
= empathy_individual_widget_new (priv
->individual
,
295 EMPATHY_INDIVIDUAL_WIDGET_SHOW_LOCATION
|
296 EMPATHY_INDIVIDUAL_WIDGET_SHOW_DETAILS
|
297 EMPATHY_INDIVIDUAL_WIDGET_SHOW_PERSONAS
);
298 gtk_container_set_border_width (GTK_CONTAINER (priv
->individual_widget
), 6);
299 gtk_box_pack_start (content_area
, priv
->individual_widget
, TRUE
, TRUE
, 0);
300 gtk_widget_show (priv
->individual_widget
);
303 button
= gtk_button_new_with_label (GTK_STOCK_CLOSE
);
304 gtk_button_set_use_stock (GTK_BUTTON (button
), TRUE
);
305 gtk_dialog_add_action_widget (GTK_DIALOG (dialog
), button
,
307 gtk_widget_set_can_default (button
, TRUE
);
308 gtk_window_set_default (GTK_WINDOW (dialog
), button
);
309 gtk_widget_show (button
);
311 g_signal_connect (dialog
, "response",
312 G_CALLBACK (individual_dialogs_response_cb
), &information_dialogs
);
316 show_gnome_contacts_error_dialog (void)
320 dialog
= gtk_message_dialog_new (NULL
, GTK_DIALOG_MODAL
,
321 GTK_MESSAGE_ERROR
, GTK_BUTTONS_CLOSE
,
322 _("gnome-contacts not installed"));
324 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog
),
325 _("Please install gnome-contacts to access contacts details."));
327 g_signal_connect_swapped (dialog
, "response",
328 G_CALLBACK (gtk_widget_destroy
), dialog
);
330 gtk_widget_show (dialog
);
334 start_gnome_contacts (FolksIndividual
*individual
,
335 gboolean try_installing
);
338 install_gnome_contacts_cb (GObject
*source
,
339 GAsyncResult
*result
,
342 FolksIndividual
*individual
= user_data
;
343 GError
*error
= NULL
;
345 if (!empathy_pkg_kit_install_packages_finish (result
, &error
))
347 DEBUG ("Failed to install gnome-contacts: %s", error
->message
);
348 g_error_free (error
);
350 show_gnome_contacts_error_dialog ();
354 DEBUG ("gnome-contacts installed");
356 start_gnome_contacts (individual
, FALSE
);
359 g_object_unref (individual
);
363 start_gnome_contacts (FolksIndividual
*individual
,
364 gboolean try_installing
)
367 GError
*error
= NULL
;
369 g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual
));
371 args
= g_strdup_printf ("-i %s", folks_individual_get_id (individual
));
373 /* First try the old desktop name */
374 if (empathy_launch_external_app ("gnome-contacts.desktop", args
, NULL
))
377 if (!empathy_launch_external_app ("org.gnome.Contacts.desktop", args
, &error
))
379 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
))
383 const gchar
*packages
[] = { "gnome-contacts", NULL
};
385 DEBUG ("gnome-contacts not installed; try to install it");
387 empathy_pkg_kit_install_packages_async (0, packages
, NULL
,
388 NULL
, install_gnome_contacts_cb
, g_object_ref (individual
));
392 show_gnome_contacts_error_dialog ();
401 /* Use gnome-contacts to display @individual or fallback to
402 * EmpathyIndividualInformationDialog if user is not not in Folks.
405 empathy_display_individual_info (FolksIndividual
*individual
)
407 EmpathyIndividualManager
*mgr
;
409 mgr
= empathy_individual_manager_dup_singleton ();
411 /* Only use gnome-contacts if that's a 'real' individual we got from
412 * Folks (and so the individual manager knows about it). If not that's a
413 * MUC contact and we use the simple dialog. */
414 if (empathy_individual_manager_lookup_member (mgr
,
415 folks_individual_get_id (individual
)) != NULL
)
417 start_gnome_contacts (individual
, TRUE
);
421 empathy_individual_information_dialog_show (individual
, NULL
);
424 g_object_unref (mgr
);