]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-individual-edit-dialog.c
Update the Edit dialogue on contact linking or unlinking
[empathy.git] / libempathy-gtk / empathy-individual-edit-dialog.c
1 /*
2  * Copyright (C) 2007-2010 Collabora Ltd.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Authors: Xavier Claessens <xclaesse@gmail.com>
19  *          Philip Withnall <philip.withnall@collabora.co.uk>
20  *          Travis Reitter <travis.reitter@collabora.co.uk>
21  */
22
23 #include <config.h>
24
25 #include <string.h>
26 #include <stdlib.h>
27
28 #include <gtk/gtk.h>
29 #include <glib/gi18n-lib.h>
30
31 #include <telepathy-glib/util.h>
32 #include <folks/folks.h>
33 #include <folks/folks-telepathy.h>
34
35 #include <libempathy/empathy-individual-manager.h>
36 #include <libempathy/empathy-utils.h>
37
38 #include "empathy-individual-edit-dialog.h"
39 #include "empathy-individual-widget.h"
40 #include "empathy-ui-utils.h"
41
42 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIndividualEditDialog)
43
44 typedef struct {
45   FolksIndividual *individual; /* owned */
46   GtkWidget *individual_widget; /* child widget */
47 } EmpathyIndividualEditDialogPriv;
48
49 enum {
50   PROP_INDIVIDUAL = 1,
51 };
52
53 /* Edit dialogs currently open.
54  * Each dialog contains a referenced pointer to its Individual */
55 static GList *edit_dialogs = NULL;
56
57 static void individual_edit_dialog_set_individual (
58     EmpathyIndividualEditDialog *dialog,
59     FolksIndividual *individual);
60
61 G_DEFINE_TYPE (EmpathyIndividualEditDialog, empathy_individual_edit_dialog,
62     GTK_TYPE_DIALOG);
63
64 /* Fairly arbitrary response ID for the "Unlink" button */
65 #define RESPONSE_UNLINK 5
66
67 static void
68 individual_dialogs_response_cb (GtkDialog *dialog,
69     gint response,
70     GList **dialogs)
71 {
72   if (response == RESPONSE_UNLINK)
73     {
74       EmpathyIndividualEditDialogPriv *priv = GET_PRIV (dialog);
75       EmpathyIndividualManager *manager =
76           empathy_individual_manager_dup_singleton ();
77
78       empathy_individual_manager_unlink_individual (manager, priv->individual);
79
80       g_object_unref (manager);
81     }
82
83   *dialogs = g_list_remove (*dialogs, dialog);
84   gtk_widget_destroy (GTK_WIDGET (dialog));
85 }
86
87 static gint
88 individual_dialogs_find (GObject *object,
89     FolksIndividual *individual)
90 {
91   EmpathyIndividualEditDialogPriv *priv = GET_PRIV (object);
92
93   return individual != priv->individual;
94 }
95
96 void
97 empathy_individual_edit_dialog_show (FolksIndividual *individual,
98     GtkWindow *parent)
99 {
100   GtkWidget *dialog;
101   GList *l;
102
103   g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual));
104   g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
105
106   l = g_list_find_custom (edit_dialogs, individual,
107       (GCompareFunc) individual_dialogs_find);
108
109   if (l != NULL)
110     {
111       gtk_window_present (GTK_WINDOW (l->data));
112       return;
113     }
114
115   /* Create dialog */
116   dialog = g_object_new (EMPATHY_TYPE_INDIVIDUAL_EDIT_DIALOG,
117       "individual", individual,
118       NULL);
119
120   edit_dialogs = g_list_prepend (edit_dialogs, dialog);
121   gtk_widget_show (dialog);
122 }
123
124 static void
125 set_unlink_button_sensitivity (EmpathyIndividualEditDialog *self)
126 {
127   EmpathyIndividualEditDialogPriv *priv = GET_PRIV (self);
128   GList *personas, *l;
129   guint num_personas = 0;
130
131   /* Count how many Telepathy personas we have, to see whether we can
132    * unlink */
133   if (priv->individual != NULL)
134     {
135       personas = folks_individual_get_personas (priv->individual);
136       for (l = personas; l != NULL; l = l->next)
137         {
138           if (TPF_IS_PERSONA (l->data))
139             num_personas++;
140         }
141     }
142
143   /* Only make the "Unlink" button sensitive if we have enough personas */
144   gtk_dialog_set_response_sensitive (GTK_DIALOG (self), RESPONSE_UNLINK,
145       (num_personas > 1) ? TRUE : FALSE);
146 }
147
148 static void
149 individual_removed_cb (FolksIndividual *individual,
150     FolksIndividual *replacement_individual,
151     EmpathyIndividualEditDialog *self)
152 {
153   /* Update to show the new Individual (this will close the dialogue if there
154    * is no new Individual). */
155   individual_edit_dialog_set_individual (self, replacement_individual);
156
157   /* Destroy the dialogue */
158   if (replacement_individual == NULL)
159     {
160       individual_dialogs_response_cb (GTK_DIALOG (self),
161           GTK_RESPONSE_DELETE_EVENT, &edit_dialogs);
162     }
163 }
164
165 static void
166 individual_edit_dialog_set_individual (
167     EmpathyIndividualEditDialog *dialog,
168     FolksIndividual *individual)
169 {
170   EmpathyIndividualEditDialogPriv *priv;
171
172   g_return_if_fail (EMPATHY_INDIVIDUAL_EDIT_DIALOG (dialog));
173   g_return_if_fail (individual == NULL || FOLKS_IS_INDIVIDUAL (individual));
174
175   priv = GET_PRIV (dialog);
176
177   /* Remove the old Individual */
178   if (priv->individual != NULL)
179     {
180       g_signal_handlers_disconnect_by_func (priv->individual,
181           (GCallback) individual_removed_cb, dialog);
182     }
183
184   tp_clear_object (&priv->individual);
185
186   /* Add the new Individual */
187   priv->individual = individual;
188
189   if (individual != NULL)
190     {
191       g_object_ref (individual);
192       g_signal_connect (individual, "removed",
193           (GCallback) individual_removed_cb, dialog);
194
195       /* Update the UI */
196       empathy_individual_widget_set_individual (
197           EMPATHY_INDIVIDUAL_WIDGET (priv->individual_widget), individual);
198       set_unlink_button_sensitivity (dialog);
199     }
200 }
201
202 static void
203 individual_edit_dialog_get_property (GObject *object,
204     guint param_id,
205     GValue *value,
206     GParamSpec *pspec)
207 {
208   EmpathyIndividualEditDialogPriv *priv = GET_PRIV (object);
209
210   switch (param_id) {
211   case PROP_INDIVIDUAL:
212     g_value_set_object (value, priv->individual);
213     break;
214   default:
215     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
216     break;
217   };
218 }
219
220 static void
221 individual_edit_dialog_set_property (GObject *object,
222   guint param_id,
223   const GValue *value,
224   GParamSpec   *pspec)
225 {
226   EmpathyIndividualEditDialog *dialog =
227     EMPATHY_INDIVIDUAL_EDIT_DIALOG (object);
228
229   switch (param_id) {
230   case PROP_INDIVIDUAL:
231     individual_edit_dialog_set_individual (dialog,
232         FOLKS_INDIVIDUAL (g_value_get_object (value)));
233     break;
234   default:
235     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
236     break;
237   };
238 }
239
240 static void
241 individual_edit_dialog_dispose (GObject *object)
242 {
243   individual_edit_dialog_set_individual (
244       EMPATHY_INDIVIDUAL_EDIT_DIALOG (object), NULL);
245
246   G_OBJECT_CLASS (
247       empathy_individual_edit_dialog_parent_class)->dispose (object);
248 }
249
250 static void
251 empathy_individual_edit_dialog_class_init (
252     EmpathyIndividualEditDialogClass *klass)
253 {
254   GObjectClass *object_class = G_OBJECT_CLASS (klass);
255
256   object_class->get_property = individual_edit_dialog_get_property;
257   object_class->set_property = individual_edit_dialog_set_property;
258   object_class->dispose = individual_edit_dialog_dispose;
259
260   g_object_class_install_property (object_class,
261       PROP_INDIVIDUAL,
262       g_param_spec_object ("individual",
263           "Folks Individual",
264           "Folks Individual to edit using the dialog.",
265           FOLKS_TYPE_INDIVIDUAL,
266           G_PARAM_CONSTRUCT_ONLY |
267           G_PARAM_READWRITE |
268           G_PARAM_STATIC_STRINGS));
269
270   g_type_class_add_private (object_class,
271       sizeof (EmpathyIndividualEditDialogPriv));
272 }
273
274 static void
275 empathy_individual_edit_dialog_init (
276     EmpathyIndividualEditDialog *dialog)
277 {
278   GtkWidget *button, *action_area;
279   EmpathyIndividualEditDialogPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (
280       dialog, EMPATHY_TYPE_INDIVIDUAL_EDIT_DIALOG,
281       EmpathyIndividualEditDialogPriv);
282
283   dialog->priv = priv;
284   priv->individual = NULL;
285
286   gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
287   gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
288   gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Contact Information"));
289
290   /* Individual widget */
291   priv->individual_widget = empathy_individual_widget_new (priv->individual,
292       EMPATHY_INDIVIDUAL_WIDGET_EDIT_ALIAS |
293       EMPATHY_INDIVIDUAL_WIDGET_EDIT_GROUPS |
294       EMPATHY_INDIVIDUAL_WIDGET_EDIT_FAVOURITE);
295   gtk_container_set_border_width (GTK_CONTAINER (priv->individual_widget), 8);
296   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (
297       GTK_DIALOG (dialog))), priv->individual_widget, TRUE, TRUE, 0);
298   gtk_widget_show (priv->individual_widget);
299
300   /* Unlink button */
301   button = gtk_button_new_with_mnemonic (
302       C_("Unlink individual (button)", "_Unlink"));
303   gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, RESPONSE_UNLINK);
304
305   action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
306   gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (action_area), button,
307       TRUE);
308
309   gtk_widget_show (button);
310
311   /* Close button */
312   button = gtk_button_new_with_label (GTK_STOCK_CLOSE);
313   gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
314   gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button,
315       GTK_RESPONSE_CLOSE);
316   gtk_widget_set_can_default (button, TRUE);
317   gtk_window_set_default (GTK_WINDOW (dialog), button);
318   gtk_widget_show (button);
319
320   g_signal_connect (dialog, "response",
321       G_CALLBACK (individual_dialogs_response_cb), &edit_dialogs);
322 }