]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-new-message-dialog.c
new-message-dialog: remove the call button
[empathy.git] / libempathy-gtk / empathy-new-message-dialog.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2007-2008 Collabora Ltd.
4  *
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.
9  *
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.
14  *
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
18  *
19  * Authors: Xavier Claessens <xclaesse@gmail.com>
20  */
21
22 #include <config.h>
23
24 #include <string.h>
25 #include <stdlib.h>
26
27 #include <gtk/gtk.h>
28 #include <glib/gi18n-lib.h>
29
30 #include <libempathy/empathy-tp-contact-factory.h>
31 #include <libempathy/empathy-contact-manager.h>
32 #include <libempathy/empathy-dispatcher.h>
33 #include <libempathy/empathy-utils.h>
34
35 #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
36 #include <libempathy/empathy-debug.h>
37
38 #include <libempathy-gtk/empathy-ui-utils.h>
39 #include <libempathy-gtk/empathy-images.h>
40
41 #include "empathy-new-message-dialog.h"
42 #include "empathy-account-chooser.h"
43
44 static EmpathyNewMessageDialog *dialog_singleton = NULL;
45
46 G_DEFINE_TYPE(EmpathyNewMessageDialog, empathy_new_message_dialog,
47                                        GTK_TYPE_DIALOG)
48
49 /**
50  * SECTION:empathy-new-message-dialog
51  * @title: EmpathyNewMessageDialog
52  * @short_description: A dialog to show a new message
53  * @include: libempathy-gtk/empathy-new-message-dialog.h
54  *
55  * #EmpathyNewMessageDialog is a dialog which allows a text chat or
56  * call to be started with any contact on any enabled account.
57  */
58
59 typedef struct _EmpathyNewMessageDialogPriv EmpathyNewMessageDialogPriv;
60
61 struct _EmpathyNewMessageDialogPriv {
62         GtkWidget *dialog;
63         GtkWidget *table_contact;
64         GtkWidget *account_chooser;
65         GtkWidget *entry_id;
66         GtkWidget *button_chat;
67         EmpathyContactManager *contact_manager;
68 };
69
70 #define GET_PRIV(o) \
71   (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_NEW_MESSAGE_DIALOG, \
72     EmpathyNewMessageDialogPriv))
73
74 enum {
75         COMPLETION_COL_TEXT,
76         COMPLETION_COL_ID,
77         COMPLETION_COL_NAME,
78 } CompletionCol;
79
80 static void
81 new_message_dialog_account_changed_cb (GtkWidget               *widget,
82                                        EmpathyNewMessageDialog *dialog)
83 {
84         EmpathyNewMessageDialogPriv *priv = GET_PRIV (dialog);
85         EmpathyAccountChooser *chooser;
86         TpConnection          *connection;
87         EmpathyTpContactList *contact_list;
88         GList                *members;
89         GtkListStore         *store;
90         GtkEntryCompletion   *completion;
91         GtkTreeIter           iter;
92         gchar                *tmpstr;
93
94         /* Remove completions */
95         completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry_id));
96         store = GTK_LIST_STORE (gtk_entry_completion_get_model (completion));
97         gtk_list_store_clear (store);
98
99         /* Get members of the new account */
100         chooser = EMPATHY_ACCOUNT_CHOOSER (priv->account_chooser);
101         connection = empathy_account_chooser_get_connection (chooser);
102         if (!connection) {
103                 return;
104         }
105         contact_list = empathy_contact_manager_get_list (priv->contact_manager,
106                                                          connection);
107         members = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (contact_list));
108
109         /* Add members to the completion */
110         while (members) {
111                 EmpathyContact *contact = members->data;
112
113                 DEBUG ("Adding contact ID %s, Name %s",
114                        empathy_contact_get_id (contact),
115                        empathy_contact_get_name (contact));
116
117                 tmpstr = g_strdup_printf ("%s (%s)",
118                         empathy_contact_get_name (contact),
119                         empathy_contact_get_id (contact));
120
121                 gtk_list_store_insert_with_values (store, &iter, -1,
122                         COMPLETION_COL_TEXT, tmpstr,
123                         COMPLETION_COL_ID, empathy_contact_get_id (contact),
124                         COMPLETION_COL_NAME, empathy_contact_get_name (contact),
125                         -1);
126
127                 g_free (tmpstr);
128
129                 g_object_unref (contact);
130                 members = g_list_delete_link (members, members);
131         }
132 }
133
134 static gboolean
135 new_message_dialog_match_selected_cb (GtkEntryCompletion *widget,
136                                       GtkTreeModel       *model,
137                                       GtkTreeIter        *iter,
138                                       EmpathyNewMessageDialog *dialog)
139 {
140         EmpathyNewMessageDialogPriv *priv = GET_PRIV (dialog);
141         gchar *id;
142
143         if (!iter || !model) {
144                 return FALSE;
145         }
146
147         gtk_tree_model_get (model, iter, COMPLETION_COL_ID, &id, -1);
148         gtk_entry_set_text (GTK_ENTRY (priv->entry_id), id);
149
150         DEBUG ("Got selected match **%s**", id);
151
152         g_free (id);
153
154         return TRUE;
155 }
156
157 static gboolean
158 new_message_dialog_match_func (GtkEntryCompletion *completion,
159                                const gchar        *key,
160                                GtkTreeIter        *iter,
161                                gpointer            user_data)
162 {
163         GtkTreeModel *model;
164         gchar        *id;
165         gchar        *name;
166
167         model = gtk_entry_completion_get_model (completion);
168         if (!model || !iter) {
169                 return FALSE;
170         }
171
172         gtk_tree_model_get (model, iter, COMPLETION_COL_NAME, &name, -1);
173         if (strstr (name, key)) {
174                 DEBUG ("Key %s is matching name **%s**", key, name);
175                 g_free (name);
176                 return TRUE;
177         }
178         g_free (name);
179
180         gtk_tree_model_get (model, iter, COMPLETION_COL_ID, &id, -1);
181         if (strstr (id, key)) {
182                 DEBUG ("Key %s is matching ID **%s**", key, id);
183                 g_free (id);
184                 return TRUE;
185         }
186         g_free (id);
187
188         return FALSE;
189 }
190
191 static void
192 new_message_dialog_response_cb (GtkWidget               *widget,
193                                 gint                    response,
194                                 EmpathyNewMessageDialog *dialog)
195 {
196         EmpathyNewMessageDialogPriv *priv = GET_PRIV (dialog);
197         TpConnection *connection;
198         const gchar *id;
199
200         connection = empathy_account_chooser_get_connection (
201                 EMPATHY_ACCOUNT_CHOOSER (priv->account_chooser));
202         id = gtk_entry_get_text (GTK_ENTRY (priv->entry_id));
203         if (!connection || EMP_STR_EMPTY (id)) {
204                 gtk_widget_destroy (widget);
205                 return;
206         }
207
208         if (response == GTK_RESPONSE_ACCEPT) {
209                 empathy_dispatcher_chat_with_contact_id (connection, id, NULL, NULL);
210         }
211
212         gtk_widget_destroy (widget);
213 }
214
215 static void
216 new_message_change_state_button_cb  (GtkEditable             *editable,
217                                      EmpathyNewMessageDialog *dialog)
218 {
219         EmpathyNewMessageDialogPriv *priv = GET_PRIV (dialog);
220         const gchar *id;
221         gboolean     sensitive;
222
223         id = gtk_entry_get_text (GTK_ENTRY (editable));
224         sensitive = !EMP_STR_EMPTY (id);
225
226         gtk_widget_set_sensitive (priv->button_chat, sensitive);
227 }
228
229 static GObject *
230 empathy_new_message_dialog_constructor (GType type,
231                                         guint n_props,
232                                         GObjectConstructParam *props)
233 {
234         GObject *retval;
235
236         if (dialog_singleton) {
237                 retval = G_OBJECT (dialog_singleton);
238                 g_object_ref (retval);
239         }
240         else {
241                 retval = G_OBJECT_CLASS (
242                 empathy_new_message_dialog_parent_class)->constructor (type,
243                         n_props, props);
244
245                 dialog_singleton = EMPATHY_NEW_MESSAGE_DIALOG (retval);
246                 g_object_add_weak_pointer (retval, (gpointer) &dialog_singleton);
247         }
248
249         return retval;
250 }
251
252 static void
253 empathy_new_message_dialog_init (EmpathyNewMessageDialog *dialog)
254 {
255         EmpathyNewMessageDialogPriv *priv = GET_PRIV (dialog);
256         GtkBuilder                     *gui;
257         gchar                          *filename;
258         GtkEntryCompletion             *completion;
259         GtkListStore                   *model;
260         GtkWidget                      *content_area;
261         GtkWidget                      *image;
262
263         /* create a contact manager */
264         priv->contact_manager = empathy_contact_manager_dup_singleton ();
265
266         filename = empathy_file_lookup ("empathy-new-message-dialog.ui",
267                                         "libempathy-gtk");
268         gui = empathy_builder_get_file (filename,
269                                         "table_contact", &priv->table_contact,
270                                         "entry_id", &priv->entry_id,
271                                         NULL);
272         g_free (filename);
273
274         content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
275         gtk_container_add (GTK_CONTAINER (content_area), priv->table_contact);
276
277         /* add buttons */
278         gtk_dialog_add_button (GTK_DIALOG (dialog),
279                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
280
281         priv->button_chat = gtk_button_new_with_mnemonic (_("C_hat"));
282         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_NEW_MESSAGE,
283                 GTK_ICON_SIZE_BUTTON);
284         gtk_button_set_image (GTK_BUTTON (priv->button_chat), image);
285
286         gtk_dialog_add_action_widget (GTK_DIALOG (dialog), priv->button_chat,
287                 GTK_RESPONSE_ACCEPT);
288         gtk_widget_show (priv->button_chat);
289
290         /* Tweak the dialog */
291         gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
292
293         gtk_window_set_title (GTK_WINDOW (dialog), _("New Conversation"));
294         gtk_window_set_role (GTK_WINDOW (dialog), "new_message");
295         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
296         gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
297         gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
298
299         /* text completion */
300         completion = gtk_entry_completion_new ();
301         model = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
302         gtk_entry_completion_set_text_column (completion, COMPLETION_COL_TEXT);
303         gtk_entry_completion_set_match_func (completion,
304                                              new_message_dialog_match_func,
305                                              NULL, NULL);
306         gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (model));
307         gtk_entry_set_completion (GTK_ENTRY (priv->entry_id), completion);
308         g_signal_connect (completion, "match-selected",
309                           G_CALLBACK (new_message_dialog_match_selected_cb),
310                           dialog);
311         g_object_unref (completion);
312         g_object_unref (model);
313
314         g_signal_connect (dialog, "response",
315                     G_CALLBACK (new_message_dialog_response_cb), dialog);
316
317         empathy_builder_connect (gui, dialog,
318                                "entry_id", "changed", new_message_change_state_button_cb,
319                                NULL);
320
321         g_object_unref (gui);
322
323         /* Create account chooser */
324         priv->account_chooser = empathy_account_chooser_new ();
325         gtk_table_attach_defaults (GTK_TABLE (priv->table_contact),
326                                    priv->account_chooser,
327                                    1, 2, 0, 1);
328         empathy_account_chooser_set_filter (EMPATHY_ACCOUNT_CHOOSER (priv->account_chooser),
329                                             empathy_account_chooser_filter_is_connected,
330                                             NULL);
331         gtk_widget_show (priv->account_chooser);
332
333         new_message_dialog_account_changed_cb (priv->account_chooser, dialog);
334         g_signal_connect (priv->account_chooser, "changed",
335                           G_CALLBACK (new_message_dialog_account_changed_cb),
336                           dialog);
337
338         gtk_widget_set_sensitive (priv->button_chat, FALSE);
339 }
340
341 static void
342 empathy_new_message_dialog_dispose (GObject *object)
343 {
344         EmpathyNewMessageDialogPriv *priv = GET_PRIV (object);
345
346         if (priv->contact_manager != NULL) {
347                 g_object_unref (priv->contact_manager);
348                 priv->contact_manager = NULL;
349         }
350
351         if (G_OBJECT_CLASS (empathy_new_message_dialog_parent_class)->dispose)
352                 G_OBJECT_CLASS (empathy_new_message_dialog_parent_class)->dispose (object);
353 }
354
355 static void
356 empathy_new_message_dialog_class_init (
357   EmpathyNewMessageDialogClass *class)
358 {
359         GObjectClass *object_class = G_OBJECT_CLASS (class);
360
361         g_type_class_add_private (class, sizeof (EmpathyNewMessageDialogPriv));
362
363         object_class->constructor = empathy_new_message_dialog_constructor;
364
365         object_class->dispose = empathy_new_message_dialog_dispose;
366 }
367
368 /**
369  * empathy_new_message_dialog_new:
370  * @parent: parent #GtkWindow of the dialog
371  *
372  * Create a new #EmpathyNewMessageDialog it.
373  *
374  * Return value: the new #EmpathyNewMessageDialog
375  */
376 GtkWidget *
377 empathy_new_message_dialog_show (GtkWindow *parent)
378 {
379         GtkWidget *dialog;
380
381         dialog = g_object_new (EMPATHY_TYPE_NEW_MESSAGE_DIALOG, NULL);
382
383         if (parent) {
384                 gtk_window_set_transient_for (GTK_WINDOW (dialog),
385                                               GTK_WINDOW (parent));
386         }
387
388         gtk_widget_show (dialog);
389         return dialog;
390 }