2 * Copyright (C) 2007-2009 Collabora Ltd.
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.
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.
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
18 * Authors: Xavier Claessens <xclaesse@gmail.com>
19 * Authors: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
20 * Authors: Danielle Madeley <danielle.madeley@collabora.co.uk>
29 #include <glib/gi18n-lib.h>
31 #include <libempathy/empathy-tp-contact-factory.h>
32 #include <libempathy/empathy-contact-manager.h>
33 #include <libempathy/empathy-utils.h>
35 #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
36 #include <libempathy/empathy-debug.h>
38 #include <libempathy-gtk/empathy-ui-utils.h>
39 #include <libempathy-gtk/empathy-images.h>
41 #include "empathy-contact-selector-dialog.h"
42 #include "empathy-account-chooser.h"
44 G_DEFINE_ABSTRACT_TYPE (EmpathyContactSelectorDialog
,
45 empathy_contact_selector_dialog
,
48 typedef struct _EmpathyContactSelectorDialogPriv \
49 EmpathyContactSelectorDialogPriv
;
51 struct _EmpathyContactSelectorDialogPriv
{
53 GtkWidget
*account_chooser_label
;
54 GtkWidget
*account_chooser
;
56 EmpathyContactManager
*contact_manager
;
57 TpAccount
*filter_account
;
59 gboolean show_account_chooser
;
63 (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_CONTACT_SELECTOR_DIALOG, \
64 EmpathyContactSelectorDialogPriv))
68 PROP_SHOW_ACCOUNT_CHOOSER
,
80 contact_selector_dialog_account_changed_cb (GtkWidget
*widget
,
81 EmpathyContactSelectorDialog
*dialog
)
83 EmpathyContactSelectorDialogPriv
*priv
= GET_PRIV (dialog
);
84 EmpathyAccountChooser
*chooser
;
85 TpConnection
*connection
;
88 /* Remove completions */
89 gtk_list_store_clear (priv
->store
);
91 /* Get members of the new account */
92 chooser
= EMPATHY_ACCOUNT_CHOOSER (priv
->account_chooser
);
93 connection
= empathy_account_chooser_get_connection (chooser
);
97 if (priv
->show_account_chooser
)
99 EmpathyTpContactList
*contact_list
;
101 contact_list
= empathy_contact_manager_get_list (priv
->contact_manager
,
103 members
= empathy_contact_list_get_members (
104 EMPATHY_CONTACT_LIST (contact_list
));
108 if (priv
->filter_account
!= NULL
)
110 EmpathyTpContactList
*contact_list
;
112 connection
= tp_account_get_connection (priv
->filter_account
);
113 if (connection
== NULL
)
116 contact_list
= empathy_contact_manager_get_list (
117 priv
->contact_manager
, connection
);
119 members
= empathy_contact_list_get_members (
120 EMPATHY_CONTACT_LIST (contact_list
));
124 members
= empathy_contact_list_get_members (
125 EMPATHY_CONTACT_LIST (priv
->contact_manager
));
129 /* Add members to the completion */
132 EmpathyContact
*contact
= members
->data
;
136 DEBUG ("Adding contact ID %s, Name %s",
137 empathy_contact_get_id (contact
),
138 empathy_contact_get_alias (contact
));
140 tmpstr
= g_strdup_printf ("%s (%s)",
141 empathy_contact_get_alias (contact
),
142 empathy_contact_get_id (contact
));
144 gtk_list_store_insert_with_values (priv
->store
, &iter
, -1,
145 COMPLETION_COL_TEXT
, tmpstr
,
146 COMPLETION_COL_ID
, empathy_contact_get_id (contact
),
147 COMPLETION_COL_NAME
, empathy_contact_get_alias (contact
),
152 g_object_unref (contact
);
153 members
= g_list_delete_link (members
, members
);
156 g_object_notify (G_OBJECT (dialog
), "selected-account");
160 contact_selector_dialog_match_selected_cb (GtkEntryCompletion
*widget
,
163 EmpathyContactSelectorDialog
*dialog
)
165 EmpathyContactSelectorDialogPriv
*priv
= GET_PRIV (dialog
);
171 gtk_tree_model_get (model
, iter
, COMPLETION_COL_ID
, &id
, -1);
172 gtk_entry_set_text (GTK_ENTRY (priv
->entry_id
), id
);
174 DEBUG ("Got selected match **%s**", id
);
182 contact_selector_dialog_match_func (GtkEntryCompletion
*completion
,
191 model
= gtk_entry_completion_get_model (completion
);
195 gtk_tree_model_get (model
, iter
, COMPLETION_COL_NAME
, &str
, -1);
196 lower
= g_utf8_strdown (str
, -1);
197 if (strstr (lower
, key
))
199 DEBUG ("Key %s is matching name **%s**", key
, str
);
206 gtk_tree_model_get (model
, iter
, COMPLETION_COL_ID
, &str
, -1);
207 lower
= g_utf8_strdown (str
, -1);
208 if (strstr (lower
, key
))
210 DEBUG ("Key %s is matching ID **%s**", key
, str
);
223 contact_selector_change_state_button_cb (GtkEditable
*editable
,
224 EmpathyContactSelectorDialog
*dialog
)
229 id
= gtk_entry_get_text (GTK_ENTRY (editable
));
230 sensitive
= !EMP_STR_EMPTY (id
);
232 gtk_widget_set_sensitive (dialog
->button_action
, sensitive
);
236 entry_activate_cb (GtkEntry
*entry
,
241 id
= gtk_entry_get_text (entry
);
242 if (EMP_STR_EMPTY (id
))
245 gtk_dialog_response (GTK_DIALOG (self
), GTK_RESPONSE_ACCEPT
);
249 account_chooser_filter (TpAccount
*account
,
250 EmpathyAccountChooserFilterResultCallback callback
,
251 gpointer callback_data
,
254 EmpathyContactSelectorDialog
*self
= user_data
;
255 EmpathyContactSelectorDialogClass
*class = \
256 EMPATHY_CONTACT_SELECTOR_DIALOG_GET_CLASS (self
);
258 if (class->account_filter
== NULL
)
260 empathy_account_chooser_filter_is_connected (
261 account
,callback
, callback_data
, user_data
);
265 class->account_filter (self
, callback
, callback_data
, account
);
269 contact_selector_dialog_filter_visible (GtkTreeModel
*model
,
273 EmpathyContactSelectorDialog
*self
= EMPATHY_CONTACT_SELECTOR_DIALOG (data
);
277 gtk_tree_model_get (model
, iter
,
278 COMPLETION_COL_ID
, &id
,
281 /* this must be non-NULL for this function to get called */
282 r
= EMPATHY_CONTACT_SELECTOR_DIALOG_GET_CLASS (self
)->contact_filter (
291 empathy_contact_selector_dialog_init (EmpathyContactSelectorDialog
*dialog
)
293 EmpathyContactSelectorDialogPriv
*priv
= GET_PRIV (dialog
);
296 GtkEntryCompletion
*completion
;
297 GtkWidget
*content_area
;
298 GtkWidget
*table_contact
;
300 dialog
->vbox
= gtk_vbox_new (FALSE
, 3);
302 /* create a contact manager */
303 priv
->contact_manager
= empathy_contact_manager_dup_singleton ();
305 filename
= empathy_file_lookup ("empathy-contact-selector-dialog.ui",
307 gui
= empathy_builder_get_file (filename
,
308 "table_contact", &table_contact
,
309 "account_chooser_label", &priv
->account_chooser_label
,
310 "entry_id", &priv
->entry_id
,
314 empathy_builder_connect (gui
, dialog
,
315 "entry_id", "activate", entry_activate_cb
,
318 content_area
= gtk_dialog_get_content_area (GTK_DIALOG (dialog
));
319 gtk_container_add (GTK_CONTAINER (content_area
), dialog
->vbox
);
320 gtk_box_pack_start (GTK_BOX (dialog
->vbox
), table_contact
, TRUE
, TRUE
, 0);
321 gtk_widget_show (dialog
->vbox
);
323 gtk_dialog_add_button (GTK_DIALOG (dialog
),
324 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
);
326 /* Tweak the dialog */
327 gtk_window_set_resizable (GTK_WINDOW (dialog
), FALSE
);
328 gtk_window_set_position (GTK_WINDOW (dialog
), GTK_WIN_POS_CENTER_ON_PARENT
);
329 gtk_window_set_type_hint (GTK_WINDOW (dialog
), GDK_WINDOW_TYPE_HINT_DIALOG
);
331 gtk_container_set_border_width (GTK_CONTAINER (dialog
->vbox
), 6);
332 gtk_container_set_border_width (GTK_CONTAINER (dialog
), 6);
334 /* text completion */
335 priv
->store
= gtk_list_store_new (3, G_TYPE_STRING
, G_TYPE_STRING
, G_TYPE_STRING
);
337 completion
= gtk_entry_completion_new ();
338 gtk_entry_completion_set_text_column (completion
, COMPLETION_COL_TEXT
);
339 gtk_entry_completion_set_match_func (completion
,
340 contact_selector_dialog_match_func
,
342 gtk_entry_completion_set_model (completion
, GTK_TREE_MODEL (priv
->store
));
343 gtk_entry_set_completion (GTK_ENTRY (priv
->entry_id
), completion
);
344 g_signal_connect (completion
, "match-selected",
345 G_CALLBACK (contact_selector_dialog_match_selected_cb
),
347 g_object_unref (completion
);
348 g_object_unref (priv
->store
);
350 empathy_builder_connect (gui
, dialog
,
351 "entry_id", "changed", contact_selector_change_state_button_cb
,
354 g_object_unref (gui
);
356 /* Create account chooser */
357 priv
->show_account_chooser
= TRUE
;
358 priv
->account_chooser
= empathy_account_chooser_new ();
359 gtk_table_attach_defaults (GTK_TABLE (table_contact
),
360 priv
->account_chooser
,
362 empathy_account_chooser_set_filter (
363 EMPATHY_ACCOUNT_CHOOSER (priv
->account_chooser
),
364 account_chooser_filter
,
366 gtk_widget_show (priv
->account_chooser
);
368 contact_selector_dialog_account_changed_cb (priv
->account_chooser
, dialog
);
369 g_signal_connect (priv
->account_chooser
, "changed",
370 G_CALLBACK (contact_selector_dialog_account_changed_cb
),
375 empathy_contact_selector_dialog_get_property (GObject
*self
,
380 EmpathyContactSelectorDialog
*dialog
= EMPATHY_CONTACT_SELECTOR_DIALOG (self
);
381 EmpathyContactSelectorDialogPriv
*priv
= GET_PRIV (dialog
);
385 case PROP_SHOW_ACCOUNT_CHOOSER
:
386 g_value_set_boolean (value
,
387 empathy_contact_selector_dialog_get_show_account_chooser (dialog
));
390 case PROP_FILTER_ACCOUNT
:
391 g_value_set_object (value
,
392 empathy_contact_selector_dialog_get_filter_account (dialog
));
395 case PROP_SELECTED_ACCOUNT
:
396 g_value_set_object (value
, empathy_account_chooser_get_account (
397 EMPATHY_ACCOUNT_CHOOSER (priv
->account_chooser
)));
401 G_OBJECT_WARN_INVALID_PROPERTY_ID (self
, prop_id
, pspec
);
407 empathy_contact_selector_dialog_set_property (GObject
*self
,
412 EmpathyContactSelectorDialog
*dialog
= EMPATHY_CONTACT_SELECTOR_DIALOG (self
);
413 EmpathyContactSelectorDialogPriv
*priv
= GET_PRIV (dialog
);
417 case PROP_SHOW_ACCOUNT_CHOOSER
:
418 empathy_contact_selector_dialog_set_show_account_chooser (dialog
,
419 g_value_get_boolean (value
));
422 case PROP_FILTER_ACCOUNT
:
423 empathy_contact_selector_dialog_set_filter_account (dialog
,
424 g_value_get_object (value
));
427 case PROP_SELECTED_ACCOUNT
:
428 empathy_account_chooser_set_account (
429 EMPATHY_ACCOUNT_CHOOSER (priv
->account_chooser
),
430 g_value_get_object (value
));
434 G_OBJECT_WARN_INVALID_PROPERTY_ID (self
, prop_id
, pspec
);
440 empathy_contact_selector_dialog_constructed (GObject
*dialog
)
442 EmpathyContactSelectorDialogPriv
*priv
= GET_PRIV (dialog
);
444 if (EMPATHY_CONTACT_SELECTOR_DIALOG_GET_CLASS (dialog
)->contact_filter
)
446 GtkEntryCompletion
*completion
;
447 GtkTreeModel
*filter
;
449 completion
= gtk_entry_get_completion (GTK_ENTRY (priv
->entry_id
));
450 filter
= gtk_tree_model_filter_new (GTK_TREE_MODEL (priv
->store
), NULL
);
452 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter
),
453 contact_selector_dialog_filter_visible
, dialog
, NULL
);
455 gtk_entry_completion_set_model (completion
, filter
);
456 g_object_unref (filter
);
461 empathy_contact_selector_dialog_dispose (GObject
*object
)
463 EmpathyContactSelectorDialogPriv
*priv
= GET_PRIV (object
);
465 if (priv
->contact_manager
!= NULL
) {
466 g_object_unref (priv
->contact_manager
);
467 priv
->contact_manager
= NULL
;
470 if (priv
->filter_account
!= NULL
) {
471 g_object_unref (priv
->filter_account
);
472 priv
->filter_account
= NULL
;
475 if (G_OBJECT_CLASS (empathy_contact_selector_dialog_parent_class
)->dispose
)
476 G_OBJECT_CLASS (empathy_contact_selector_dialog_parent_class
)->dispose (
481 empathy_contact_selector_dialog_class_init (
482 EmpathyContactSelectorDialogClass
*class)
484 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
486 g_type_class_add_private (class, sizeof (EmpathyContactSelectorDialogPriv
));
488 class->contact_filter
= NULL
;
490 object_class
->constructed
= empathy_contact_selector_dialog_constructed
;
491 object_class
->dispose
= empathy_contact_selector_dialog_dispose
;
492 object_class
->get_property
= empathy_contact_selector_dialog_get_property
;
493 object_class
->set_property
= empathy_contact_selector_dialog_set_property
;
495 g_object_class_install_property (object_class
, PROP_SHOW_ACCOUNT_CHOOSER
,
496 g_param_spec_boolean ("show-account-chooser",
497 "Show Account Chooser",
498 "Whether or not this dialog should show an account chooser",
502 g_object_class_install_property (object_class
, PROP_FILTER_ACCOUNT
,
503 g_param_spec_object ("filter-account",
504 "Account to filter contacts",
505 "if 'show-account-chooser' is unset, only the contacts from this "
506 "account are displayed",
508 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
));
510 g_object_class_install_property (object_class
, PROP_SELECTED_ACCOUNT
,
511 g_param_spec_object ("selected-account",
513 "Current account selected in the account-chooser",
515 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
));
519 empathy_contact_selector_dialog_get_selected (
520 EmpathyContactSelectorDialog
*self
,
521 TpConnection
**connection
,
524 EmpathyContactSelectorDialogPriv
*priv
;
527 g_return_val_if_fail (EMPATHY_IS_CONTACT_SELECTOR_DIALOG (self
), NULL
);
529 priv
= GET_PRIV (self
);
531 if (connection
!= NULL
)
533 if (priv
->show_account_chooser
)
534 *connection
= empathy_account_chooser_get_connection (
535 EMPATHY_ACCOUNT_CHOOSER (priv
->account_chooser
));
542 if (priv
->show_account_chooser
)
543 *account
= empathy_account_chooser_get_account (
544 EMPATHY_ACCOUNT_CHOOSER (priv
->account_chooser
));
550 id
= gtk_entry_get_text (GTK_ENTRY (priv
->entry_id
));
555 empathy_contact_selector_dialog_set_show_account_chooser (
556 EmpathyContactSelectorDialog
*self
,
557 gboolean show_account_chooser
)
559 EmpathyContactSelectorDialogPriv
*priv
;
561 g_return_if_fail (EMPATHY_IS_CONTACT_SELECTOR_DIALOG (self
));
563 priv
= GET_PRIV (self
);
564 priv
->show_account_chooser
= show_account_chooser
;
566 gtk_widget_set_visible (priv
->account_chooser_label
, show_account_chooser
);
567 gtk_widget_set_visible (priv
->account_chooser
, show_account_chooser
);
568 contact_selector_dialog_account_changed_cb (priv
->account_chooser
, self
);
570 g_object_notify (G_OBJECT (self
), "show-account-chooser");
574 empathy_contact_selector_dialog_get_show_account_chooser (
575 EmpathyContactSelectorDialog
*self
)
577 EmpathyContactSelectorDialogPriv
*priv
;
579 g_return_val_if_fail (EMPATHY_IS_CONTACT_SELECTOR_DIALOG (self
), FALSE
);
581 priv
= GET_PRIV (self
);
582 return priv
->show_account_chooser
;
586 empathy_contact_selector_dialog_set_filter_account (
587 EmpathyContactSelectorDialog
*self
,
590 EmpathyContactSelectorDialogPriv
*priv
;
592 g_return_if_fail (EMPATHY_IS_CONTACT_SELECTOR_DIALOG (self
));
594 priv
= GET_PRIV (self
);
595 priv
->filter_account
= g_object_ref (account
);
597 g_object_notify (G_OBJECT (self
), "filter-account");
601 empathy_contact_selector_dialog_get_filter_account (
602 EmpathyContactSelectorDialog
*self
)
604 EmpathyContactSelectorDialogPriv
*priv
;
606 g_return_val_if_fail (EMPATHY_IS_CONTACT_SELECTOR_DIALOG (self
), NULL
);
608 priv
= GET_PRIV (self
);
609 return priv
->filter_account
;