]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-contact-search-dialog.c
Updated Spanish translation
[empathy.git] / libempathy-gtk / empathy-contact-search-dialog.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  * empathy-contact-search-dialog.c
4  *
5  * Copyright (C) 2010-2011 Collabora Ltd.
6  *
7  * The code contained in this file is free software; you can redistribute
8  * it and/or modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either version
10  * 2.1 of the License, or (at your option) any later version.
11  *
12  * This file is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this code; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  * Authors:
22  *     Danielle Madeley <danielle.madeley@collabora.co.uk>
23  *     Emilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>
24  */
25
26 #include "config.h"
27 #include "empathy-contact-search-dialog.h"
28
29 #include <glib/gi18n-lib.h>
30
31 #include "empathy-account-chooser.h"
32 #include "empathy-cell-renderer-activatable.h"
33 #include "empathy-cell-renderer-text.h"
34 #include "empathy-client-factory.h"
35 #include "empathy-images.h"
36 #include "empathy-individual-information-dialog.h"
37 #include "empathy-utils.h"
38
39 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
40 #include "empathy-debug.h"
41
42 #include "empathy-contact-search-dialog.h"
43
44 #define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_CONTACT_SEARCH_DIALOG, EmpathyContactSearchDialogPrivate))
45
46 G_DEFINE_TYPE (EmpathyContactSearchDialog, empathy_contact_search_dialog, GTK_TYPE_DIALOG);
47
48 enum
49 {
50    NAME_COLUMN,
51    LOGIN_COLUMN,
52    N_COLUMNS
53 };
54
55 enum {
56    PAGE_SEARCH_RESULTS,
57    PAGE_NO_MATCH,
58    PAGE_NOT_SUPPORTED,
59 };
60
61 typedef struct _EmpathyContactSearchDialogPrivate EmpathyContactSearchDialogPrivate;
62 struct _EmpathyContactSearchDialogPrivate
63 {
64   TpContactSearch *searcher;
65   GtkListStore *store;
66
67   GtkWidget *chooser;
68   GtkWidget *notebook;
69   GtkWidget *tree_view;
70   GtkWidget *spinner;
71   GtkWidget *add_button;
72   GtkWidget *find_button;
73   GtkWidget *search_entry;
74   /* GtkWidget *server_entry; */
75   GtkWidget *message;
76   GtkWidget *message_window;
77   GtkWidget *message_label;
78 };
79
80 static void
81 empathy_contact_search_dialog_dispose (GObject *self)
82 {
83   EmpathyContactSearchDialogPrivate *priv = GET_PRIVATE (self);
84
85   tp_clear_object (&priv->searcher);
86
87   G_OBJECT_CLASS (empathy_contact_search_dialog_parent_class)->dispose (self);
88 }
89
90 static void
91 on_searcher_reset (GObject *source_object,
92     GAsyncResult *result,
93     gpointer user_data)
94 {
95   EmpathyContactSearchDialog *self = EMPATHY_CONTACT_SEARCH_DIALOG (user_data);
96   EmpathyContactSearchDialogPrivate *priv = GET_PRIVATE (self);
97   TpContactSearch *searcher = TP_CONTACT_SEARCH (source_object);
98   GError *error = NULL;
99   GHashTable *search;
100   const gchar *search_criteria;
101
102   tp_contact_search_reset_finish (searcher, result, &error);
103   if (error != NULL)
104     {
105       DEBUG ("Failed to reset the TpContactSearch: %s", error->message);
106       gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook),
107           PAGE_NOT_SUPPORTED);
108
109       g_error_free (error);
110       return;
111     }
112
113   gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook),
114       PAGE_SEARCH_RESULTS);
115
116   search = g_hash_table_new (g_str_hash, g_str_equal);
117
118   search_criteria = gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
119
120   if (tp_strv_contains (tp_contact_search_get_search_keys (searcher), ""))
121     g_hash_table_insert (search, "", (gpointer) search_criteria);
122   else
123     g_hash_table_insert (search, "fn", (gpointer) search_criteria);
124
125   gtk_list_store_clear (priv->store);
126   tp_contact_search_start (priv->searcher, search);
127
128   g_hash_table_unref (search);
129 }
130
131 static void
132 empathy_contact_search_dialog_do_search (EmpathyContactSearchDialog *self)
133 {
134   EmpathyContactSearchDialogPrivate *priv = GET_PRIVATE (self);
135
136   tp_contact_search_reset_async (priv->searcher,
137       NULL, /* gtk_entry_get_text (GTK_ENTRY (priv->server_entry)), */
138       0,
139       on_searcher_reset,
140       self);
141 }
142
143 static void
144 on_get_contact_factory_get_from_id_cb (GObject *source,
145     GAsyncResult *result,
146     gpointer user_data)
147 {
148   gchar *message = user_data;
149   GError *error = NULL;
150   EmpathyContact *contact;
151
152   contact = empathy_client_factory_dup_contact_by_id_finish (
153       EMPATHY_CLIENT_FACTORY (source), result, &error);
154   if (contact == NULL)
155     {
156       g_warning ("Error while getting the contact: %s", error->message);
157       g_error_free (error);
158       goto out;
159     }
160
161   empathy_contact_add_to_contact_list (contact, message);
162   g_object_unref (contact);
163
164 out:
165   g_free (message);
166 }
167
168 static void
169 add_selected_contact (EmpathyContactSearchDialog *self)
170 {
171   EmpathyContactSearchDialogPrivate *priv = GET_PRIVATE (self);
172   GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
173   TpConnection *conn;
174   GtkTreeIter iter;
175   GtkTreeModel *model;
176   GtkTextBuffer *buffer;
177   GtkTextIter start, end;
178   gchar *message;
179   gboolean sel;
180   gchar *id;
181   EmpathyClientFactory *factory;
182
183   conn = empathy_account_chooser_get_connection (EMPATHY_ACCOUNT_CHOOSER (priv->chooser));
184
185   sel = gtk_tree_selection_get_selected (selection, &model, &iter);
186   g_return_if_fail (sel == TRUE);
187
188   gtk_tree_model_get (model, &iter, LOGIN_COLUMN, &id, -1);
189
190   DEBUG ("Requested to add contact: %s", id);
191
192   buffer = gtk_text_view_get_buffer GTK_TEXT_VIEW (priv->message);
193   gtk_text_buffer_get_start_iter (buffer, &start);
194   gtk_text_buffer_get_end_iter (buffer, &end);
195   message = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
196
197   factory = empathy_client_factory_dup ();
198
199   empathy_client_factory_dup_contact_by_id_async (factory, conn, id,
200       on_get_contact_factory_get_from_id_cb, message);
201
202   g_object_unref (factory);
203
204   /* Close the dialog */
205   gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_CANCEL);
206 }
207
208 static void
209 empathy_contact_search_dialog_response (GtkDialog *self,
210     gint response)
211 {
212   switch (response)
213     {
214       case GTK_RESPONSE_APPLY:
215         add_selected_contact (EMPATHY_CONTACT_SEARCH_DIALOG (self));
216         break;
217       default:
218         gtk_widget_destroy (GTK_WIDGET (self));
219         break;
220     }
221 }
222
223 static void
224 empathy_contact_search_dialog_class_init (
225     EmpathyContactSearchDialogClass *klass)
226 {
227   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
228   GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
229
230   gobject_class->dispose = empathy_contact_search_dialog_dispose;
231
232   dialog_class->response = empathy_contact_search_dialog_response;
233
234   g_type_class_add_private (gobject_class,
235       sizeof (EmpathyContactSearchDialogPrivate));
236 }
237
238 static void
239 _on_search_state_changed_cb (TpContactSearch *searcher,
240     GParamSpec *pspec,
241     gpointer user_data)
242 {
243   EmpathyContactSearchDialog *self = EMPATHY_CONTACT_SEARCH_DIALOG (user_data);
244   EmpathyContactSearchDialogPrivate *priv = GET_PRIVATE (self);
245   TpChannelContactSearchState state;
246
247   g_object_get (searcher, "state", &state, NULL);
248
249   DEBUG ("new search status: %d", state);
250
251   if (state == TP_CHANNEL_CONTACT_SEARCH_STATE_IN_PROGRESS)
252     {
253       gtk_widget_show (priv->spinner);
254       gtk_spinner_start (GTK_SPINNER (priv->spinner));
255     }
256   else
257     {
258       gtk_widget_hide (priv->spinner);
259       gtk_spinner_stop (GTK_SPINNER (priv->spinner));
260     }
261
262   if (state == TP_CHANNEL_CONTACT_SEARCH_STATE_NOT_STARTED
263       || state == TP_CHANNEL_CONTACT_SEARCH_STATE_IN_PROGRESS)
264     {
265       gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook),
266           PAGE_SEARCH_RESULTS);
267     }
268   else
269     {
270       GtkTreeIter help_iter;
271
272       if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->store),
273           &help_iter))
274         {
275           /* No results found, display a helpful message. */
276           gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook),
277               PAGE_NO_MATCH);
278         }
279     }
280 }
281
282 static void
283 _search_results_received (TpContactSearch *searcher,
284     GList *results,
285     EmpathyContactSearchDialog *self)
286 {
287   EmpathyContactSearchDialogPrivate *priv = GET_PRIVATE (self);
288   const TpContactInfoField *name;
289   GList *l;
290
291   for (l = results; l != NULL; l = l->next)
292     {
293       TpContactSearchResult *result = l->data;
294
295       name = tp_contact_search_result_get_field (result, "fn");
296
297       gtk_list_store_insert_with_values (priv->store, NULL, -1,
298           NAME_COLUMN, name ? name->field_value[0] : NULL,
299           LOGIN_COLUMN, tp_contact_search_result_get_identifier (result),
300           -1);
301     }
302 }
303
304 static void
305 on_searcher_created (GObject *source_object,
306     GAsyncResult *result,
307     gpointer user_data)
308 {
309   EmpathyContactSearchDialog *self;
310   EmpathyContactSearchDialogPrivate *priv;
311   GError *error = NULL;
312
313   if (EMPATHY_IS_CONTACT_SEARCH_DIALOG (user_data) == FALSE)
314     /* This happens if the dialog is closed before the callback is called */
315     return;
316
317   self = EMPATHY_CONTACT_SEARCH_DIALOG (user_data);
318   priv = GET_PRIVATE (self);
319
320   priv->searcher = tp_contact_search_new_finish (result, &error);
321   if (error != NULL)
322     {
323       DEBUG ("Failed to create a TpContactSearch: %s", error->message);
324       gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook),
325           PAGE_NOT_SUPPORTED);
326
327       g_error_free (error);
328       return;
329     }
330
331   gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook),
332       PAGE_SEARCH_RESULTS);
333
334   g_signal_connect (priv->searcher, "search-results-received",
335       G_CALLBACK (_search_results_received), self);
336   g_signal_connect (priv->searcher, "notify::state",
337       G_CALLBACK (_on_search_state_changed_cb), self);
338
339   gtk_widget_set_sensitive (priv->find_button, TRUE);
340   gtk_widget_set_sensitive (priv->search_entry, TRUE);
341 }
342
343 static void
344 on_selection_changed (GtkTreeSelection *selection,
345     gpointer user_data)
346 {
347   EmpathyContactSearchDialog *self;
348   EmpathyContactSearchDialogPrivate *priv;
349   gboolean sel;
350
351   self = EMPATHY_CONTACT_SEARCH_DIALOG (user_data);
352   priv = GET_PRIVATE (self);
353   sel = gtk_tree_selection_get_selected (selection, NULL, NULL);
354
355   gtk_widget_set_sensitive (priv->add_button, sel);
356 }
357
358 static void
359 check_request_message_available (EmpathyContactSearchDialog *self,
360     TpConnection *conn)
361 {
362   EmpathyContactSearchDialogPrivate *priv = GET_PRIVATE (self);
363
364   gtk_widget_set_visible (priv->message_window,
365       tp_connection_get_can_change_contact_list (conn));
366   gtk_widget_set_visible (priv->message_label,
367       tp_connection_get_can_change_contact_list (conn));
368 }
369
370 static void
371 _account_chooser_changed (EmpathyAccountChooser *chooser,
372     EmpathyContactSearchDialog *self)
373 {
374   EmpathyContactSearchDialogPrivate *priv = GET_PRIVATE (self);
375   TpAccount *account = empathy_account_chooser_get_account (chooser);
376   TpConnection *conn = empathy_account_chooser_get_connection (chooser);
377   TpCapabilities *caps = tp_connection_get_capabilities (conn);
378   gboolean can_cs, can_set_limit, can_set_server;
379
380   can_cs = tp_capabilities_supports_contact_search (caps,
381       &can_set_limit, &can_set_server);
382   DEBUG ("The server supports cs|limit|server: %s|%s|%s",
383       can_cs ? "yes" : "no",
384       can_set_limit ? "yes" : "no",
385       can_set_server ? "yes" : "no");
386
387   /* gtk_widget_set_sensitive (priv->server_entry, can_set_server); */
388   gtk_widget_set_sensitive (priv->find_button, FALSE);
389   gtk_widget_set_sensitive (priv->search_entry, FALSE);
390
391   DEBUG ("New account is %s", tp_proxy_get_object_path (account));
392
393   tp_clear_object (&priv->searcher);
394   tp_contact_search_new_async (account,
395       NULL, /* gtk_entry_get_text (GTK_ENTRY (priv->server_entry)), */
396       0,
397       on_searcher_created, self);
398
399   /* Make the request message textview sensitive if it can be used */
400   check_request_message_available (self, conn);
401 }
402
403 static void
404 _on_button_search_clicked (GtkWidget *widget,
405     EmpathyContactSearchDialog *self)
406 {
407   empathy_contact_search_dialog_do_search (self);
408 }
409
410 #if 0
411 static void
412 on_server_changed_cb (GtkEditable *editable,
413     gpointer user_data)
414 {
415   EmpathyContactSearchDialog *self = EMPATHY_CONTACT_SEARCH_DIALOG (user_data);
416   EmpathyContactSearchDialogPrivate *priv = GET_PRIVATE (self);
417
418   g_return_if_fail (priv->searcher != NULL);
419
420   tp_contact_search_reset_async (priv->searcher,
421       gtk_entry_get_text (GTK_ENTRY (editable)),
422       0,
423       on_searcher_reset,
424       self);
425 }
426 #endif
427
428 static void
429 empathy_account_chooser_filter_supports_contact_search (
430     TpAccount *account,
431     EmpathyAccountChooserFilterResultCallback callback,
432     gpointer callback_data,
433     gpointer user_data)
434 {
435   TpConnection *connection;
436   gboolean supported = FALSE;
437   TpCapabilities *caps;
438
439   connection = tp_account_get_connection (account);
440   if (connection == NULL)
441       goto out;
442
443   caps = tp_connection_get_capabilities (connection);
444   if (caps == NULL)
445       goto out;
446
447   supported = tp_capabilities_supports_contact_search (caps, NULL, NULL);
448
449 out:
450   callback (supported, callback_data);
451 }
452
453 static void
454 contact_search_dialog_row_activated_cb (GtkTreeView *tv,
455     GtkTreePath *path,
456     GtkTreeViewColumn *column,
457     EmpathyContactSearchDialog *self)
458 {
459   /* just emit the same response as the Add Button */
460   gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_APPLY);
461 }
462
463 static void
464 on_profile_button_got_contact_cb (GObject *source,
465     GAsyncResult *result,
466     gpointer user_data)
467 {
468   GError *error = NULL;
469   EmpathyContact *contact;
470   FolksIndividual *individual;
471
472   contact = empathy_client_factory_dup_contact_by_id_finish (
473         EMPATHY_CLIENT_FACTORY (source), result, &error);
474   if (contact == NULL)
475     {
476       g_warning ("Error while getting the contact: %s", error->message);
477       g_error_free (error);
478       return;
479     }
480
481   individual = empathy_ensure_individual_from_tp_contact (
482     empathy_contact_get_tp_contact (contact));
483
484   empathy_display_individual_info (individual);
485
486   g_object_unref (contact);
487   g_object_unref (individual);
488 }
489
490 static void
491 on_profile_button_clicked_cb (EmpathyCellRendererActivatable *cell,
492     const gchar *path_string,
493     EmpathyContactSearchDialog *self)
494 {
495   EmpathyContactSearchDialogPrivate *priv = GET_PRIVATE (self);
496   TpConnection *conn;
497   GtkTreeIter iter;
498   GtkTreeModel *model;
499   gboolean valid;
500   gchar *id;
501   EmpathyClientFactory *factory;
502
503   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view));
504
505   conn = empathy_account_chooser_get_connection (
506       EMPATHY_ACCOUNT_CHOOSER (priv->chooser));
507
508   valid = gtk_tree_model_get_iter_from_string (model, &iter, path_string);
509   g_return_if_fail (valid == TRUE);
510
511   gtk_tree_model_get (model, &iter, LOGIN_COLUMN, &id, -1);
512
513   DEBUG ("Requested to show profile for contact: %s", id);
514
515   factory = empathy_client_factory_dup ();
516
517   empathy_client_factory_dup_contact_by_id_async (factory, conn, id,
518       on_profile_button_got_contact_cb, self);
519
520   g_object_unref (factory);
521 }
522
523 static void
524 append_message_page (EmpathyContactSearchDialog *self,
525     const gchar *message)
526 {
527   EmpathyContactSearchDialogPrivate *priv = GET_PRIVATE (self);
528   GtkWidget *label;
529   gchar *tmp;
530
531   label = gtk_label_new (NULL);
532   tmp = g_strdup_printf ("<b><span size='xx-large'>%s</span></b>", message);
533   gtk_label_set_markup (GTK_LABEL (label), tmp);
534   g_free (tmp);
535
536   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
537
538   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), label, NULL);
539 }
540
541 static void
542 empathy_contact_search_dialog_init (EmpathyContactSearchDialog *self)
543 {
544   EmpathyContactSearchDialogPrivate *priv = GET_PRIVATE (self);
545   GtkWidget *vbox, *hbox, *scrolled_window, *label;
546   GtkCellRenderer *cell;
547   GtkTreeViewColumn *col;
548   GtkTreeSelection *selection;
549   GtkSizeGroup *size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
550
551   /* Title */
552   gtk_window_set_title (GTK_WINDOW (self), _("Search contacts"));
553
554   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
555   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
556
557   /* Account chooser */
558   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
559   label = gtk_label_new (_("Account:"));
560   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
561   gtk_size_group_add_widget (size_group, label);
562
563   priv->chooser = empathy_account_chooser_new ();
564   empathy_account_chooser_set_filter (EMPATHY_ACCOUNT_CHOOSER (priv->chooser),
565       empathy_account_chooser_filter_supports_contact_search, NULL);
566   gtk_box_pack_start (GTK_BOX (hbox), priv->chooser, TRUE, TRUE, 0);
567   g_signal_connect (priv->chooser, "changed",
568       G_CALLBACK (_account_chooser_changed), self);
569
570   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
571
572 #if 0
573   /* Server entry */
574   priv->server_entry = gtk_entry_new ();
575   gtk_box_pack_start (GTK_BOX (vbox), priv->server_entry, FALSE, TRUE, 6);
576   g_signal_connect (GTK_EDITABLE (priv->server_entry), "changed",
577       G_CALLBACK (on_server_changed_cb), self);
578 #endif
579
580   /* Search input */
581   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
582   label = gtk_label_new (_("Search: "));
583   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
584   gtk_size_group_add_widget (size_group, label);
585
586   priv->search_entry = gtk_entry_new ();
587   gtk_box_pack_start (GTK_BOX (hbox), priv->search_entry, TRUE, TRUE, 0);
588   g_signal_connect (priv->search_entry, "activate",
589       G_CALLBACK (_on_button_search_clicked), self);
590
591   priv->find_button = gtk_button_new_from_stock (GTK_STOCK_FIND);
592   g_signal_connect (priv->find_button, "clicked",
593       G_CALLBACK (_on_button_search_clicked), self);
594   gtk_box_pack_end (GTK_BOX (hbox), priv->find_button, FALSE, TRUE, 0);
595
596   priv->spinner = gtk_spinner_new ();
597   gtk_box_pack_end (GTK_BOX (hbox), priv->spinner, FALSE, TRUE, 0);
598   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
599
600   /* Search results */
601   priv->store = gtk_list_store_new (N_COLUMNS,
602                                     G_TYPE_STRING,  /* Name */
603                                     G_TYPE_STRING); /* Login */
604
605   priv->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->store));
606   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
607   gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
608
609   g_signal_connect (priv->tree_view, "row-activated",
610       G_CALLBACK (contact_search_dialog_row_activated_cb), self);
611   g_signal_connect (selection, "changed",
612       G_CALLBACK (on_selection_changed), self);
613
614   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
615
616   col = gtk_tree_view_column_new ();
617
618   cell = empathy_cell_renderer_text_new ();
619   gtk_tree_view_column_pack_start (col, cell, TRUE);
620   /* EmpathyCellRendererText displays "name" above and "status" below.
621    * We want the login above since it'll always be available, and the
622    * name below since we won't always have it. */
623   gtk_tree_view_column_add_attribute (col, cell,
624       "name", LOGIN_COLUMN);
625   gtk_tree_view_column_add_attribute (col, cell,
626       "status", NAME_COLUMN);
627
628   cell = empathy_cell_renderer_activatable_new ();
629   gtk_tree_view_column_pack_end (col, cell, FALSE);
630   g_object_set (cell, "stock-id", EMPATHY_IMAGE_CONTACT_INFORMATION, NULL);
631   g_signal_connect (cell, "path-activated",
632       G_CALLBACK (on_profile_button_clicked_cb), self);
633
634   gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree_view), col);
635
636   gtk_dialog_add_button (GTK_DIALOG (self),
637       GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
638
639   priv->add_button = gtk_dialog_add_button (GTK_DIALOG (self),
640       _("_Add Contact"), GTK_RESPONSE_APPLY);
641   gtk_widget_set_sensitive (priv->add_button, FALSE);
642   gtk_button_set_image (GTK_BUTTON (priv->add_button),
643       gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON));
644
645   /* Pack the dialog */
646   priv->notebook = gtk_notebook_new ();
647   gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE);
648   g_object_set (priv->notebook, "margin", 6, NULL);
649
650   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
651   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
652       GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
653
654   gtk_container_add (GTK_CONTAINER (scrolled_window), priv->tree_view);
655
656   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), scrolled_window,
657       NULL);
658
659   append_message_page (self, _("No contacts found"));
660   append_message_page (self, _("Contact search is not supported on this account"));
661
662   gtk_box_pack_start (GTK_BOX (vbox), priv->notebook, TRUE, TRUE, 3);
663
664   /* Request message textview */
665   priv->message_label = gtk_label_new (
666        _("Your message introducing yourself:"));
667   gtk_misc_set_alignment (GTK_MISC (priv->message_label), 0, 0.5);
668
669   priv->message = gtk_text_view_new ();
670   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->message),
671       GTK_WRAP_WORD_CHAR);
672   gtk_text_buffer_set_text (
673       gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->message)),
674       _("Please let me see when you're online. Thanks!"), -1);
675
676   priv->message_window = gtk_scrolled_window_new (NULL, NULL);
677   gtk_scrolled_window_set_shadow_type (
678       GTK_SCROLLED_WINDOW (priv->message_window),
679       GTK_SHADOW_ETCHED_IN);
680   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->message_window),
681       GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
682
683   gtk_container_add (GTK_CONTAINER (priv->message_window), priv->message);
684
685   gtk_box_pack_start (GTK_BOX (vbox), priv->message_label, FALSE, TRUE, 3);
686   gtk_box_pack_start (GTK_BOX (vbox), priv->message_window, FALSE, TRUE, 3);
687
688   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (
689           GTK_DIALOG (self))), vbox, TRUE, TRUE, 0);
690
691   gtk_window_set_default_size (GTK_WINDOW (self), 200, 400);
692   gtk_widget_show_all (vbox);
693   gtk_widget_hide (priv->spinner);
694   g_object_unref (size_group);
695 }
696
697 GtkWidget *
698 empathy_contact_search_dialog_new (GtkWindow *parent)
699 {
700   GtkWidget *self;
701
702   g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
703
704   self = g_object_new (EMPATHY_TYPE_CONTACT_SEARCH_DIALOG, NULL);
705
706   if (parent != NULL)
707     {
708       gtk_window_set_transient_for (GTK_WINDOW (self), parent);
709     }
710
711   return self;
712 }