]> git.0d.be Git - empathy.git/commitdiff
Merge branch 'master' into tp-tube
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>
Fri, 24 Apr 2009 15:28:22 +0000 (16:28 +0100)
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>
Fri, 24 Apr 2009 15:28:22 +0000 (16:28 +0100)
98 files changed:
HACKING [new file with mode: 0644]
configure.ac
docs/libempathy-gtk/libempathy-gtk-docs.sgml
docs/libempathy/libempathy-docs.sgml
docs/libempathy/libempathy.types
empathy.doap
help/es/es.po
libempathy-gtk/Makefile.am
libempathy-gtk/empathy-account-chooser.c
libempathy-gtk/empathy-account-chooser.h
libempathy-gtk/empathy-account-widget-irc.c
libempathy-gtk/empathy-account-widget-irc.ui
libempathy-gtk/empathy-avatar-chooser.c
libempathy-gtk/empathy-avatar-chooser.h
libempathy-gtk/empathy-avatar-image.c
libempathy-gtk/empathy-avatar-image.h
libempathy-gtk/empathy-chat.c
libempathy-gtk/empathy-chat.h
libempathy-gtk/empathy-contact-dialogs.c
libempathy-gtk/empathy-contact-dialogs.h
libempathy-gtk/empathy-contact-list-view.c
libempathy-gtk/empathy-contact-list-view.h
libempathy-gtk/empathy-contact-menu.c
libempathy-gtk/empathy-contact-selector.c
libempathy-gtk/empathy-contact-selector.h
libempathy-gtk/empathy-contact-widget.c
libempathy-gtk/empathy-contact-widget.h
libempathy-gtk/empathy-irc-network-dialog.c
libempathy-gtk/empathy-log-window.c
libempathy-gtk/empathy-new-message-dialog.c
libempathy-gtk/empathy-presence-chooser.c
libempathy-gtk/empathy-presence-chooser.h
libempathy-gtk/empathy-presence-chooser.ui [deleted file]
libempathy-gtk/empathy-profile-chooser.c
libempathy-gtk/empathy-profile-chooser.h
libempathy-gtk/empathy-spell-dialog.c [deleted file]
libempathy-gtk/empathy-spell-dialog.h [deleted file]
libempathy-gtk/empathy-spell-dialog.ui [deleted file]
libempathy-gtk/empathy-status-preset-dialog.c [new file with mode: 0644]
libempathy-gtk/empathy-status-preset-dialog.h [new file with mode: 0644]
libempathy-gtk/empathy-status-preset-dialog.ui [new file with mode: 0644]
libempathy-gtk/empathy-theme-boxes.c
libempathy-gtk/empathy-ui-utils.c
libempathy/Makefile.am
libempathy/empathy-account-manager.c
libempathy/empathy-account-manager.h
libempathy/empathy-call-handler.c
libempathy/empathy-chatroom-manager.c
libempathy/empathy-chatroom.c
libempathy/empathy-chatroom.h
libempathy/empathy-contact-factory.c [deleted file]
libempathy/empathy-contact-factory.h [deleted file]
libempathy/empathy-contact-manager.c
libempathy/empathy-contact-manager.h
libempathy/empathy-contact.c
libempathy/empathy-contact.h
libempathy/empathy-dispatch-operation.c
libempathy/empathy-dispatcher.c
libempathy/empathy-dispatcher.h
libempathy/empathy-log-store-empathy.c
libempathy/empathy-tp-call.c
libempathy/empathy-tp-chat.c
libempathy/empathy-tp-chat.h
libempathy/empathy-tp-contact-factory.c
libempathy/empathy-tp-contact-factory.h
libempathy/empathy-tp-contact-list.c
libempathy/empathy-tp-contact-list.h
libempathy/empathy-tp-file.c
libempathy/empathy-tp-file.h
libempathy/empathy-tp-group.c [deleted file]
libempathy/empathy-tp-group.h [deleted file]
libempathy/empathy-tp-tube.c
libempathy/empathy-utils.c
libempathy/empathy-utils.h
megaphone/src/megaphone-applet.c
po/POTFILES.in
po/es.po
python/pyempathy/pyempathy.defs
python/pyempathy/pyempathy.override
python/pyempathygtk/pyempathygtk.defs
python/pyempathygtk/pyempathygtk.override
python/update-binding.sh
src/empathy-accounts-dialog.c
src/empathy-call-window.c
src/empathy-call-window.ui
src/empathy-chat-window.c
src/empathy-chatrooms-window.c
src/empathy-event-manager.c
src/empathy-main-window.c
src/empathy-new-chatroom-dialog.c
src/empathy.c
tests/.gitignore
tests/Makefile.am
tests/check-empathy-helpers.c
tests/contact-run-until-ready-2.c [deleted file]
tests/contact-run-until-ready.c [deleted file]
tests/test-empathy-presence-chooser.c
tests/test-empathy-status-preset-dialog.c [new file with mode: 0644]

diff --git a/HACKING b/HACKING
new file mode 100644 (file)
index 0000000..778244f
--- /dev/null
+++ b/HACKING
@@ -0,0 +1,2 @@
+See http://live.gnome.org/Empathy/ about coding style conventions.
+See also http://live.gnome.org/Empathy/Git to read about our git workflow.
index c3926fdb20aafd2c0e56dc71472ff154cd6323a7..0ff17396d009a367aefc24d767f078f00b004221 100644 (file)
@@ -29,7 +29,7 @@ GLIB_REQUIRED=2.16.0
 GTK_REQUIRED=2.16.0
 GCONF_REQUIRED=1.2.0
 LIBPANELAPPLET_REQUIRED=2.10.0
-TELEPATHY_GLIB_REQUIRED=0.7.23
+TELEPATHY_GLIB_REQUIRED=0.7.27
 MISSION_CONTROL_REQUIRED=4.61
 ENCHANT_REQUIRED=1.2.0
 ISO_CODES_REQUIRED=0.35
index 033ebf018b60419c335f22e7d0dd12d177da6a14..f265de20b4dd899c3c568c306baec2e725695921 100644 (file)
@@ -45,7 +45,6 @@
       <xi:include href="xml/empathy-presence-chooser.xml"/>
       <xi:include href="xml/empathy-profile-chooser.xml"/>
       <xi:include href="xml/empathy-smiley-manager.xml"/>
-      <xi:include href="xml/empathy-spell-dialog.xml"/>
       <xi:include href="xml/empathy-spell.xml"/>
       <xi:include href="xml/empathy-theme-boxes.xml"/>
       <xi:include href="xml/empathy-theme-irc.xml"/>
index a7e3df9b812ca3383a686f3c68719e3694679f12..f3291f7720cd4b041f962fbaba809c970b030cfe 100644 (file)
@@ -21,7 +21,6 @@
       <xi:include href="xml/empathy-call-handler.xml"/>
       <xi:include href="xml/empathy-chatroom-manager.xml"/>
       <xi:include href="xml/empathy-chatroom.xml"/>
-      <xi:include href="xml/empathy-contact-factory.xml"/>
       <xi:include href="xml/empathy-contact-groups.xml"/>
       <xi:include href="xml/empathy-contact-list.xml"/>
       <xi:include href="xml/empathy-contact-manager.xml"/>
@@ -45,7 +44,6 @@
       <xi:include href="xml/empathy-tp-contact-factory.xml"/>
       <xi:include href="xml/empathy-tp-contact-list.xml"/>
       <xi:include href="xml/empathy-tp-file.xml"/>
-      <xi:include href="xml/empathy-tp-group.xml"/>
       <xi:include href="xml/empathy-tp-roomlist.xml"/>
       <xi:include href="xml/empathy-tp-tube.xml"/>
       <xi:include href="xml/empathy-tube-handler.xml"/>
index 1a81ac6718a8f8d79e9365d50bb9f9c67eb406c3..26040474e1bcacf7443c62faefe0ea6475ca9996 100644 (file)
@@ -3,7 +3,6 @@ empathy_call_factory_get_type
 empathy_call_handler_get_type
 empathy_chatroom_get_type
 empathy_chatroom_manager_get_type
-empathy_contact_factory_get_type
 empathy_contact_get_type
 empathy_avatar_get_type
 empathy_contact_list_get_type
@@ -12,7 +11,6 @@ empathy_contact_monitor_get_type
 empathy_dispatcher_get_type
 empathy_dispatch_operation_get_type
 empathy_capabilities_get_type
-empathy_contact_ready_get_type
 empathy_debug_flags_get_type
 empathy_dispatch_operation_state_get_type
 empathy_tp_call_status_get_type
@@ -29,7 +27,6 @@ empathy_tp_chat_get_type
 empathy_tp_contact_factory_get_type
 empathy_tp_contact_list_get_type
 empathy_tp_file_get_type
-empathy_tp_group_get_type
 empathy_tp_roomlist_get_type
 empathy_tp_tube_get_type
 empathy_tube_handler_get_type
index 7b5e7564257500f8f47b82272d0b7655acdf0f14..acd6494bc7f391a1a8bf116f9013f2c66ae05d36 100644 (file)
@@ -6,6 +6,7 @@
          xmlns="http://usefulinc.com/ns/doap#">
   <name xml:lang="en">Empathy Instant Messenger</name>
   <shortdesc xml:lang="en">Send and receive instant messages</shortdesc>
+  <category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
 
   <homepage rdf:resource="http://live.gnome.org/Empathy" />
   <mailing-list rdf:resource="http://lists.freedesktop.org/mailman/listinfo/telepathy" />
index da48d12575d70096917cb675acc6173a06121648..8357dde94e3df46c5c421f691297810a5a0bddff 100644 (file)
@@ -3,8 +3,8 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: empathy.help.HEAD\n"
-"POT-Creation-Date: 2009-03-10 20:40+0000\n"
-"PO-Revision-Date: 2009-03-22 16:23+0100\n"
+"POT-Creation-Date: 2009-04-18 18:34+0000\n"
+"PO-Revision-Date: 2009-04-21 21:04+0200\n"
 "Last-Translator: Jorge González <jorgegonz@svn.gnome.org>\n"
 "Language-Team: Español <gnome-es-list@gnome.org>\n"
 "MIME-Version: 1.0\n"
@@ -15,7 +15,7 @@ msgstr ""
 
 #. When image changes, this message will be marked fuzzy or untranslated for you.
 #. It doesn't matter what you translate it to: it's not used at all.
-#: C/empathy.xml:238(None)
+#: C/empathy.xml:237(None)
 msgid ""
 "@@image: 'figures/empathy-main-window.png'; "
 "md5=38259a866f38ff1f754828e46d2b0e5c"
@@ -199,37 +199,42 @@ msgid "Feedback"
 msgstr "Comentarios"
 
 #: C/empathy.xml:111(para)
+#| msgid ""
+#| "To report a bug or make a suggestion regarding the <application>Empathy</"
+#| "application> application or this manual, follow the directions in the "
+#| "<ulink url=\"ghelp:gnome-feedback\" type=\"help\">GNOME Feedback Page</"
+#| "ulink>."
 msgid ""
 "To report a bug or make a suggestion regarding the <application>Empathy</"
 "application> application or this manual, follow the directions in the <ulink "
-"url=\"ghelp:gnome-feedback\" type=\"help\">GNOME Feedback Page</ulink>."
+"url=\"ghelp:user-guide?feedback\" type=\"help\">GNOME Feedback Page</ulink>."
 msgstr ""
 "Para informar de un fallo, o hacer alguna sugerencia concerniente a la "
 "aplicación <application>Empathy</application> o este manual, siga las "
-"indicaciones en la <ulink url=\"ghelp:gnome-feedback\" type=\"help\">Página "
-"de comentarios de GNOME</ulink>."
+"indicaciones en la <ulink url=\"ghelp:user-guide?feedback\" type=\"help"
+"\">Página de comentarios de GNOME</ulink>."
 
-#: C/empathy.xml:119(para)
+#: C/empathy.xml:118(para)
 msgid "Empathy is an application for instant messaging."
 msgstr "Empathy es una aplicación para mensajería instantánea."
 
-#: C/empathy.xml:127(primary) C/empathy.xml:0(application)
+#: C/empathy.xml:126(primary) C/empathy.xml:0(application)
 msgid "Empathy"
 msgstr "Empathy"
 
-#: C/empathy.xml:130(primary)
+#: C/empathy.xml:129(primary)
 msgid "empathy"
 msgstr "empathy"
 
-#: C/empathy.xml:131(secondary)
+#: C/empathy.xml:130(secondary)
 msgid "istant messaging"
 msgstr "mensajería instantánea"
 
-#: C/empathy.xml:135(title)
+#: C/empathy.xml:134(title)
 msgid "Introduction"
 msgstr "Introducción"
 
-#: C/empathy.xml:136(para)
+#: C/empathy.xml:135(para)
 msgid ""
 "<application>Empathy</application> is a multi-protocol instant messaging "
 "program for the GNOME Desktop. With <application>Empathy</application> you "
@@ -241,47 +246,47 @@ msgstr ""
 "application> puede mantenerse en contacto con sus amigos a través de muchos "
 "de los servicios de mensajería instantánea soportados."
 
-#: C/empathy.xml:146(acronym)
+#: C/empathy.xml:145(acronym)
 msgid "AIM"
 msgstr "AIM"
 
-#: C/empathy.xml:150(para)
+#: C/empathy.xml:149(para)
 msgid "Google Talk"
 msgstr "Google Talk"
 
-#: C/empathy.xml:155(para) C/empathy.xml:1090(title)
+#: C/empathy.xml:154(para) C/empathy.xml:1089(title)
 msgid "ICQ"
 msgstr "ICQ"
 
-#: C/empathy.xml:161(acronym)
+#: C/empathy.xml:160(acronym)
 msgid "IRC"
 msgstr "IRC"
 
-#: C/empathy.xml:165(para)
+#: C/empathy.xml:164(para)
 msgid "Jabber (or <acronym>XMPP</acronym>)"
 msgstr "Jabber (o <acronym>XMPP</acronym>)"
 
-#: C/empathy.xml:171(acronym)
+#: C/empathy.xml:170(acronym)
 msgid "MSN"
 msgstr "MSN"
 
-#: C/empathy.xml:175(para) C/empathy.xml:442(para) C/empathy.xml:1050(title)
+#: C/empathy.xml:174(para) C/empathy.xml:441(para) C/empathy.xml:1049(title)
 msgid "Salut"
 msgstr "Salut"
 
-#: C/empathy.xml:181(acronym)
+#: C/empathy.xml:180(acronym)
 msgid "SIP"
 msgstr "SIP"
 
-#: C/empathy.xml:185(para) C/empathy.xml:920(title)
+#: C/empathy.xml:184(para) C/empathy.xml:919(title)
 msgid "Yahoo"
 msgstr "Yahoo"
 
-#: C/empathy.xml:190(para)
+#: C/empathy.xml:189(para)
 msgid "And many others..."
 msgstr "Y muchos otros…"
 
-#: C/empathy.xml:141(para)
+#: C/empathy.xml:140(para)
 msgid ""
 "<application>Empathy</application> supports the following services: "
 "<placeholder-1/>"
@@ -289,24 +294,24 @@ msgstr ""
 "<application>Empathy</application> soporta los siguientes servicios: "
 "<placeholder-1/>"
 
-#: C/empathy.xml:199(title)
+#: C/empathy.xml:198(title)
 msgid "Getting Started"
 msgstr "Inicio"
 
-#: C/empathy.xml:202(title)
+#: C/empathy.xml:201(title)
 msgid "Starting Empathy"
 msgstr "Iniciar Empathy"
 
-#: C/empathy.xml:203(para)
+#: C/empathy.xml:202(para)
 msgid "You can start <application>Empathy</application> in the following ways:"
 msgstr ""
 "Puede iniciar <application>Empathy</application> de las siguientes formas:"
 
-#: C/empathy.xml:207(term)
+#: C/empathy.xml:206(term)
 msgid "<guimenu>Applications</guimenu> menu"
 msgstr "Menú <guimenu>Aplicaciones</guimenu>"
 
-#: C/empathy.xml:209(para)
+#: C/empathy.xml:208(para)
 msgid ""
 "Choose <menuchoice><guisubmenu>Internet</guisubmenu><guimenuitem>Empathy "
 "Instant Messenger</guimenuitem></menuchoice>."
@@ -314,23 +319,23 @@ msgstr ""
 "Elija <menuchoice><guisubmenu>Internet</guisubmenu><guimenuitem>Mensajería "
 "instantánea Empathy</guimenuitem></menuchoice>."
 
-#: C/empathy.xml:218(term)
+#: C/empathy.xml:217(term)
 msgid "Command line"
 msgstr "Línea de comandos"
 
-#: C/empathy.xml:220(para)
+#: C/empathy.xml:219(para)
 msgid "Type <command>empathy</command> and then press <keycap>Enter</keycap>."
 msgstr "Escriba <command>empathy</command> y pulse <keycap>intro</keycap>."
 
-#: C/empathy.xml:229(title)
+#: C/empathy.xml:228(title)
 msgid "When You Start Empathy"
 msgstr "Al iniciar Empathy"
 
-#: C/empathy.xml:234(title)
+#: C/empathy.xml:233(title)
 msgid "<application>Empathy</application> Main Window"
 msgstr "Ventana principal de <application>Empathy</application>"
 
-#: C/empathy.xml:241(phrase)
+#: C/empathy.xml:240(phrase)
 msgid ""
 "Shows <placeholder-1/> main window. Contains the titlebar, the menubar, "
 "contact list, status icon and status arrow button list."
@@ -339,7 +344,7 @@ msgstr ""
 "título, la barra de menú, la lista de contactos, el icono de estado y la "
 "lista de estados."
 
-#: C/empathy.xml:230(para)
+#: C/empathy.xml:229(para)
 msgid ""
 "When you start <application>Empathy</application> the following window is "
 "shown. <placeholder-1/>"
@@ -347,54 +352,54 @@ msgstr ""
 "Se mostrará la siguiente ventana al iniciar <application>Empathy</"
 "application>. <placeholder-1/>"
 
-#: C/empathy.xml:256(title)
+#: C/empathy.xml:255(title)
 msgid "<application>Empathy</application> Main Components"
 msgstr "Componentes principales de <application>Empathy</application>"
 
-#: C/empathy.xml:263(para)
+#: C/empathy.xml:262(para)
 msgid "Component"
 msgstr "Componente"
 
-#: C/empathy.xml:266(para)
+#: C/empathy.xml:265(para)
 msgid "Description"
 msgstr "Descripción"
 
-#: C/empathy.xml:273(para)
+#: C/empathy.xml:272(para)
 msgid "Menubar"
 msgstr "Barra de menú"
 
-#: C/empathy.xml:276(para)
+#: C/empathy.xml:275(para)
 msgid ""
 "Contains menus used to perform actions in <application>Empathy</application>."
 msgstr ""
 "Contiene los menús usados para realizar acciones en <application>Empathy</"
 "application>."
 
-#: C/empathy.xml:283(para)
+#: C/empathy.xml:282(para)
 msgid "Status Drop-Down List"
 msgstr "Lista desplegable de estados"
 
-#: C/empathy.xml:286(para)
+#: C/empathy.xml:285(para)
 msgid "Allows to update the status."
 msgstr "Permite actualizar el estado."
 
-#: C/empathy.xml:293(para)
+#: C/empathy.xml:292(para)
 msgid "Account Button"
 msgstr "Botón Cuentas"
 
-#: C/empathy.xml:296(para)
+#: C/empathy.xml:295(para)
 msgid "Opens the <guilabel>Accounts</guilabel> dialog."
 msgstr "Abre el diálogo <guilabel>Cuentas</guilabel>."
 
-#: C/empathy.xml:303(para)
+#: C/empathy.xml:302(para)
 msgid "Contact List"
 msgstr "Lista de contactos"
 
-#: C/empathy.xml:306(para)
+#: C/empathy.xml:305(para)
 msgid "Shows all the available contacts and their associated status."
 msgstr "Muestra todos los contactos disponibles y su estado asociado."
 
-#: C/empathy.xml:252(para)
+#: C/empathy.xml:251(para)
 msgid ""
 "<xref linkend=\"empathy-TBL-1\"/> describes the components of "
 "<application>Empathy</application>'s main window. <table frame=\"topbot\" id="
@@ -410,11 +415,11 @@ msgstr ""
 "\"colspec1\" colwidth=\"70.61*\"/><placeholder-2/><placeholder-3/></tgroup></"
 "table>"
 
-#: C/empathy.xml:320(title)
+#: C/empathy.xml:319(title)
 msgid "Accounts"
 msgstr "Cuentas"
 
-#: C/empathy.xml:321(para)
+#: C/empathy.xml:320(para)
 msgid ""
 "To use <application>Empathy</application> you need at least one account of "
 "the supported services."
@@ -422,7 +427,7 @@ msgstr ""
 "Para usar <application>Empathy</application> debe tener al menos una cuenta "
 "de los servicios soportados."
 
-#: C/empathy.xml:324(para)
+#: C/empathy.xml:323(para)
 msgid ""
 "If you don't already have an account and you don't have your <emphasis>user "
 "name</emphasis> and <emphasis>password</emphasis>, you need to register a "
@@ -432,7 +437,7 @@ msgstr ""
 "<emphasis>contraseña</emphasis>, debe registrar una cuenta nueva (consulte "
 "<xref linkend=\"empathy-register-account\"/>)."
 
-#: C/empathy.xml:329(para)
+#: C/empathy.xml:328(para)
 msgid ""
 "In order to talk with other users, also called <emphasis>contacts</"
 "emphasis>, you need to use the same service they are using. If, for example, "
@@ -444,7 +449,7 @@ msgstr ""
 "de sus contactos está usando el servicio <emphasis role=\"strong\">Jabber</"
 "emphasis>, necesita tener una cuenta registrada en ese servicio."
 
-#: C/empathy.xml:336(para)
+#: C/empathy.xml:335(para)
 msgid ""
 "<application>Empathy</application> can handle as many accounts on any "
 "supported services as you want and you can have them all open at the same "
@@ -454,11 +459,11 @@ msgstr ""
 "cualquiera de los servicios soportados que quiera añadir y puede tener todas "
 "ellas abiertas al mismo tiempo."
 
-#: C/empathy.xml:342(title)
+#: C/empathy.xml:341(title)
 msgid "Registering an Account"
 msgstr "Registrar una cuenta"
 
-#: C/empathy.xml:343(para)
+#: C/empathy.xml:342(para)
 msgid ""
 "You can freely register an account on any of the following services. Follow "
 "the instructions reported on each website on how to register your new "
@@ -476,7 +481,7 @@ msgstr ""
 
 #. Translators: try to find a localized version of the
 #.         registration service website
-#: C/empathy.xml:361(para)
+#: C/empathy.xml:360(para)
 msgid ""
 "The <ulink type=\"http\" url=\"http://dashboard.aim.com/aim\">AIM</ulink> "
 "service."
@@ -486,7 +491,7 @@ msgstr ""
 
 #. Translators: try to find a localized version of the
 #.         registration service website
-#: C/empathy.xml:368(para)
+#: C/empathy.xml:367(para)
 msgid ""
 "The <ulink type=\"http\" url=\"http://www.google.com/talk/\">Google Talk</"
 "ulink> service."
@@ -496,7 +501,7 @@ msgstr ""
 
 #. Translators: try to find a localized version of the
 #.         registration service website
-#: C/empathy.xml:376(para)
+#: C/empathy.xml:375(para)
 msgid ""
 "The <ulink type=\"http\" url=\"https://www.icq.com/register/\">ICQ</ulink> "
 "service."
@@ -506,7 +511,7 @@ msgstr ""
 
 #. Translators: try to find a localized version of the
 #.         registration service website
-#: C/empathy.xml:383(para)
+#: C/empathy.xml:382(para)
 msgid ""
 "The <ulink type=\"http\" url=\"https://accountservices.passport.net\">MSN</"
 "ulink> service."
@@ -516,7 +521,7 @@ msgstr ""
 
 #. Translators: try to find a localized version of the
 #.         registration service website
-#: C/empathy.xml:390(para)
+#: C/empathy.xml:389(para)
 msgid ""
 "The <ulink type=\"http\" url=\"https://login.yahoo.com/config/login\">Yahoo</"
 "ulink> service."
@@ -524,12 +529,12 @@ msgstr ""
 "El servicio <ulink type=\"http\" url=\"https://login.yahoo.com/config/login"
 "\">Yahoo</ulink>."
 
-#: C/empathy.xml:352(para)
+#: C/empathy.xml:351(para)
 msgid "Click on the name of the service to visit its website: <placeholder-1/>"
 msgstr ""
 "Pulse en el nombre del servicio para visitar su página web: <placeholder-1/>"
 
-#: C/empathy.xml:396(para)
+#: C/empathy.xml:395(para)
 msgid ""
 "For registering a <acronym>SIP</acronym> account, you can use one of the "
 "following service:"
@@ -539,7 +544,7 @@ msgstr ""
 
 #. Translators: try to find a localized version of the
 #.         registration service website
-#: C/empathy.xml:405(para)
+#: C/empathy.xml:404(para)
 msgid ""
 "The <ulink type=\"http\" url=\"https://www.ekiga.net/index.php?page=register"
 "\">Ekiga</ulink> service."
@@ -549,7 +554,7 @@ msgstr ""
 
 #. Translators: try to find a localized version of the
 #.         registration service website
-#: C/empathy.xml:412(para)
+#: C/empathy.xml:411(para)
 msgid ""
 "The <ulink type=\"http\" url=\"http://account2.freeworlddialup.com/index.php?"
 "section_id=94\"><acronym>FWD</acronym></ulink> (Free World Dialup) service."
@@ -559,7 +564,7 @@ msgstr ""
 
 #. Translators: try to find a localized version of the
 #.         registration service website
-#: C/empathy.xml:420(para)
+#: C/empathy.xml:419(para)
 msgid ""
 "The <ulink type=\"http\" url=\"https://signup.sipphone.com/new-users/app?"
 "class=NewUser;proc=start\">Sipphone</ulink> service."
@@ -567,7 +572,7 @@ msgstr ""
 "El servicio <ulink type=\"http\" url=\"https://signup.sipphone.com/new-users/"
 "app?class=NewUser;proc=start\">Sipphone</ulink>."
 
-#: C/empathy.xml:426(para)
+#: C/empathy.xml:425(para)
 msgid ""
 "For registering a <emphasis role=\"strong\">Jabber</emphasis> account, you "
 "can use the automatic account creation of <application>Empathy</"
@@ -583,7 +588,7 @@ msgstr ""
 "sabe que funcionan con <application>Empathy</application> es <ulink type="
 "\"http\" url=\"http://www.jabber.org/web/Jabber.org\">jabber.org</ulink>."
 
-#: C/empathy.xml:434(para)
+#: C/empathy.xml:433(para)
 msgid ""
 "If you already have a <emphasis role=\"strong\">Jabber</emphasis> account, "
 "you can use one of the following services:"
@@ -591,12 +596,12 @@ msgstr ""
 "Si ya tiene una cuenta <emphasis role=\"strong\">Jabber</emphasis> puede "
 "usar uno de los siguientes servicios:"
 
-#: C/empathy.xml:451(title)
+#: C/empathy.xml:450(title)
 msgid "Adding your Account to <application>Empathy</application>"
 msgstr "Añadir su cuenta a <application>Empathy</application>"
 
-#: C/empathy.xml:456(para) C/empathy.xml:534(para) C/empathy.xml:586(para)
-#: C/empathy.xml:619(para) C/empathy.xml:649(para) C/empathy.xml:672(para)
+#: C/empathy.xml:455(para) C/empathy.xml:533(para) C/empathy.xml:585(para)
+#: C/empathy.xml:618(para) C/empathy.xml:648(para) C/empathy.xml:671(para)
 msgid ""
 "From the <link linkend=\"empathy-FIG-mainwindow\">main window </link> "
 "(<guilabel>Contact List</guilabel>) click on the account button or press "
@@ -606,7 +611,7 @@ msgstr ""
 "(<guilabel>Lista de contactos</guilabel>) pulse en el botón de cuentas o "
 "<keycap>F4</keycap> para abrir el diálogo <guilabel>Cuentas</guilabel>."
 
-#: C/empathy.xml:468(para) C/empathy.xml:485(para)
+#: C/empathy.xml:467(para) C/empathy.xml:484(para)
 msgid ""
 "From the <guilabel>Type</guilabel> drop-down list choose the service you "
 "wish to add an account for, then click on the <guibutton>Create</guibutton> "
@@ -616,7 +621,7 @@ msgstr ""
 "el que quiere crear la cuenta, después pulse en el botón <guibutton>Crear</"
 "guibutton>."
 
-#: C/empathy.xml:464(para)
+#: C/empathy.xml:463(para)
 msgid ""
 "If it is the first time you launch <application>Empathy</application>: "
 "<placeholder-1/>"
@@ -624,15 +629,15 @@ msgstr ""
 "Si Ã©sta es la primera vez que lanza <application>Empathy</application>: "
 "<placeholder-1/>"
 
-#: C/empathy.xml:480(para)
+#: C/empathy.xml:479(para)
 msgid "Click on the <guilabel>Add</guilabel> button."
 msgstr "Pulse el botón <guibutton>Añadir</guibutton>."
 
-#: C/empathy.xml:476(para)
+#: C/empathy.xml:475(para)
 msgid "Otherwise: <placeholder-1/>"
 msgstr "De otra forma: <placeholder-1/>"
 
-#: C/empathy.xml:495(para)
+#: C/empathy.xml:494(para)
 msgid ""
 "Fill the required fields with your <emphasis>user name</emphasis> and "
 "<emphasis>password</emphasis>. Optionally, you can modify some advanced "
@@ -644,7 +649,7 @@ msgstr ""
 "opciones avanzadas. Para obtener más información consulte <xref linkend="
 "\"empathy-advanced-options\"/>."
 
-#: C/empathy.xml:504(para) C/empathy.xml:567(para)
+#: C/empathy.xml:503(para) C/empathy.xml:566(para)
 msgid ""
 "To enable the new account, select the <guilabel>Enabled</guilabel> check-box "
 "next to the name of the account in the box on the left."
@@ -653,7 +658,7 @@ msgstr ""
 "<guilabel>Activada</guilabel> junto al nombre de la cuenta, en la caja de la "
 "izquierda."
 
-#: C/empathy.xml:452(para)
+#: C/empathy.xml:451(para)
 msgid ""
 "To add your account to <application>Empathy</application>, proceed as "
 "follows: <placeholder-1/>"
@@ -661,11 +666,11 @@ msgstr ""
 "Para añadir su cuenta a <application>Empathy</application>, proceda como "
 "sigue: <placeholder-1/>"
 
-#: C/empathy.xml:514(title)
+#: C/empathy.xml:513(title)
 msgid "Importing Accounts"
 msgstr "Importar cuentas"
 
-#: C/empathy.xml:515(para)
+#: C/empathy.xml:514(para)
 msgid ""
 "If you use another instant messaging program, you can import the accounts "
 "from that program into <application>Empathy</application>"
@@ -673,7 +678,7 @@ msgstr ""
 "Si usa otro programa de mensajería instantánea puede importar las cuentas de "
 "ese programa en <application>Empathy</application>"
 
-#: C/empathy.xml:521(para)
+#: C/empathy.xml:520(para)
 msgid ""
 "At the moment <application>Empathy</application> can import the accounts "
 "only from the instant messaging program <application>Pidgin</application>. "
@@ -685,7 +690,7 @@ msgstr ""
 "información acerca de <application>Pidgin</application> consulte la <ulink "
 "type=\"http\" url=\"http://www.pidgin.im/\">página web de Pidgin</ulink>."
 
-#: C/empathy.xml:542(para)
+#: C/empathy.xml:541(para)
 msgid ""
 "Click on the <guibutton>Import Accounts...</guibutton> button to open the "
 "<guilabel>Import Accounts</guilabel> dialog."
@@ -693,7 +698,7 @@ msgstr ""
 "Pulse en el botón <guibutton>Importar cuentas...</guibutton> para abrir el "
 "diálogo <guilabel>Importar cuentas</guilabel>."
 
-#: C/empathy.xml:549(para)
+#: C/empathy.xml:548(para)
 msgid ""
 "Select the accounts you would like to import by clicking on the "
 "<guilabel>Import</guilabel> check-box."
@@ -701,7 +706,7 @@ msgstr ""
 "Seleccione la cuenta que quiere importar pulsando en la casilla de selección "
 "<guilabel>Importar</guilabel>."
 
-#: C/empathy.xml:555(para)
+#: C/empathy.xml:554(para)
 msgid ""
 "When you have selected all the desired accounts, click <guibutton>OK</"
 "guibutton> to import them. If you don't want to import the accounts, click "
@@ -711,7 +716,7 @@ msgstr ""
 "<guibutton>Aceptar</guibutton> para importarlas. Si no quiere importar las "
 "cuentas, pulse el botón <guibutton>Cancelar</guibutton>."
 
-#: C/empathy.xml:563(para)
+#: C/empathy.xml:562(para)
 msgid ""
 "When you import a new account into <application>Empathy</application>, it "
 "will not be enabled by default."
@@ -719,7 +724,7 @@ msgstr ""
 "Al importar una cuenta nueva en <application>Empathy</application> no se "
 "activará de forma predeterminada."
 
-#: C/empathy.xml:530(para)
+#: C/empathy.xml:529(para)
 msgid ""
 "To import the accounts into <application>Empathy</application>, proceed as "
 "follows: <placeholder-1/>"
@@ -727,19 +732,19 @@ msgstr ""
 "Para importar cuentas en <application>Empathy</application> proceda como "
 "sigue: <placeholder-1/>"
 
-#: C/empathy.xml:579(title)
+#: C/empathy.xml:578(title)
 msgid "Editing an Account"
 msgstr "Editar una cuenta"
 
-#: C/empathy.xml:594(para)
+#: C/empathy.xml:593(para)
 msgid "Select the account you wish to edit in the box on the left."
 msgstr "Seleccione la cuenta que quiere editar en la caja a la izquierda."
 
-#: C/empathy.xml:600(para)
+#: C/empathy.xml:599(para)
 msgid "Modify the desired data."
 msgstr "Modifique los datos deseados."
 
-#: C/empathy.xml:580(para)
+#: C/empathy.xml:579(para)
 msgid ""
 "To edit one of your accounts, i.e. to change the <emphasis>password</"
 "emphasis> or your <emphasis>user name</emphasis>, proceed as follows: "
@@ -749,12 +754,12 @@ msgstr ""
 "<emphasis>contraseña</emphasis> o su <emphasis>usuario</emphasis>, proceda "
 "como sigue: <placeholder-1/>"
 
-#: C/empathy.xml:608(para)
+#: C/empathy.xml:607(para)
 msgid ""
 "Based on the type of the account, it is possibile to edit different settings."
 msgstr "Basado en el tipo de cuenta, es posible editar diferentes ajustes."
 
-#: C/empathy.xml:627(para)
+#: C/empathy.xml:626(para)
 msgid ""
 "Select the account you wish to edit in the box on the left and double-click "
 "on its name."
@@ -762,11 +767,11 @@ msgstr ""
 "Seleccione la cuenta que quiere editar en la caja de la izquierda y pulse "
 "dos veces en su nombre."
 
-#: C/empathy.xml:633(para)
+#: C/empathy.xml:632(para)
 msgid "Change the name of the account as you desire."
 msgstr "Cambie el nombre de la cuenta como desee."
 
-#: C/empathy.xml:614(para)
+#: C/empathy.xml:613(para)
 msgid ""
 "To modify the identifier of an account, how <application>Empathy</"
 "application> identifies an account, proceed as follows: <placeholder-1/>"
@@ -775,15 +780,15 @@ msgstr ""
 "<application>Empathy</application> identifica a la cuente, proceda como "
 "sigue: <placeholder-1/>"
 
-#: C/empathy.xml:642(title)
+#: C/empathy.xml:641(title)
 msgid "Disabling and Removing an Account"
 msgstr "Desactivar y quitaruna cuenta"
 
-#: C/empathy.xml:643(para)
+#: C/empathy.xml:642(para)
 msgid "To disable an account, proceed as follows:"
 msgstr "Para desactivar una cuenta, proceda como sigue:"
 
-#: C/empathy.xml:658(para)
+#: C/empathy.xml:657(para)
 msgid ""
 "Select the account you wish to disable in the box on the left of the dialog "
 "and deselect the <guilabel>Enabled</guilabel> check-box."
@@ -792,22 +797,22 @@ msgstr ""
 "diálogo y deselecicone la casilla de verificación <guilabel>Activada</"
 "guilabel>."
 
-#: C/empathy.xml:666(para)
+#: C/empathy.xml:665(para)
 msgid "To remove an account, proceed as follows:"
 msgstr "Para quitar una cuenta, proceda como sigue:"
 
-#: C/empathy.xml:681(para)
+#: C/empathy.xml:680(para)
 msgid ""
 "Select the account you wish to disable in the box on the left of the dialog."
 msgstr ""
 "Seleccione la cuenta que desea desactivar en la caja a la izquierda del "
 "diálogo."
 
-#: C/empathy.xml:687(para)
+#: C/empathy.xml:686(para)
 msgid "Click on the <guibutton>Remove</guibutton> button."
 msgstr "Pulse en el botón <guibutton>Quitar</guibutton>."
 
-#: C/empathy.xml:692(para)
+#: C/empathy.xml:691(para)
 msgid ""
 "A dialog will be shown asking for confirmation. Click on the "
 "<guibutton>Remove</guibutton> button to remove the account."
@@ -815,11 +820,11 @@ msgstr ""
 "Se mostrará un diálogo preguntando por una confirmación. Pulse en el botón "
 "<guibutton>Quitar</guibutton> para quitar la cuenta."
 
-#: C/empathy.xml:702(title)
+#: C/empathy.xml:701(title)
 msgid "Editing Personal Information"
 msgstr "Editar información personal"
 
-#: C/empathy.xml:703(para)
+#: C/empathy.xml:702(para)
 msgid ""
 "To change your personal information, your alias and your icon (the image "
 "that other contacts will see of you), for each of your accounts, proceed as "
@@ -829,7 +834,7 @@ msgstr ""
 "que otros contactos le ven), para cada una de las cuentas, proceda como "
 "sigue:"
 
-#: C/empathy.xml:711(para)
+#: C/empathy.xml:710(para)
 msgid ""
 "From the <link linkend=\"empathy-FIG-mainwindow\">main window</link>, select "
 "<menuchoice><guimenu>Edit</guimenu><guimenuitem>Personal Information</"
@@ -839,7 +844,7 @@ msgstr ""
 "seleccione <menuchoice><guimenu>Editar</guimenu><guimenuitem>Información "
 "personal</guimenuitem></menuchoice>."
 
-#: C/empathy.xml:720(para)
+#: C/empathy.xml:719(para)
 msgid ""
 "From the <guilabel>Account</guilabel> drop-down list, choose the account you "
 "want to edit."
@@ -847,11 +852,11 @@ msgstr ""
 "Desde la lista desplegable <guilabel>Cuenta</guilabel>, elija la cuenta que "
 "quiere editar."
 
-#: C/empathy.xml:726(para)
+#: C/empathy.xml:725(para)
 msgid "In the <guilabel>Alias</guilabel> text box, write your new alias."
 msgstr "En la caja de texto <guilabel>Apodo</guilabel> escriba su nuevo apodo."
 
-#: C/empathy.xml:732(para)
+#: C/empathy.xml:731(para)
 msgid ""
 "To change your icon, click on the person-looking button and choose an image "
 "file."
@@ -859,11 +864,11 @@ msgstr ""
 "Para cambiar su icono pulse en el botón de apariencia personal y elija un "
 "archivo de imagen."
 
-#: C/empathy.xml:738(para) C/empathy.xml:1319(para) C/empathy.xml:1353(para)
+#: C/empathy.xml:737(para) C/empathy.xml:1318(para) C/empathy.xml:1352(para)
 msgid "When done, click <guibutton>Close</guibutton>."
 msgstr "Cuando termine pulse <guibutton>Cerrar</guibutton>."
 
-#: C/empathy.xml:746(para)
+#: C/empathy.xml:745(para)
 msgid ""
 "An <emphasis>alias</emphasis> is an alternative way you can identify "
 "yourself. You can use your real name or a nickname."
@@ -871,11 +876,11 @@ msgstr ""
 "Un <emphasis>apodo</emphasis> es una forma alternativa por la que se puede "
 "identificar. Puede usar su nombre real o un apodo."
 
-#: C/empathy.xml:756(title)
+#: C/empathy.xml:755(title)
 msgid "Advanced Options"
 msgstr "Opciones avanzadas"
 
-#: C/empathy.xml:757(para)
+#: C/empathy.xml:756(para)
 msgid ""
 "Based on the service you are using, it is possible to configure more "
 "advanced options to modify the normal behavior of <application>Empathy</"
@@ -885,7 +890,7 @@ msgstr ""
 "avanzadas para modificar el comportamiento normal de <application>Empathy</"
 "application>."
 
-#: C/empathy.xml:762(para)
+#: C/empathy.xml:761(para)
 msgid ""
 "To configure these options, when you are <link linkend=\"empathy-create-"
 "account\">adding a new account</link>, click on the drop-down section "
@@ -895,15 +900,15 @@ msgstr ""
 "account\">añadiendo una cuenta nueva</link>, pulse la sección desplegable "
 "<guilabel>Avanzadas</guilabel>."
 
-#: C/empathy.xml:770(title)
+#: C/empathy.xml:769(title)
 msgid "Jabber (or <acronym>XMPP</acronym>) and Google Talk"
 msgstr "Jabber (o <acronym>XMPP</acronym>) y Google Talk"
 
-#: C/empathy.xml:777(guilabel)
+#: C/empathy.xml:776(guilabel)
 msgid "Encryption required (TLS/SSL)"
 msgstr "Se requiere cifrado (TLS/SSL)"
 
-#: C/empathy.xml:780(para)
+#: C/empathy.xml:779(para)
 msgid ""
 "Select this option in order to use some sort of encryption during your "
 "conversations."
@@ -911,11 +916,11 @@ msgstr ""
 "Seleccione esta opción para usar algún tipo de cifrado durante sus "
 "conversaciones."
 
-#: C/empathy.xml:788(guilabel)
+#: C/empathy.xml:787(guilabel)
 msgid "Ignore SSL certificate errors"
 msgstr "Ignorar los errores de certificados SSL"
 
-#: C/empathy.xml:791(para)
+#: C/empathy.xml:790(para)
 msgid ""
 "Select this option in order to ignore the errors that can be generated by "
 "some types of security certificates. Usually these certificates are called "
@@ -925,7 +930,7 @@ msgstr ""
 "tipos de certificados de seguridad. Generalmente esos certificados se llaman "
 "autofirmados."
 
-#: C/empathy.xml:799(para)
+#: C/empathy.xml:798(para)
 msgid ""
 "Select this option only if you are sure the certificate is secure and you "
 "can trust it."
@@ -933,20 +938,11 @@ msgstr ""
 "Seleccione esta opción sólo si está seguro de que su certificado es seguro y "
 "puede confiar en Ã©l."
 
-#: C/empathy.xml:809(guilabel)
+#: C/empathy.xml:808(guilabel)
 msgid "Resource"
 msgstr "Recurso"
 
-#: C/empathy.xml:812(para)
-#| msgid ""
-#| "Use this text box to set a name with which you can identify the running "
-#| "program based on where you are running it. With this option, and the "
-#| "<guilabel>Priority</guilabel> one, you can use your account "
-#| "simultaneously in two different devices. For example, if you set one "
-#| "device to <replaceable>desktop</replaceable> and of the other one to "
-#| "<replaceable>mobile</replaceable>, you can connect with both of them and "
-#| "based on the <guilabel>Priority</guilabel> value you will receive "
-#| "messages on one of the two devices or both."
+#: C/empathy.xml:811(para)
 msgid ""
 "Use this text box to set a name with which you can identify the running "
 "program based on where you are running it. With this option, and the "
@@ -966,7 +962,7 @@ msgstr ""
 "dispositivos y basándose en el valor <guilabel>Prioridad</guilabel> recibirá "
 "los mensajes en uno de los dispositivos o en ambos."
 
-#: C/empathy.xml:825(para)
+#: C/empathy.xml:824(para)
 msgid ""
 "This can be useful if you have two devices, a main one and a portable one, "
 "and you move away from the main one bringing with you the other: you can "
@@ -978,7 +974,7 @@ msgstr ""
 "mensajes desde su cuenta con el dispositivo portable incluso si no "
 "desconecta el principal."
 
-#: C/empathy.xml:834(para)
+#: C/empathy.xml:833(para)
 msgid ""
 "If you set the same value for this text box on both the devices, when you "
 "connect with one of them, the other one will be disconnected, even if you "
@@ -989,11 +985,11 @@ msgstr ""
 "establece un valor diferente en la caja incrementable <guilabel>Prioridad</"
 "guilabel>."
 
-#: C/empathy.xml:847(guilabel)
+#: C/empathy.xml:846(guilabel)
 msgid "Priority"
 msgstr "Prioridad"
 
-#: C/empathy.xml:850(para)
+#: C/empathy.xml:849(para)
 msgid ""
 "Use this spin box to indicate wich device, set in the <guilabel>Resource</"
 "guilabel> text box, will receive the new messages. The higher the number, "
@@ -1005,7 +1001,7 @@ msgstr ""
 "Cuanto mayor sea el número, mayor será la prioridad: recibirá los mensajes "
 "nuevos en el dispositivo con el número más alto."
 
-#: C/empathy.xml:857(para)
+#: C/empathy.xml:856(para)
 msgid ""
 "You can set values in the range from <literal>-128</literal> to "
 "<literal>127</literal>."
@@ -1013,7 +1009,7 @@ msgstr ""
 "Puede establecer valores en el rango de <literal>-128</literal> a "
 "<literal>127</literal>."
 
-#: C/empathy.xml:863(para)
+#: C/empathy.xml:862(para)
 msgid ""
 "If you set the same value of this spin box in both the devices, you will "
 "receive messages on both of them."
@@ -1021,13 +1017,13 @@ msgstr ""
 "Si establece el mismo valor de esta caja incrementable en ambos "
 "dispositivos, recibirá mensajes en ambos dos."
 
-#: C/empathy.xml:880(guilabel) C/empathy.xml:973(guilabel)
-#: C/empathy.xml:1021(guilabel) C/empathy.xml:1115(guilabel)
+#: C/empathy.xml:879(guilabel) C/empathy.xml:972(guilabel)
+#: C/empathy.xml:1020(guilabel) C/empathy.xml:1114(guilabel)
 msgid "Server"
 msgstr "Servidor"
 
-#: C/empathy.xml:883(para) C/empathy.xml:976(para) C/empathy.xml:1024(para)
-#: C/empathy.xml:1118(para)
+#: C/empathy.xml:882(para) C/empathy.xml:975(para) C/empathy.xml:1023(para)
+#: C/empathy.xml:1117(para)
 msgid ""
 "Use this text box to write the name of the server you want to use for this "
 "service."
@@ -1035,20 +1031,20 @@ msgstr ""
 "Use esta caja de texto para escribir el nombre del servidor que quiere usar "
 "para este servicio."
 
-#: C/empathy.xml:891(guilabel) C/empathy.xml:984(guilabel)
-#: C/empathy.xml:1032(guilabel) C/empathy.xml:1126(guilabel)
+#: C/empathy.xml:890(guilabel) C/empathy.xml:983(guilabel)
+#: C/empathy.xml:1031(guilabel) C/empathy.xml:1125(guilabel)
 msgid "Port"
 msgstr "Puerto"
 
-#: C/empathy.xml:894(para) C/empathy.xml:987(para) C/empathy.xml:1035(para)
-#: C/empathy.xml:1129(para)
+#: C/empathy.xml:893(para) C/empathy.xml:986(para) C/empathy.xml:1034(para)
+#: C/empathy.xml:1128(para)
 msgid "Use this spin box to set the number of the port of the server to use."
 msgstr ""
 "Use esta caja incrementable para establecer el número del puerto del "
 "servidor que usar."
 
-#: C/empathy.xml:898(para) C/empathy.xml:991(para) C/empathy.xml:1039(para)
-#: C/empathy.xml:1133(para)
+#: C/empathy.xml:897(para) C/empathy.xml:990(para) C/empathy.xml:1038(para)
+#: C/empathy.xml:1132(para)
 msgid ""
 "You can set values in the range from <literal>0</literal> to "
 "<literal>65,555</literal>."
@@ -1056,11 +1052,11 @@ msgstr ""
 "Puede establecer valores en el rango de <literal>0</literal> a "
 "<literal>65.555</literal>."
 
-#: C/empathy.xml:906(guilabel)
+#: C/empathy.xml:905(guilabel)
 msgid "Use old SSL"
 msgstr "Usar SSL antiguo"
 
-#: C/empathy.xml:909(para)
+#: C/empathy.xml:908(para)
 msgid ""
 "Select this option to use the old version of the secure protocol for "
 "encrypting your connection."
@@ -1068,7 +1064,7 @@ msgstr ""
 "Seleccione esta opción para usar la versión antigua del protocolo seguro "
 "para cifrar su conexión."
 
-#: C/empathy.xml:874(para)
+#: C/empathy.xml:873(para)
 msgid ""
 "In the <guilabel>Override server settings</guilabel> section you can set "
 "options that take precedence over the default settings. <placeholder-1/>"
@@ -1077,22 +1073,22 @@ msgstr ""
 "puede establecer opciones que tienen preferencia sobre los ajustes "
 "predeterminados. <placeholder-1/>"
 
-#: C/empathy.xml:925(guilabel)
+#: C/empathy.xml:924(guilabel)
 msgid "Ignore conference and chatrooms invitations"
 msgstr "Ignorar invitaciones a conferencias y salas de chat"
 
-#: C/empathy.xml:929(para)
+#: C/empathy.xml:928(para)
 msgid ""
 "Select this option to ignore the invitations that other people may send you."
 msgstr ""
 "Seleccione esta opción para ignorar las invitaciones que otras personas "
 "pueden enviarle."
 
-#: C/empathy.xml:937(guilabel)
+#: C/empathy.xml:936(guilabel)
 msgid "Room List locale"
 msgstr "Configuración de la lista de salas"
 
-#: C/empathy.xml:940(para)
+#: C/empathy.xml:939(para)
 msgid ""
 "The value of this text box identifies the language used to retrieve the room "
 "list when connecting to the Yahoo service."
@@ -1100,17 +1096,17 @@ msgstr ""
 "El valor de esta caja de texto identifica el idioma que usar al obtener la "
 "lista de salas al conectar con el servicio de Yahoo!"
 
-#: C/empathy.xml:945(para)
+#: C/empathy.xml:944(para)
 msgid ""
 "If you need to change this value, use the two letter code of your language."
 msgstr ""
 "Si necesita cambiar ese valor use el código de dos letras para su idioma."
 
-#: C/empathy.xml:953(guilabel) C/empathy.xml:1095(guilabel)
+#: C/empathy.xml:952(guilabel) C/empathy.xml:1094(guilabel)
 msgid "Charset"
 msgstr "Conjunto de caracteres"
 
-#: C/empathy.xml:956(para) C/empathy.xml:1098(para)
+#: C/empathy.xml:955(para) C/empathy.xml:1097(para)
 msgid ""
 "The value of this text box identifies the set of the characters used by "
 "<application>Empathy</application>."
@@ -1118,7 +1114,7 @@ msgstr ""
 "El valor de esta caja de texto identifica el conjunto de caracteres que usa "
 "<application>Empathy</application>."
 
-#: C/empathy.xml:962(para) C/empathy.xml:1104(para)
+#: C/empathy.xml:961(para) C/empathy.xml:1103(para)
 msgid ""
 "It is advise to leave this value to <literal>UTF-8</literal>. Change it only "
 "if that charset does not cover your language."
@@ -1126,11 +1122,11 @@ msgstr ""
 "Se recomienda dejar este valor en <literal>UTF-8</literal>. Cámbielo sólo si "
 "ese conjunto de caracteres no cubre su idioma."
 
-#: C/empathy.xml:999(guilabel)
+#: C/empathy.xml:998(guilabel)
 msgid "Use Yahoo Japan"
 msgstr "Usar Yahoo Japón"
 
-#: C/empathy.xml:1002(para)
+#: C/empathy.xml:1001(para)
 msgid ""
 "Select this option only if you have a Yahoo! Japan account. With the Yahoo! "
 "Japan service you can only use a Yahoo! Japan account: if you have "
@@ -1142,15 +1138,15 @@ msgstr ""
 "registrado una cuenta con la versión inglesa del servicio, esa cuenta no "
 "funcionará."
 
-#: C/empathy.xml:1016(title)
+#: C/empathy.xml:1015(title)
 msgid "<acronym>AIM</acronym>, GroupWise and <acronym>MSN</acronym>"
 msgstr "<acronym>AIM</acronym>, GroupWise y <acronym>MSN</acronym>"
 
-#: C/empathy.xml:1055(guilabel)
+#: C/empathy.xml:1054(guilabel)
 msgid "Published Name"
 msgstr "Nombre publicado"
 
-#: C/empathy.xml:1058(para)
+#: C/empathy.xml:1057(para)
 msgid ""
 "Use this text box to write the name that will be visible to the other users "
 "of the network."
@@ -1158,42 +1154,42 @@ msgstr ""
 "Use esta caja de texto para escribir el nombre que será visible al resto de "
 "usuarios de la red."
 
-#: C/empathy.xml:1066(guilabel)
+#: C/empathy.xml:1065(guilabel)
 msgid "Email"
 msgstr "Correo-e"
 
-#: C/empathy.xml:1069(para)
+#: C/empathy.xml:1068(para)
 msgid "Use this text box to write your email."
 msgstr "Use esta caja de texto para escribir su correo-e."
 
-#: C/empathy.xml:1076(guilabel)
+#: C/empathy.xml:1075(guilabel)
 msgid "Jabber ID"
 msgstr "ID Jabber"
 
-#: C/empathy.xml:1079(para)
+#: C/empathy.xml:1078(para)
 msgid "Use this text box to write your Jabber ID, if you have one."
 msgstr "Use esta caja de texto para escribir su ID Jabber, si tiene uno."
 
-#: C/empathy.xml:1144(title)
+#: C/empathy.xml:1143(title)
 msgid "Gadu Gadu"
 msgstr "Gadu Gadu"
 
-#: C/empathy.xml:1148(guilabel)
+#: C/empathy.xml:1147(guilabel)
 msgid "Nick"
 msgstr "Apodo"
 
-#: C/empathy.xml:1150(para)
+#: C/empathy.xml:1149(para)
 msgid ""
 "Use this text box to write an alternative name to use with this service."
 msgstr ""
 "Use esta caja de texto para escribir un nombre alternativo que usar con este "
 "servicio."
 
-#: C/empathy.xml:1165(title)
+#: C/empathy.xml:1164(title)
 msgid "Contacts and Groups"
 msgstr "Contactos y grupos"
 
-#: C/empathy.xml:1166(para)
+#: C/empathy.xml:1165(para)
 msgid ""
 "All the contacts are handled within <application>Empathy</application>'s "
 "<link linkend=\"empathy-FIG-mainwindow\">main window</link>."
@@ -1201,7 +1197,7 @@ msgstr ""
 "Todos los contactos se gestionan en la <link linkend=\"empathy-FIG-mainwindow"
 "\">ventana principal</link> de <application>Empathy</application>."
 
-#: C/empathy.xml:1170(para)
+#: C/empathy.xml:1169(para)
 msgid ""
 "You can add or remove a contact or you can edit the information of a "
 "particular contact. It is also possibile to arrange contacts in groups. You "
@@ -1213,15 +1209,15 @@ msgstr ""
 "Puede tener un grupo para sus contactos del trabajo, uno para los contactos "
 "de su familia, y demás."
 
-#: C/empathy.xml:1177(title)
+#: C/empathy.xml:1176(title)
 msgid "Adding and Removing a Contact"
 msgstr "Añadir y quitar un contacto"
 
-#: C/empathy.xml:1178(para)
+#: C/empathy.xml:1177(para)
 msgid "To add a new contact, proceed as follows:"
 msgstr "Para añadir un contacto nuevo, proceda como sigue:"
 
-#: C/empathy.xml:1184(para)
+#: C/empathy.xml:1183(para)
 msgid ""
 "From the <link linkend=\"empathy-FIG-mainwindow\">main window</link> choose "
 "<menuchoice><guimenu>Chat</guimenu><guimenuitem>Add Contact...</"
@@ -1233,7 +1229,7 @@ msgstr ""
 "guimenuitem></menuchoice>. Se mostrará el diálogo <guilabel>Contacto nuevo</"
 "guilabel>."
 
-#: C/empathy.xml:1194(para)
+#: C/empathy.xml:1193(para)
 msgid ""
 "From the <guilabel>Account</guilabel> drop-down list, choose the service "
 "used by the contact you are adding."
@@ -1241,7 +1237,7 @@ msgstr ""
 "Desde la lista desplegable <guilabel>Cuenta</guilabel>, elija el servicio "
 "que usa el contacto que está añadiendo."
 
-#: C/empathy.xml:1200(para)
+#: C/empathy.xml:1199(para)
 msgid ""
 "In the <guilabel>Identifier</guilabel> text box type the <emphasis>address</"
 "emphasis> of the contact in the form of <userinput><replaceable>user name</"
@@ -1254,7 +1250,7 @@ msgstr ""
 "replaceable>@<replaceable>servicio\n"
 "\t     dominio</replaceable></userinput>."
 
-#: C/empathy.xml:1209(para)
+#: C/empathy.xml:1208(para)
 msgid ""
 "In the <guilabel>Alias</guilabel> text box type the name you want to give at "
 "the the new contact."
@@ -1262,15 +1258,15 @@ msgstr ""
 "En la caja de texto <guilabel>Apodo</guilabel> escriba el nombre que quiere "
 "darle a su nuevo contacto."
 
-#: C/empathy.xml:1215(para)
+#: C/empathy.xml:1214(para)
 msgid "Click on <guibutton>Add</guibutton> to add the new contact."
 msgstr "Pulse en <guibutton>Añadir</guibutton> para añadir el contacto nuevo."
 
-#: C/empathy.xml:1221(para)
+#: C/empathy.xml:1220(para)
 msgid "To remove a contact, proceed as follows:"
 msgstr "Para quitar un contacto, proceda como sigue:"
 
-#: C/empathy.xml:1227(para)
+#: C/empathy.xml:1226(para)
 msgid ""
 "From the <link linkend=\"empathy-FIG-mainwindow\">main window</link>, select "
 "the contact you would like to remove and right-click on it."
@@ -1279,7 +1275,7 @@ msgstr ""
 "seleccione el contacto que quiere quitar y pulse con el botón derecho sobre "
 "él."
 
-#: C/empathy.xml:1234(para)
+#: C/empathy.xml:1233(para)
 msgid ""
 "From the popup menu, choose <guilabel>Remove</guilabel> to remove the "
 "contact."
@@ -1287,7 +1283,7 @@ msgstr ""
 "Desde el menú emergente, elija <guilabel>Quitar</guilabel> para quitar el "
 "contacto."
 
-#: C/empathy.xml:1243(para) C/empathy.xml:1279(para)
+#: C/empathy.xml:1242(para) C/empathy.xml:1278(para)
 msgid ""
 "An <emphasis>alias</emphasis> is an alternative way you can identify that "
 "particular contact. You can use the real name or the nickname of that person."
@@ -1295,21 +1291,15 @@ msgstr ""
 "Un <emphasis>apodo</emphasis> es una forma alternativa de identificar un "
 "contacto en particular. Puede usar el nombre real o el apodo de esa persona."
 
-#: C/empathy.xml:1252(title)
+#: C/empathy.xml:1251(title)
 msgid "Editing a Contact"
 msgstr "Editar un contacto"
 
-#: C/empathy.xml:1253(para)
+#: C/empathy.xml:1252(para)
 msgid "To edit a contact, proceed as follows:"
 msgstr "Para editar un contacto, proceda como sigue:"
 
-#: C/empathy.xml:1259(para) C/empathy.xml:1301(para)
-#| msgid ""
-#| "From the <link linkend=\"empathy-FIG-mainwindow\">main window</link>, "
-#| "select the contact you would like to modify and choose "
-#| "<menuchoice><guimenu>Edit</guimenu><guisubmenu>Account</"
-#| "guisubmenu><guimenuitem>Modify</guimenuitem></menuchoice>, or right-click "
-#| "on it and choose <guilabel>Modify</guilabel>."
+#: C/empathy.xml:1258(para) C/empathy.xml:1300(para)
 msgid ""
 "From the <link linkend=\"empathy-FIG-mainwindow\">main window</link>, select "
 "the contact you would like to modify and choose <menuchoice><guimenu>Edit</"
@@ -1322,7 +1312,7 @@ msgstr ""
 "guisubmenu><guimenuitem>Editar</guimenuitem></menuchoice> o pulse con el "
 "botón derecho sobre Ã©l y elija <guilabel>Editar</guilabel>."
 
-#: C/empathy.xml:1272(para)
+#: C/empathy.xml:1271(para)
 msgid ""
 "From the <guilabel>Edit Contact Information</guilabel> dialog, you can "
 "modify the <emphasis>alias</emphasis> and the <emphasis>group</emphasis> of "
@@ -1332,7 +1322,7 @@ msgstr ""
 "modificar el <emphasis>apodp</emphasis> y el <emphasis>grupo</emphasis> del "
 "contacto."
 
-#: C/empathy.xml:1286(para)
+#: C/empathy.xml:1285(para)
 msgid ""
 "For more information about groups, see <xref linkend=\"empathy-add-contact-"
 "group\"/> and <xref linkend=\"empathy-add-group\"/>."
@@ -1340,15 +1330,15 @@ msgstr ""
 "Para obtener más información acerca de los grupos, consulte <xref linkend="
 "\"empathy-add-contact-group\"/> y <xref linkend=\"empathy-add-group\"/>."
 
-#: C/empathy.xml:1294(title)
+#: C/empathy.xml:1293(title)
 msgid "Adding a Contact to a Group"
 msgstr "Añadir un contacto a un grupo"
 
-#: C/empathy.xml:1295(para)
+#: C/empathy.xml:1294(para)
 msgid "To add a contact to one or more groups, proceed as follows:"
 msgstr "Para añadir un contacto a uno o más grupos, proceda como sigue:"
 
-#: C/empathy.xml:1313(para)
+#: C/empathy.xml:1312(para)
 msgid ""
 "From the <guilabel>Groups</guilabel> section, select the group, or groups, "
 "you want to add the contact to."
@@ -1356,21 +1346,15 @@ msgstr ""
 "En la sección <guilabel>Grupos</guilabel>, seleccione el grupo o grupos a "
 "los que quiera añadir el contacto."
 
-#: C/empathy.xml:1328(title)
+#: C/empathy.xml:1327(title)
 msgid "Adding a New Group"
 msgstr "Añadir un grupo nuevo"
 
-#: C/empathy.xml:1329(para)
+#: C/empathy.xml:1328(para)
 msgid "To add a new group, proceed as follows:"
 msgstr "Para añadir un grupo nuevo, proceda como sigue:"
 
-#: C/empathy.xml:1335(para)
-#| msgid ""
-#| "From the <link linkend=\"empathy-FIG-mainwindow\">main window</link>, "
-#| "select one contact and choose <menuchoice><guimenu>Edit</"
-#| "guimenu><guisubmenu>Account</guisubmenu><guimenuitem>Modify</"
-#| "guimenuitem></menuchoice>, or right-click on it and choose "
-#| "<guilabel>Modify</guilabel>."
+#: C/empathy.xml:1334(para)
 msgid ""
 "From the <link linkend=\"empathy-FIG-mainwindow\">main window</link>, select "
 "one contact and choose <menuchoice><guimenu>Edit</"
@@ -1382,7 +1366,7 @@ msgstr ""
 "guimenu><guisubmenu>Contacto</guisubmenu><guimenuitem>Editar</guimenuitem></"
 "menuchoice> o pulse con el botón derecho y elija <guilabel>Editar</guilabel>."
 
-#: C/empathy.xml:1346(para)
+#: C/empathy.xml:1345(para)
 msgid ""
 "In the <guilabel>Groups</guilabel> section, write the name of the group you "
 "want to add and then click on <guibutton>Add Group</guibutton>."
index 6f3b99ba6e98282345e3ee69e858bbe9bb5c51e7..2065589e3594b19d11419d9f2318e1bcfcb7fbe9 100644 (file)
@@ -49,7 +49,7 @@ libempathy_gtk_la_SOURCES =                   \
        empathy-profile-chooser.c               \
        empathy-smiley-manager.c                \
        empathy-spell.c                         \
-       empathy-spell-dialog.c                  \
+       empathy-status-preset-dialog.c          \
        empathy-theme-boxes.c                   \
        empathy-theme-irc.c                     \
        empathy-theme-manager.c                 \
@@ -102,7 +102,7 @@ libempathy_gtk_headers =                    \
        empathy-profile-chooser.h               \
        empathy-smiley-manager.h                \
        empathy-spell.h                         \
-       empathy-spell-dialog.h                  \
+       empathy-status-preset-dialog.h          \
        empathy-theme-boxes.h                   \
        empathy-theme-irc.h                     \
        empathy-theme-manager.h                 \
@@ -117,7 +117,6 @@ uidir = $(datadir)/empathy
 ui_DATA =                                      \
        empathy-contact-widget.ui               \
        empathy-contact-dialogs.ui              \
-       empathy-presence-chooser.ui             \
        empathy-account-widget-generic.ui       \
        empathy-account-widget-jabber.ui        \
        empathy-account-widget-msn.ui           \
@@ -128,7 +127,7 @@ ui_DATA =                                   \
        empathy-account-widget-yahoo.ui         \
        empathy-account-widget-groupwise.ui     \
        empathy-account-widget-aim.ui           \
-       empathy-spell-dialog.ui                 \
+       empathy-status-preset-dialog.ui         \
        empathy-log-window.ui                   \
        empathy-chat.ui                         \
        empathy-new-message-dialog.ui
index 8c402c07a0c1e672b188e20a437141d23f675867..5d11e8e1e288d823fe2a30bcb9b4104996f8211c 100644 (file)
 #include "empathy-ui-utils.h"
 #include "empathy-account-chooser.h"
 
+/**
+ * SECTION:empathy-account-chooser
+ * @title:EmpathyAccountChooser
+ * @short_description: A widget used to choose from a list of accounts
+ * @include: libempathy-gtk/empathy-account-chooser.h
+ *
+ * #EmpathyAccountChooser is a widget which extends #GtkComboBox to provide
+ * a chooser of available accounts.
+ */
+
+/**
+ * EmpathyAccountChooser:
+ * @parent: parent object
+ *
+ * Widget which extends #GtkComboBox to provide a chooser of available accounts.
+ */
+
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountChooser)
 typedef struct {
        EmpathyAccountManager          *manager;
@@ -112,6 +129,11 @@ empathy_account_chooser_class_init (EmpathyAccountChooserClass *klass)
        object_class->get_property = account_chooser_get_property;
        object_class->set_property = account_chooser_set_property;
 
+       /**
+        * EmpathyAccountChooser:has-all-option:
+        *
+        * Have an additional option in the list to mean all accounts.
+        */
        g_object_class_install_property (object_class,
                                         PROP_HAS_ALL_OPTION,
                                         g_param_spec_boolean ("has-all-option",
@@ -209,6 +231,13 @@ account_chooser_set_property (GObject      *object,
        };
 }
 
+/**
+ * empathy_account_chooser_new:
+ *
+ * Creates a new #EmpathyAccountChooser.
+ *
+ * Return value: A new #EmpathyAccountChooser
+ */
 GtkWidget *
 empathy_account_chooser_new (void)
 {
@@ -219,8 +248,18 @@ empathy_account_chooser_new (void)
        return chooser;
 }
 
+/**
+ * empathy_account_chooser_dup_account:
+ * @chooser: an #EmpathyAccountChooser
+ *
+ * Returns the account which is currently selected in the chooser or %NULL
+ * if there is no account selected. The #McAccount returned should be
+ * unrefed with g_object_unref() when finished with.
+ *
+ * Return value: a new ref to the #McAccount currently selected, or %NULL.
+ */
 McAccount *
-empathy_account_chooser_get_account (EmpathyAccountChooser *chooser)
+empathy_account_chooser_dup_account (EmpathyAccountChooser *chooser)
 {
        EmpathyAccountChooserPriv *priv;
        McAccount                *account;
@@ -241,6 +280,44 @@ empathy_account_chooser_get_account (EmpathyAccountChooser *chooser)
        return account;
 }
 
+/**
+ * empathy_account_chooser_get_connection:
+ * @chooser: an #EmpathyAccountChooser
+ *
+ * Returns a borrowed reference to the #TpConnection associated with the
+ * account currently selected. The caller must reference the returned object with
+ * g_object_ref() if it will be kept
+ *
+ * Return value: a borrowed reference to the #TpConnection associated with the
+ * account curently selected.
+ */
+TpConnection *
+empathy_account_chooser_get_connection (EmpathyAccountChooser *chooser)
+{
+       EmpathyAccountChooserPriv *priv;
+       McAccount                 *account;
+       TpConnection              *connection;
+
+       g_return_val_if_fail (EMPATHY_IS_ACCOUNT_CHOOSER (chooser), NULL);
+
+       priv = GET_PRIV (chooser);
+
+       account = empathy_account_chooser_dup_account (chooser);
+       connection = empathy_account_manager_get_connection (priv->manager, account);
+       g_object_unref (account);
+
+       return connection;
+}
+
+/**
+ * empathy_account_chooser_set_account:
+ * @chooser: an #EmpathyAccountChooser
+ * @account: an #McAccount
+ *
+ * Sets the currently selected account to @account, if it exists in the list.
+ *
+ * Return value: whether the chooser was set to @account.
+ */
 gboolean
 empathy_account_chooser_set_account (EmpathyAccountChooser *chooser,
                                     McAccount             *account)
@@ -266,6 +343,16 @@ empathy_account_chooser_set_account (EmpathyAccountChooser *chooser,
        return data.set;
 }
 
+/**
+ * empathy_account_chooser_get_has_all_option:
+ * @chooser: an #EmpathyAccountChooser
+ *
+ * Returns whether @chooser has the #EmpathyAccountChooser:has-all-option property
+ * set to true.
+ *
+ * Return value: whether @chooser has the #EmpathyAccountChooser:has-all-option property
+ * enabled.
+ */
 gboolean
 empathy_account_chooser_get_has_all_option (EmpathyAccountChooser *chooser)
 {
@@ -278,6 +365,13 @@ empathy_account_chooser_get_has_all_option (EmpathyAccountChooser *chooser)
        return priv->has_all_option;
 }
 
+/**
+ * empathy_account_chooser_set_has_all_option:
+ * @chooser: an #EmpathyAccountChooser
+ * @has_all_option: a new value for the #EmpathyAccountChooser:has-all-option property
+ *
+ * Sets the #EmpathyAccountChooser:has-all-option property.
+ */
 void
 empathy_account_chooser_set_has_all_option (EmpathyAccountChooser *chooser,
                                           gboolean              has_all_option)
@@ -618,6 +712,15 @@ account_chooser_filter_foreach (GtkTreeModel *model,
        return FALSE;
 }
 
+/**
+ * empathy_account_chooser_set_filter:
+ * @chooser: an #EmpathyAccountChooser
+ * @filter: a filter
+ * @user_data: data to pass to @filter, or %NULL
+ *
+ * Sets a filter on the @chooser so only accounts that are %TRUE in the eyes
+ * of the filter are visible in the @chooser.
+ */
 void
 empathy_account_chooser_set_filter (EmpathyAccountChooser           *chooser,
                                     EmpathyAccountChooserFilterFunc  filter,
@@ -639,6 +742,27 @@ empathy_account_chooser_set_filter (EmpathyAccountChooser           *chooser,
        gtk_tree_model_foreach (model, account_chooser_filter_foreach, chooser);
 }
 
+/**
+ * EmpathyAccountChooserFilterFunc:
+ * @account: an #McAccount
+ * @user_data: user data, or %NULL
+ *
+ * A function which decides whether the account indicated by @account
+ * is visible.
+ *
+ * Return value: whether the account indicated by @account is visible.
+ */
+
+/**
+ * empathy_account_chooser_filter_is_connected:
+ * @account: an #McAccount
+ * @user_data: user data or %NULL
+ *
+ * A useful #EmpathyAccountChooserFilterFunc that one could pass into
+ * empathy_account_chooser_set_filter() and only show connected accounts.
+ *
+ * Return value: Whether @account is connected
+ */
 gboolean
 empathy_account_chooser_filter_is_connected (McAccount *account,
                                             gpointer   user_data)
index c15923bc3ac76a04fe9bf34b0b214007ed3c3403..98d568bccab62ba7d357862502972adc12ec08a5 100644 (file)
@@ -47,6 +47,8 @@ typedef struct _EmpathyAccountChooserClass EmpathyAccountChooserClass;
 
 struct _EmpathyAccountChooser {
        GtkComboBox parent;
+
+       /*<private>*/
        gpointer priv;
 };
 
@@ -56,7 +58,8 @@ struct _EmpathyAccountChooserClass {
 
 GType          empathy_account_chooser_get_type           (void) G_GNUC_CONST;
 GtkWidget *    empathy_account_chooser_new                (void);
-McAccount *    empathy_account_chooser_get_account        (EmpathyAccountChooser *chooser);
+McAccount *    empathy_account_chooser_dup_account        (EmpathyAccountChooser *chooser);
+TpConnection * empathy_account_chooser_get_connection     (EmpathyAccountChooser *chooser);
 gboolean       empathy_account_chooser_set_account        (EmpathyAccountChooser *chooser,
                                                           McAccount            *account);
 gboolean       empathy_account_chooser_get_has_all_option (EmpathyAccountChooser *chooser);
index 3af842415ec219a1e41b4298d86cb05f47408f0b..cc86a5aaa44d539c6c270d7c5632afc574d0b0d3 100644 (file)
@@ -50,9 +50,6 @@ typedef struct {
   GtkWidget *vbox_settings;
 
   GtkWidget *combobox_network;
-  GtkWidget *button_add_network;
-  GtkWidget *button_network;
-  GtkWidget *button_remove;
 } EmpathyAccountWidgetIrc;
 
 enum {
@@ -462,9 +459,6 @@ empathy_account_widget_irc_new (McAccount *account)
   gui = empathy_builder_get_file (filename,
       "vbox_irc_settings", &settings->vbox_settings,
       "combobox_network", &settings->combobox_network,
-      "button_network", &settings->button_network,
-      "button_add_network", &settings->button_add_network,
-      "button_remove", &settings->button_remove,
       NULL);
   g_free (filename);
 
@@ -501,7 +495,7 @@ empathy_account_widget_irc_new (McAccount *account)
       "vbox_irc_settings", "destroy", account_widget_irc_destroy_cb,
       "button_network", "clicked", account_widget_irc_button_edit_network_clicked_cb,
       "button_add_network", "clicked", account_widget_irc_button_add_network_clicked_cb,
-      "button_remove", "clicked", account_widget_irc_button_remove_clicked_cb,
+      "button_remove_network", "clicked", account_widget_irc_button_remove_clicked_cb,
       "combobox_network", "changed", account_widget_irc_combobox_network_changed_cb,
       NULL);
 
index f499866ebe3c9aec740e5ce50e25824977a1b708..76c67f711719697245643c28da0a7e3e8a44a170 100644 (file)
@@ -3,7 +3,6 @@
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy toplevel-contextual -->
   <object class="GtkDialog" id="irc_network_dialog">
-    <property name="visible">True</property>
     <property name="border_width">5</property>
     <property name="title" translatable="yes">Network</property>
     <property name="window_position">center-on-parent</property>
           </packing>
         </child>
         <child>
-          <object class="GtkButton" id="button_remove">
+          <object class="GtkButton" id="button_remove_network">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>
       </packing>
     </child>
     <child>
-      <object class="GtkLabel" id="label_network">
+      <object class="GtkLabel" id="label_network2">
         <property name="visible">True</property>
         <property name="xalign">0</property>
         <property name="label" translatable="yes">Network:</property>
index 02aa689eb28aa48c3db98cf58ad4d54485db5173..c86b85d259a27d4fa31c66c58970f95c057f360f 100644 (file)
@@ -30,7 +30,7 @@
 #include <gio/gio.h>
 
 #include <libempathy/empathy-utils.h>
-#include <libempathy/empathy-contact-factory.h>
+#include <libempathy/empathy-tp-contact-factory.h>
 
 #include "empathy-avatar-chooser.h"
 #include "empathy-conf.h"
 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
 #include <libempathy/empathy-debug.h>
 
+/**
+ * SECTION:empathy-avatar-chooser
+ * @title: EmpathyAvatarChooser
+ * @short_description: A widget used to change avatar
+ * @include: libempathy-gtk/empathy-avatar-chooser.h
+ *
+ * #EmpathyAvatarChooser is a widget which extends #GtkButton to
+ * provide a way of changing avatar.
+ */
+
+/**
+ * EmpathyAvatarChooser:
+ * @parent: parent object
+ *
+ * Widget which extends #GtkButton to provide a way of changing avatar.
+ */
+
 #define AVATAR_SIZE_SAVE 96
 #define AVATAR_SIZE_VIEW 64
 #define DEFAULT_DIR DATADIR"/pixmaps/faces"
 
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAvatarChooser)
 typedef struct {
-       EmpathyContactFactory   *contact_factory;
-       McAccount               *account;
-       EmpathyTpContactFactory *tp_contact_factory;
+       EmpathyTpContactFactory *factory;
+       TpConnection            *connection;
        GtkFileChooser          *chooser_dialog;
 
        gulong ready_handler_id;
@@ -56,8 +72,8 @@ typedef struct {
 } EmpathyAvatarChooserPriv;
 
 static void       avatar_chooser_finalize              (GObject              *object);
-static void       avatar_chooser_set_account           (EmpathyAvatarChooser *self,
-                                                       McAccount            *account);
+static void       avatar_chooser_set_connection        (EmpathyAvatarChooser *self,
+                                                       TpConnection         *connection);
 static void       avatar_chooser_set_image             (EmpathyAvatarChooser *chooser,
                                                        EmpathyAvatar        *avatar,
                                                        GdkPixbuf            *pixbuf,
@@ -96,7 +112,7 @@ enum {
 
 enum {
        PROP_0,
-       PROP_ACCOUNT
+       PROP_CONNECTION
 };
 
 static guint signals [LAST_SIGNAL];
@@ -125,8 +141,8 @@ avatar_chooser_get_property (GObject    *object,
        EmpathyAvatarChooserPriv *priv = GET_PRIV (object);
 
        switch (param_id) {
-       case PROP_ACCOUNT:
-               g_value_set_object (value, priv->account);
+       case PROP_CONNECTION:
+               g_value_set_object (value, priv->connection);
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -143,8 +159,8 @@ avatar_chooser_set_property (GObject      *object,
        EmpathyAvatarChooser *self = EMPATHY_AVATAR_CHOOSER (object);
 
        switch (param_id) {
-       case PROP_ACCOUNT:
-               avatar_chooser_set_account (self, g_value_get_object (value));
+       case PROP_CONNECTION:
+               avatar_chooser_set_connection (self, g_value_get_object (value));
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -162,6 +178,13 @@ empathy_avatar_chooser_class_init (EmpathyAvatarChooserClass *klass)
        object_class->get_property = avatar_chooser_get_property;
        object_class->set_property = avatar_chooser_set_property;
 
+       /**
+        * EmpathyAvatarChooser::changed:
+        * @chooser: an #EmpathyAvatarChooser
+        *
+        * Emitted when the chosen avatar has changed.
+        *
+        */
        signals[CHANGED] =
                g_signal_new ("changed",
                              G_TYPE_FROM_CLASS (klass),
@@ -171,15 +194,21 @@ empathy_avatar_chooser_class_init (EmpathyAvatarChooserClass *klass)
                              g_cclosure_marshal_VOID__VOID,
                              G_TYPE_NONE, 0);
 
-       param_spec = g_param_spec_object ("account",
-                                         "McAccount",
-                                         "McAccount whose avatar should be "
+       /**
+        * EmpathyAvatarChooser:connection:
+        *
+        * The #TpConnection whose avatar should be shown and modified by
+        * the #EmpathyAvatarChooser instance.
+        */
+       param_spec = g_param_spec_object ("connection",
+                                         "TpConnection",
+                                         "TpConnection whose avatar should be "
                                          "shown and modified by this widget",
-                                         MC_TYPE_ACCOUNT,
+                                         TP_TYPE_CONNECTION,
                                          G_PARAM_READWRITE |
                                          G_PARAM_STATIC_STRINGS);
        g_object_class_install_property (object_class,
-                                        PROP_ACCOUNT,
+                                        PROP_CONNECTION,
                                         param_spec);
 
        g_type_class_add_private (object_class, sizeof (EmpathyAvatarChooserPriv));
@@ -214,8 +243,6 @@ empathy_avatar_chooser_init (EmpathyAvatarChooser *chooser)
                          G_CALLBACK (avatar_chooser_clicked_cb),
                          chooser);
 
-       priv->contact_factory = empathy_contact_factory_dup_singleton ();
-
        empathy_avatar_chooser_set (chooser, NULL);
 }
 
@@ -226,11 +253,9 @@ avatar_chooser_finalize (GObject *object)
 
        priv = GET_PRIV (object);
 
-       avatar_chooser_set_account (EMPATHY_AVATAR_CHOOSER (object), NULL);
-       g_assert (priv->account == NULL);
-       g_assert (priv->tp_contact_factory == NULL);
-
-       g_object_unref (priv->contact_factory);
+       avatar_chooser_set_connection (EMPATHY_AVATAR_CHOOSER (object), NULL);
+       g_assert (priv->connection == NULL);
+       g_assert (priv->factory == NULL);
 
        if (priv->avatar != NULL) {
                empathy_avatar_unref (priv->avatar);
@@ -240,51 +265,22 @@ avatar_chooser_finalize (GObject *object)
 }
 
 static void
-avatar_chooser_tp_cf_ready_cb (EmpathyTpContactFactory *tp_cf,
-                              GParamSpec              *unused,
-                              EmpathyAvatarChooser    *self)
-{
-       EmpathyAvatarChooserPriv *priv = GET_PRIV (self);
-       gboolean ready;
-
-       /* sanity check that we're listening on the right ETpCF */
-       g_assert (priv->tp_contact_factory == tp_cf);
-
-       ready = empathy_tp_contact_factory_is_ready (tp_cf);
-       gtk_widget_set_sensitive (GTK_WIDGET (self), ready);
-}
-
-static void
-avatar_chooser_set_account (EmpathyAvatarChooser *self,
-                           McAccount            *account)
+avatar_chooser_set_connection (EmpathyAvatarChooser *self,
+                              TpConnection         *connection)
 {
        EmpathyAvatarChooserPriv *priv = GET_PRIV (self);
 
-       if (priv->account != NULL) {
-               g_object_unref (priv->account);
-               priv->account = NULL;
+       if (priv->connection != NULL) {
+               g_object_unref (priv->connection);
+               priv->connection = NULL;
 
-               g_assert (priv->tp_contact_factory != NULL);
-
-               g_signal_handler_disconnect (priv->tp_contact_factory,
-                       priv->ready_handler_id);
-               priv->ready_handler_id = 0;
-
-               g_object_unref (priv->tp_contact_factory);
-               priv->tp_contact_factory = NULL;
+               g_object_unref (priv->factory);
+               priv->factory = NULL;
        }
 
-       if (account != NULL) {
-               priv->account = g_object_ref (account);
-               priv->tp_contact_factory = g_object_ref (
-                       empathy_contact_factory_get_tp_factory (
-                               priv->contact_factory, priv->account));
-
-               priv->ready_handler_id = g_signal_connect (
-                       priv->tp_contact_factory, "notify::ready",
-                       G_CALLBACK (avatar_chooser_tp_cf_ready_cb), self);
-               avatar_chooser_tp_cf_ready_cb (priv->tp_contact_factory, NULL,
-                       self);
+       if (connection != NULL) {
+               priv->connection = g_object_ref (connection);
+               priv->factory = empathy_tp_contact_factory_dup_singleton (connection);
        }
 }
 
@@ -412,7 +408,6 @@ avatar_chooser_maybe_convert_and_scale (EmpathyAvatarChooser *chooser,
                                        EmpathyAvatar        *avatar)
 {
        EmpathyAvatarChooserPriv *priv = GET_PRIV (chooser);
-       EmpathyTpContactFactory  *tp_cf = priv->tp_contact_factory;
        guint                     max_width = 0, max_height = 0, max_size = 0;
        gchar                   **mime_types = NULL;
        gboolean                  needs_conversion = FALSE;
@@ -424,15 +419,7 @@ avatar_chooser_maybe_convert_and_scale (EmpathyAvatarChooser *chooser,
        gchar                    *converted_image_data = NULL;
        gsize                     converted_image_size = 0;
 
-       /* This should only be called if the user is setting a new avatar,
-        * which should only be allowed once the avatar requirements have been
-        * discovered.
-        */
-       g_return_val_if_fail (tp_cf != NULL, NULL);
-       g_return_val_if_fail (empathy_tp_contact_factory_is_ready (tp_cf),
-               NULL);
-
-       g_object_get (tp_cf,
+       g_object_get (priv->factory,
                "avatar-mime-types", &mime_types, /* Needs g_strfreev-ing */
                "avatar-max-width", &max_width,
                "avatar-max-height", &max_height,
@@ -901,16 +888,6 @@ avatar_chooser_response_cb (GtkWidget            *widget,
 
        priv->chooser_dialog = NULL;
 
-       if (response == GTK_RESPONSE_CANCEL) {
-               goto out;
-       }
-
-       /* Check if we went non-ready since displaying the dialog. */
-       if (!empathy_tp_contact_factory_is_ready (priv->tp_contact_factory)) {
-               DEBUG ("Can't set avatar when contact factory isn't ready.");
-               goto out;
-       }
-
        if (response == GTK_RESPONSE_OK) {
                gchar *filename;
                gchar *path;
@@ -932,7 +909,6 @@ avatar_chooser_response_cb (GtkWidget            *widget,
                avatar_chooser_clear_image (chooser);
        }
 
-out:
        gtk_widget_destroy (widget);
 }
 
@@ -1037,12 +1013,26 @@ avatar_chooser_clicked_cb (GtkWidget            *button,
        g_free (saved_dir);
 }
 
+/**
+ * empathy_avatar_chooser_new:
+ *
+ * Creates a new #EmpathyAvatarChooser.
+ *
+ * Return value: a new #EmpathyAvatarChooser
+ */
 GtkWidget *
 empathy_avatar_chooser_new ()
 {
        return g_object_new (EMPATHY_TYPE_AVATAR_CHOOSER, NULL);
 }
 
+/**
+ * empathy_avatar_chooser_set:
+ * @chooser: an #EmpathyAvatarChooser
+ * @avatar: a new #EmpathyAvatar
+ *
+ * Sets the @chooser to display the avatar indicated by @avatar.
+ */
 void
 empathy_avatar_chooser_set (EmpathyAvatarChooser *chooser,
                            EmpathyAvatar        *avatar)
@@ -1056,6 +1046,15 @@ empathy_avatar_chooser_set (EmpathyAvatarChooser *chooser,
        }
 }
 
+/**
+ * empathy_avatar_chooser_get_image_data:
+ * @chooser: an #EmpathyAvatarChooser
+ * @data: avatar bytes
+ * @data_size: size of @data
+ * @mime_type: avatar mime-type
+ *
+ * Gets image data about the currently selected avatar.
+ */
 void
 empathy_avatar_chooser_get_image_data (EmpathyAvatarChooser  *chooser,
                                       const gchar          **data,
index bdc5b40ae1a159905dfd9a8c7f3c1092f6c67f88..564c1f37d3d81e73304ca5cfd680cdcff176d2f1 100644 (file)
@@ -41,6 +41,8 @@ typedef struct _EmpathyAvatarChooserClass   EmpathyAvatarChooserClass;
 
 struct _EmpathyAvatarChooser {
        GtkButton parent;
+
+       /*<private>*/
        gpointer priv;
 };
 
index 51f30bdd501fe07b502d3932f60316066d480bae..e5513231bf82c83cc97b29717d7f344812ab349d 100644 (file)
 #include "empathy-avatar-image.h"
 #include "empathy-ui-utils.h"
 
+/**
+ * SECTION:empathy-avatar-image
+ * @title: EmpathyAvatarImage
+ * @short_description: A widget to display an avatar
+ * @include: libempathy-gtk/empathy-avatar-image.h
+ *
+ * #EmpathyAvatarImage is a widget which displays an avatar.
+ */
+
+/**
+ * EmpathyAvatarImage:
+ * @parent: parent object
+ *
+ * Widget which displays an avatar.
+ */
+
 #define MAX_SMALL 64
 #define MAX_LARGE 400
 
@@ -251,6 +267,13 @@ avatar_image_button_release_event (GtkWidget *widget, GdkEventButton *event)
        return TRUE;
 }
 
+/**
+ * empathy_avatar_image_new:
+ *
+ * Creates a new #EmpathyAvatarImage.
+ *
+ * Return value: a new #EmpathyAvatarImage
+ */
 GtkWidget *
 empathy_avatar_image_new (void)
 {
@@ -261,6 +284,13 @@ empathy_avatar_image_new (void)
        return GTK_WIDGET (avatar_image);
 }
 
+/**
+ * empathy_avatar_image_set:
+ * @avatar_image: an #EmpathyAvatarImage
+ * @avatar: the #EmpathyAvatar to set @avatar_image to
+ *
+ * Sets @avatar_image to display the avatar indicated by @avatar.
+ */
 void
 empathy_avatar_image_set (EmpathyAvatarImage *avatar_image,
                          EmpathyAvatar      *avatar)
index d6a6cd0b08ccfd1a223ccca42bf61e02f9ea4b02..8969c1227541f5a01102061348ee2221e20a71b2 100644 (file)
@@ -42,6 +42,8 @@ typedef struct _EmpathyAvatarImageClass EmpathyAvatarImageClass;
 
 struct _EmpathyAvatarImage {
        GtkEventBox parent;
+
+       /*<private>*/
        gpointer priv;
 };
 
index 7d939027470ce7c18e58751f462424327ade880f..425a1c555a4c41036c6bc40726e849e5886faff9 100644 (file)
@@ -45,7 +45,6 @@
 #include "empathy-chat.h"
 #include "empathy-conf.h"
 #include "empathy-spell.h"
-#include "empathy-spell-dialog.h"
 #include "empathy-contact-list-store.h"
 #include "empathy-contact-list-view.h"
 #include "empathy-contact-menu.h"
@@ -65,7 +64,6 @@
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyChat)
 typedef struct {
        EmpathyTpChat     *tp_chat;
-       gulong            tp_chat_destroy_handler;
        McAccount         *account;
        gchar             *id;
        gchar             *name;
@@ -190,17 +188,15 @@ chat_connect_channel_reconnected (EmpathyDispatchOperation *dispatch,
 }
 
 static void
-chat_connection_changed_cb (EmpathyAccountManager *manager,
-                           McAccount *account,
-                           TpConnectionStatusReason reason,
-                           TpConnectionStatus current,
-                           TpConnectionStatus previous,
-                           EmpathyChat *chat)
+chat_new_connection_cb (EmpathyAccountManager *manager,
+                       TpConnection *connection,
+                       EmpathyChat *chat)
 {
        EmpathyChatPriv *priv = GET_PRIV (chat);
+       McAccount *account;
 
-       if (current == TP_CONNECTION_STATUS_CONNECTED && !priv->tp_chat &&
-           empathy_account_equal (account, priv->account) &&
+       account = empathy_account_manager_get_account (manager, connection);
+       if (!priv->tp_chat && empathy_account_equal (account, priv->account) &&
            priv->handle_type != TP_HANDLE_TYPE_NONE &&
            !EMP_STR_EMPTY (priv->id)) {
                
@@ -208,12 +204,14 @@ chat_connection_changed_cb (EmpathyAccountManager *manager,
 
                switch (priv->handle_type) {
                        case TP_HANDLE_TYPE_CONTACT:
-                               empathy_dispatcher_chat_with_contact_id (account, priv->id,
+                               empathy_dispatcher_chat_with_contact_id (
+                                       connection, priv->id,
                                        chat_connect_channel_reconnected,
                                        chat);
                                break;
                        case TP_HANDLE_TYPE_ROOM:
-                               empathy_dispatcher_join_muc (account, priv->id,
+                               empathy_dispatcher_join_muc (connection,
+                                       priv->id,
                                        chat_connect_channel_reconnected,
                                        chat);
                                break;
@@ -596,7 +594,7 @@ chat_property_changed_cb (EmpathyTpChat *tp_chat,
 
 static void
 chat_input_text_buffer_changed_cb (GtkTextBuffer *buffer,
-                                  EmpathyChat    *chat)
+                                   EmpathyChat    *chat)
 {
        EmpathyChatPriv *priv;
        GtkTextIter     start, end;
@@ -612,8 +610,8 @@ chat_input_text_buffer_changed_cb (GtkTextBuffer *buffer,
        }
 
        empathy_conf_get_bool (empathy_conf_get (),
-                             EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED,
-                             &spell_checker);
+                           EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED,
+                           &spell_checker);
 
        gtk_text_buffer_get_start_iter (buffer, &start);
 
@@ -932,13 +930,42 @@ chat_spell_free (EmpathyChatSpell *chat_spell)
 }
 
 static void
-chat_text_check_word_spelling_cb (GtkMenuItem     *menuitem,
-                                 EmpathyChatSpell *chat_spell)
+chat_spelling_menu_activate_cb (GtkMenuItem     *menu_item,
+                                               EmpathyChatSpell *chat_spell)
 {
-       empathy_spell_dialog_show (chat_spell->chat,
-                                 &chat_spell->start,
-                                 &chat_spell->end,
-                                 chat_spell->word);
+    empathy_chat_correct_word (chat_spell->chat,
+                               &(chat_spell->start),
+                               &(chat_spell->end),
+                               gtk_menu_item_get_label (menu_item));
+}
+
+static GtkWidget*
+chat_spelling_build_menu (EmpathyChatSpell *chat_spell)
+{
+    GtkWidget *menu, *menu_item;
+    GList     *suggestions, *l;
+
+    menu = gtk_menu_new ();
+    suggestions = empathy_spell_get_suggestions (chat_spell->word);
+    if (suggestions == NULL) {
+        menu_item = gtk_menu_item_new_with_label (_("(No Suggestions)"));
+       gtk_widget_set_sensitive (menu_item, FALSE);
+        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+    } else {
+        for (l = suggestions; l; l = l->next) {
+            menu_item = gtk_menu_item_new_with_label (l->data);
+            g_signal_connect (G_OBJECT (menu_item),
+                          "activate",
+                          G_CALLBACK (chat_spelling_menu_activate_cb),
+                          chat_spell);
+            gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+        }
+    }
+    empathy_spell_free_suggestions (suggestions);
+
+    gtk_widget_show_all (menu);
+
+    return menu;
 }
 
 static void
@@ -961,7 +988,8 @@ chat_input_populate_popup_cb (GtkTextView *view,
        GtkTextIter           iter, start, end;
        GtkWidget            *item;
        gchar                *str = NULL;
-       EmpathyChatSpell      *chat_spell;
+       EmpathyChatSpell     *chat_spell;
+       GtkWidget            *spell_menu;
        EmpathySmileyManager *smiley_manager;
        GtkWidget            *smiley_menu;
        GtkWidget            *image;
@@ -1026,14 +1054,14 @@ chat_input_populate_popup_cb (GtkTextView *view,
                gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
                gtk_widget_show (item);
 
-               item = gtk_image_menu_item_new_with_mnemonic (_("_Check Word Spelling..."));
+               item = gtk_image_menu_item_new_with_mnemonic (_("_Spelling Suggestions"));
                image = gtk_image_new_from_icon_name (GTK_STOCK_SPELL_CHECK,
                                                      GTK_ICON_SIZE_MENU);
                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
-               g_signal_connect (item,
-                                 "activate",
-                                 G_CALLBACK (chat_text_check_word_spelling_cb),
-                                 chat_spell);
+
+               spell_menu = chat_spelling_build_menu (chat_spell);
+               gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), spell_menu);
+
                gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
                gtk_widget_show (item);
        }
@@ -1139,10 +1167,6 @@ chat_members_changed_cb (EmpathyTpChat  *tp_chat,
        if (priv->block_events_timeout_id == 0) {
                gchar *str;
 
-               empathy_contact_run_until_ready (contact,
-                                                EMPATHY_CONTACT_READY_NAME,
-                                                NULL);
-
                if (is_member) {
                        str = g_strdup_printf (_("%s has joined the room"),
                                               empathy_contact_get_name (contact));
@@ -1434,13 +1458,26 @@ chat_finalize (GObject *object)
        chat_composing_remove_timeout (chat);
 
        g_signal_handlers_disconnect_by_func (priv->account_manager,
-                                             chat_connection_changed_cb, object);
+                                             chat_new_connection_cb, object);
 
        g_object_unref (priv->account_manager);
        g_object_unref (priv->log_manager);
 
        if (priv->tp_chat) {
-               g_signal_handler_disconnect (priv->tp_chat, priv->tp_chat_destroy_handler);
+               g_signal_handlers_disconnect_by_func (priv->tp_chat,
+                       chat_destroy_cb, chat);
+               g_signal_handlers_disconnect_by_func (priv->tp_chat,
+                       chat_message_received_cb, chat);
+               g_signal_handlers_disconnect_by_func (priv->tp_chat,
+                       chat_send_error_cb, chat);
+               g_signal_handlers_disconnect_by_func (priv->tp_chat,
+                       chat_state_changed_cb, chat);
+               g_signal_handlers_disconnect_by_func (priv->tp_chat,
+                       chat_property_changed_cb, chat);
+               g_signal_handlers_disconnect_by_func (priv->tp_chat,
+                       chat_members_changed_cb, chat);
+               g_signal_handlers_disconnect_by_func (priv->tp_chat,
+                       chat_remote_contact_changed_cb, chat);
                empathy_tp_chat_close (priv->tp_chat);
                g_object_unref (priv->tp_chat);
        }
@@ -1578,8 +1615,8 @@ empathy_chat_init (EmpathyChat *chat)
        priv->account_manager = empathy_account_manager_dup_singleton ();
 
        g_signal_connect (priv->account_manager,
-                         "account-connection-changed",
-                         G_CALLBACK (chat_connection_changed_cb),
+                         "new-connection",
+                         G_CALLBACK (chat_new_connection_cb),
                          chat);
 
        /* Block events for some time to avoid having "has come online" or
@@ -1613,6 +1650,7 @@ empathy_chat_set_tp_chat (EmpathyChat   *chat,
                          EmpathyTpChat *tp_chat)
 {
        EmpathyChatPriv *priv = GET_PRIV (chat);
+       TpConnection    *connection;
 
        g_return_if_fail (EMPATHY_IS_CHAT (chat));
        g_return_if_fail (EMPATHY_IS_TP_CHAT (tp_chat));
@@ -1627,8 +1665,14 @@ empathy_chat_set_tp_chat (EmpathyChat   *chat,
        }
 
        priv->tp_chat = g_object_ref (tp_chat);
-       priv->account = g_object_ref (empathy_tp_chat_get_account (tp_chat));
+       connection = empathy_tp_chat_get_connection (priv->tp_chat);
+       priv->account = empathy_account_manager_get_account (priv->account_manager,
+                                                            connection);
+       g_object_ref (priv->account);
 
+       g_signal_connect (tp_chat, "destroy",
+                         G_CALLBACK (chat_destroy_cb),
+                         chat);
        g_signal_connect (tp_chat, "message-received",
                          G_CALLBACK (chat_message_received_cb),
                          chat);
@@ -1647,10 +1691,6 @@ empathy_chat_set_tp_chat (EmpathyChat   *chat,
        g_signal_connect_swapped (tp_chat, "notify::remote-contact",
                                  G_CALLBACK (chat_remote_contact_changed_cb),
                                  chat);
-       priv->tp_chat_destroy_handler =
-               g_signal_connect (tp_chat, "destroy",
-                         G_CALLBACK (chat_destroy_cb),
-                         chat);
 
        chat_remote_contact_changed_cb (chat);
 
@@ -1730,20 +1770,6 @@ empathy_chat_get_remote_contact (EmpathyChat *chat)
        return priv->remote_contact;
 }
 
-guint
-empathy_chat_get_members_count (EmpathyChat *chat)
-{
-       EmpathyChatPriv *priv = GET_PRIV (chat);
-
-       g_return_val_if_fail (EMPATHY_IS_CHAT (chat), 0);
-
-       if (priv->tp_chat) {
-               return empathy_tp_chat_get_members_count (priv->tp_chat);
-       }
-
-       return 0;
-}
-
 GtkWidget *
 empathy_chat_get_contact_menu (EmpathyChat *chat)
 {
index 6b7fcf26e1d0a13a80a0e6a2900e1d0267121a8b..f61ce415415d7ba9700059280c2aef897c87b8b7 100644 (file)
@@ -71,7 +71,6 @@ const gchar *      empathy_chat_get_id               (EmpathyChat   *chat);
 const gchar *      empathy_chat_get_name             (EmpathyChat   *chat);
 const gchar *      empathy_chat_get_subject          (EmpathyChat   *chat);
 EmpathyContact *   empathy_chat_get_remote_contact   (EmpathyChat   *chat);
-guint              empathy_chat_get_members_count    (EmpathyChat   *chat);
 GtkWidget *        empathy_chat_get_contact_menu     (EmpathyChat   *chat);
 void               empathy_chat_clear                (EmpathyChat   *chat);
 void               empathy_chat_scroll_down          (EmpathyChat   *chat);
index 72b5b28b38be9eb4d4611d0e582c7504e8d12031..056ec2d856093b768a80ed0473e18b235a64f503 100644 (file)
@@ -30,6 +30,7 @@
 #include <libmissioncontrol/mission-control.h>
 
 #include <libempathy/empathy-contact-manager.h>
+#include <libempathy/empathy-account-manager.h>
 #include <libempathy/empathy-contact-list.h>
 #include <libempathy/empathy-utils.h>
 
 
 static GList *subscription_dialogs = NULL;
 static GList *information_dialogs = NULL;
+static GList *edit_dialogs = NULL;
+static GtkWidget *personal_dialog = NULL;
 static GtkWidget *new_contact_dialog = NULL;
 
-
 static gint
 contact_dialogs_find (GtkDialog      *dialog,
                      EmpathyContact *contact)
@@ -114,6 +116,7 @@ empathy_subscription_dialog_show (EmpathyContact *contact,
        g_free (filename);
        g_object_unref (gui);
 
+       /* Contact info widget */
        contact_widget = empathy_contact_widget_new (contact,
                                                     EMPATHY_CONTACT_WIDGET_EDIT_ALIAS |
                                                     EMPATHY_CONTACT_WIDGET_EDIT_GROUPS);
@@ -123,7 +126,6 @@ empathy_subscription_dialog_show (EmpathyContact *contact,
                          0);
        gtk_widget_show (contact_widget);
 
-
        g_object_set_data (G_OBJECT (dialog), "contact_widget", contact_widget);
        subscription_dialogs = g_list_prepend (subscription_dialogs, dialog);
 
@@ -143,25 +145,22 @@ empathy_subscription_dialog_show (EmpathyContact *contact,
  */
 
 static void
-contact_information_response_cb (GtkDialog *dialog,
-                                gint       response,
-                                GtkWidget *contact_widget)
+contact_dialogs_response_cb (GtkDialog *dialog,
+                            gint       response,
+                            GList    **dialogs)
 {
-       information_dialogs = g_list_remove (information_dialogs, dialog);
+       *dialogs = g_list_remove (*dialogs, dialog);
        gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
 void
 empathy_contact_information_dialog_show (EmpathyContact *contact,
-                                        GtkWindow      *parent,
-                                        gboolean        edit,
-                                        gboolean        is_user)
+                                        GtkWindow      *parent)
 {
-       GtkWidget                *dialog;
-       GtkWidget                *button;
-       GtkWidget                *contact_widget;
-       GList                    *l;
-       EmpathyContactWidgetFlags flags = 0;
+       GtkWidget *dialog;
+       GtkWidget *button;
+       GtkWidget *contact_widget;
+       GList     *l;
 
        g_return_if_fail (EMPATHY_IS_CONTACT (contact));
 
@@ -177,15 +176,7 @@ empathy_contact_information_dialog_show (EmpathyContact *contact,
        dialog = gtk_dialog_new ();
        gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
        gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
-       if (is_user) {
-               gtk_window_set_title (GTK_WINDOW (dialog), _("Personal Information"));
-       }
-       else if (edit) {
-               gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Contact Information"));
-       }
-       else {
-               gtk_window_set_title (GTK_WINDOW (dialog), _("Contact Information"));
-       }
+       gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Contact Information"));
 
        /* Close button */
        button = gtk_button_new_with_label (GTK_STOCK_CLOSE);
@@ -198,34 +189,79 @@ empathy_contact_information_dialog_show (EmpathyContact *contact,
        gtk_widget_show (button);
 
        /* Contact info widget */
-       if (edit) {
-               flags |= EMPATHY_CONTACT_WIDGET_EDIT_ALIAS;
-       }
-       if (is_user) {
-               flags |= EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT;
-               flags |= EMPATHY_CONTACT_WIDGET_EDIT_AVATAR;
+       contact_widget = empathy_contact_widget_new (contact,
+               EMPATHY_CONTACT_WIDGET_EDIT_NONE);
+       gtk_container_set_border_width (GTK_CONTAINER (contact_widget), 8);
+       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+                           contact_widget,
+                           TRUE, TRUE, 0);
+       gtk_widget_show (contact_widget);
+
+       g_object_set_data (G_OBJECT (dialog), "contact_widget", contact_widget);
+       information_dialogs = g_list_prepend (information_dialogs, dialog);
+
+       g_signal_connect (dialog, "response",
+                         G_CALLBACK (contact_dialogs_response_cb),
+                         &information_dialogs);
+
+       if (parent) {
+               gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
        }
-       if (!is_user && edit) {
-               flags |= EMPATHY_CONTACT_WIDGET_EDIT_GROUPS;
+
+       gtk_widget_show (dialog);
+}
+
+void
+empathy_contact_edit_dialog_show (EmpathyContact *contact,
+                                 GtkWindow      *parent)
+{
+       GtkWidget *dialog;
+       GtkWidget *button;
+       GtkWidget *contact_widget;
+       GList     *l;
+
+       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+       l = g_list_find_custom (edit_dialogs,
+                               contact,
+                               (GCompareFunc) contact_dialogs_find);
+       if (l) {
+               gtk_window_present (GTK_WINDOW (l->data));
+               return;
        }
-       contact_widget = empathy_contact_widget_new (contact, flags);
+
+       /* Create dialog */
+       dialog = gtk_dialog_new ();
+       gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+       gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+       gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Contact Information"));
+
+       /* Close button */
+       button = gtk_button_new_with_label (GTK_STOCK_CLOSE);
+       gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
+       gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
+                                     button,
+                                     GTK_RESPONSE_CLOSE);
+       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+       gtk_window_set_default (GTK_WINDOW (dialog), button);
+       gtk_widget_show (button);
+
+       /* Contact info widget */
+       contact_widget = empathy_contact_widget_new (contact,
+               EMPATHY_CONTACT_WIDGET_EDIT_ALIAS |
+               EMPATHY_CONTACT_WIDGET_EDIT_GROUPS);
        gtk_container_set_border_width (GTK_CONTAINER (contact_widget), 8);
        gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
                            contact_widget,
                            TRUE, TRUE, 0);
-       if (flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT) {
-               empathy_contact_widget_set_account_filter (contact_widget,
-                                                          empathy_account_chooser_filter_is_connected,
-                                                          NULL);
-       }
        gtk_widget_show (contact_widget);
 
        g_object_set_data (G_OBJECT (dialog), "contact_widget", contact_widget);
-       information_dialogs = g_list_prepend (information_dialogs, dialog);
+       edit_dialogs = g_list_prepend (edit_dialogs, dialog);
 
        g_signal_connect (dialog, "response",
-                         G_CALLBACK (contact_information_response_cb),
-                         contact_widget);
+                         G_CALLBACK (contact_dialogs_response_cb),
+                         &edit_dialogs);
 
        if (parent) {
                gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
@@ -234,6 +270,58 @@ empathy_contact_information_dialog_show (EmpathyContact *contact,
        gtk_widget_show (dialog);
 }
 
+void
+empathy_contact_personal_dialog_show (GtkWindow *parent)
+{
+       GtkWidget *button;
+       GtkWidget *contact_widget;
+
+       if (personal_dialog) {
+               gtk_window_present (GTK_WINDOW (personal_dialog));
+               return;
+       }
+
+       /* Create dialog */
+       personal_dialog = gtk_dialog_new ();
+       gtk_dialog_set_has_separator (GTK_DIALOG (personal_dialog), FALSE);
+       gtk_window_set_resizable (GTK_WINDOW (personal_dialog), FALSE);
+       gtk_window_set_title (GTK_WINDOW (personal_dialog), _("Personal Information"));
+
+       /* Close button */
+       button = gtk_button_new_with_label (GTK_STOCK_CLOSE);
+       gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
+       gtk_dialog_add_action_widget (GTK_DIALOG (personal_dialog),
+                                     button,
+                                     GTK_RESPONSE_CLOSE);
+       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+       gtk_window_set_default (GTK_WINDOW (personal_dialog), button);
+       gtk_widget_show (button);
+
+       /* Contact info widget */
+       contact_widget = empathy_contact_widget_new (NULL,
+               EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT |
+               EMPATHY_CONTACT_WIDGET_EDIT_ALIAS |
+               EMPATHY_CONTACT_WIDGET_EDIT_AVATAR);
+       gtk_container_set_border_width (GTK_CONTAINER (contact_widget), 8);
+       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (personal_dialog)->vbox),
+                           contact_widget,
+                           TRUE, TRUE, 0);
+       empathy_contact_widget_set_account_filter (contact_widget,
+               empathy_account_chooser_filter_is_connected, NULL);
+       gtk_widget_show (contact_widget);
+
+       g_signal_connect (personal_dialog, "response",
+                         G_CALLBACK (gtk_widget_destroy), NULL);
+       g_object_add_weak_pointer (G_OBJECT (personal_dialog),
+                                  (gpointer) &personal_dialog);
+
+       if (parent) {
+               gtk_window_set_transient_for (GTK_WINDOW (personal_dialog), parent);
+       }
+
+       gtk_widget_show (personal_dialog);
+}
+
 /*
  *  New contact dialog
  */
@@ -242,12 +330,23 @@ static gboolean
 can_add_contact_to_account (McAccount *account,
                            gpointer   user_data)
 {
-       EmpathyContactManager *mgr;
+       EmpathyAccountManager *account_manager;
+       EmpathyContactManager *contact_manager;
+       TpConnection          *connection;
        gboolean               result;
 
-       mgr = empathy_contact_manager_dup_singleton ();
-       result = empathy_contact_manager_can_add (mgr, account);
-       g_object_unref (mgr);
+       account_manager = empathy_account_manager_dup_singleton ();
+       connection = empathy_account_manager_get_connection (account_manager,
+                                                            account);
+       if (!connection) {
+               g_object_unref (account_manager);
+               return FALSE;
+       }
+
+       contact_manager = empathy_contact_manager_dup_singleton ();
+       result = empathy_contact_manager_can_add (contact_manager, connection);
+       g_object_unref (contact_manager);
+       g_object_unref (account_manager);
 
        return result;
 }
index e375f959cf0833ee6dda19a1ad6fc0d21e9da4f8..c714c6b9611d3560762d35a5b21cfa99cbc098d0 100644 (file)
 G_BEGIN_DECLS
 
 void empathy_subscription_dialog_show        (EmpathyContact *contact,
-                                             GtkWindow     *parent);
+                                             GtkWindow      *parent);
 void empathy_contact_information_dialog_show (EmpathyContact *contact,
-                                             GtkWindow     *parent,
-                                             gboolean       edit,
-                                             gboolean       is_user);
-void empathy_new_contact_dialog_show         (GtkWindow     *parent);
+                                             GtkWindow      *parent);
+void empathy_contact_edit_dialog_show        (EmpathyContact *contact,
+                                             GtkWindow      *parent);
+void empathy_contact_personal_dialog_show    (GtkWindow      *parent);
+void empathy_new_contact_dialog_show         (GtkWindow      *parent);
 
 G_END_DECLS
 
index 3fdc7b327a91b7c83ee9890508f7cf025e88d791..ca224f52631be53cffa9043d08c45d62d78a4265 100644 (file)
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtk.h>
 
+#include <telepathy-glib/util.h>
 #include <libmissioncontrol/mc-account.h>
 
+#include <libempathy/empathy-account-manager.h>
 #include <libempathy/empathy-call-factory.h>
-#include <libempathy/empathy-contact-factory.h>
+#include <libempathy/empathy-tp-contact-factory.h>
 #include <libempathy/empathy-contact-list.h>
 #include <libempathy/empathy-contact-groups.h>
 #include <libempathy/empathy-dispatcher.h>
@@ -122,8 +124,8 @@ contact_list_view_tooltip_destroy_cb (GtkWidget              *widget,
        
        if (priv->tooltip_widget) {
                DEBUG ("Tooltip destroyed");
+               g_object_unref (priv->tooltip_widget);
                priv->tooltip_widget = NULL;
-               g_object_unref (widget);
        }
 }
 
@@ -188,8 +190,52 @@ OUT:
        return ret;
 }
 
+typedef struct {
+       gchar *new_group;
+       gchar *old_group;
+       GdkDragAction action;
+} DndGetContactData;
+
+static void
+contact_list_view_dnd_get_contact_free (DndGetContactData *data)
+{
+       g_free (data->new_group);
+       g_free (data->old_group);
+       g_slice_free (DndGetContactData, data);
+}
+
 static void
-contact_list_view_drag_data_received (GtkWidget         *widget,
+contact_list_view_drag_got_contact (EmpathyTpContactFactory *factory,
+                                   EmpathyContact          *contact,
+                                   const GError            *error,
+                                   gpointer                 user_data,
+                                   GObject                 *view)
+{
+       EmpathyContactListViewPriv *priv = GET_PRIV (view);
+       DndGetContactData          *data = user_data;
+       EmpathyContactList         *list;
+
+       if (error != NULL) {
+               DEBUG ("Error: %s", error->message);
+               return;
+       }
+
+       DEBUG ("contact %s (%d) dragged from '%s' to '%s'",
+               empathy_contact_get_id (contact),
+               empathy_contact_get_handle (contact),
+               data->old_group, data->new_group);
+
+       list = empathy_contact_list_store_get_list_iface (priv->store);
+       if (data->new_group) {
+               empathy_contact_list_add_to_group (list, contact, data->new_group);
+       }
+       if (data->old_group && data->action == GDK_ACTION_MOVE) {       
+               empathy_contact_list_remove_from_group (list, contact, data->old_group);
+       }
+}
+
+static void
+contact_list_view_drag_data_received (GtkWidget         *view,
                                      GdkDragContext    *context,
                                      gint               x,
                                      gint               y,
@@ -198,88 +244,102 @@ contact_list_view_drag_data_received (GtkWidget         *widget,
                                      guint              time)
 {
        EmpathyContactListViewPriv *priv;
-       EmpathyContactList         *list;
-       EmpathyContactFactory      *factory;
+       EmpathyAccountManager      *account_manager;
+       EmpathyTpContactFactory    *factory = NULL;
        McAccount                  *account;
        GtkTreeModel               *model;
-       GtkTreePath                *path;
        GtkTreeViewDropPosition     position;
-       EmpathyContact             *contact = NULL;
+       GtkTreePath                *path;
        const gchar                *id;
-       gchar                     **strv;
+       gchar                     **strv = NULL;
+       const gchar                *account_id;
+       const gchar                *contact_id;
        gchar                      *new_group = NULL;
        gchar                      *old_group = NULL;
+       DndGetContactData          *data;
        gboolean                    is_row;
+       gboolean                    success = TRUE;
 
-       priv = GET_PRIV (widget);
-
-       id = (const gchar*) selection->data;
-       DEBUG ("Received %s%s drag & drop contact from roster with id:'%s'",
-               context->action == GDK_ACTION_MOVE ? "move" : "",
-               context->action == GDK_ACTION_COPY ? "copy" : "",
-               id);
+       priv = GET_PRIV (view);
+       model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
 
-       strv = g_strsplit (id, "/", 2);
-       factory = empathy_contact_factory_dup_singleton ();
-       account = mc_account_lookup (strv[0]);
-       if (account) {
-               contact = empathy_contact_factory_get_from_id (factory,
-                                                              account,
-                                                              strv[1]);
-               g_object_unref (account);
-       }
-       g_object_unref (factory);
-       g_strfreev (strv);
+       /* Get destination group information. */
+       is_row = gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (view),
+                                                   x,
+                                                   y,
+                                                   &path,
+                                                   &position);
 
-       if (!contact) {
-               DEBUG ("No contact found associated with drag & drop");
-               return;
+       if (is_row) {
+               new_group = empathy_contact_list_store_get_parent_group (model,
+                       path, NULL);
+               gtk_tree_path_free (path);
        }
 
-       empathy_contact_run_until_ready (contact,
-                                        EMPATHY_CONTACT_READY_HANDLE,
-                                        NULL);
-
-       model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
-
        /* Get source group information. */
        if (priv->drag_row) {
                path = gtk_tree_row_reference_get_path (priv->drag_row);
                if (path) {
-                       old_group = empathy_contact_list_store_get_parent_group (model, path, NULL);
+                       old_group = empathy_contact_list_store_get_parent_group (
+                               model, path, NULL);
                        gtk_tree_path_free (path);
                }
        }
 
-       /* Get destination group information. */
-       is_row = gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (widget),
-                                                   x,
-                                                   y,
-                                                   &path,
-                                                   &position);
-
-       if (is_row) {
-               new_group = empathy_contact_list_store_get_parent_group (model, path, NULL);
-               gtk_tree_path_free (path);
+       if (!tp_strdiff (old_group, new_group)) {
+               g_free (new_group);
+               g_free (old_group);
+               goto OUT;
        }
 
-       DEBUG ("contact %s (%d) dragged from '%s' to '%s'",
-               empathy_contact_get_id (contact),
-               empathy_contact_get_handle (contact),
-               old_group, new_group);
+       id = (const gchar*) selection->data;
+       DEBUG ("Received %s%s drag & drop contact from roster with id:'%s'",
+               context->action == GDK_ACTION_MOVE ? "move" : "",
+               context->action == GDK_ACTION_COPY ? "copy" : "",
+               id);
 
-       list = empathy_contact_list_store_get_list_iface (priv->store);
-       if (new_group) {
-               empathy_contact_list_add_to_group (list, contact, new_group);
+       strv = g_strsplit (id, "/", 2);
+       account_id = strv[0];
+       contact_id = strv[1];
+       account = mc_account_lookup (account_id);
+       if (account) {
+               TpConnection *connection;
+
+               /* FIXME: We assume we have already an account manager */
+               account_manager = empathy_account_manager_dup_singleton ();
+               connection = empathy_account_manager_get_connection (account_manager,
+                                                                    account);
+               if (connection) {
+                       factory = empathy_tp_contact_factory_dup_singleton (connection);
+               }
+               g_object_unref (account_manager);
        }
-       if (old_group && context->action == GDK_ACTION_MOVE) {  
-               empathy_contact_list_remove_from_group (list, contact, old_group);
+
+       if (!factory) {
+               DEBUG ("Failed to get factory for account '%s'", account_id);
+               success = FALSE;
+               g_free (new_group);
+               g_free (old_group);
+               goto OUT;
        }
 
-       g_free (old_group);
-       g_free (new_group);
+       data = g_slice_new0 (DndGetContactData);
+       data->new_group = new_group;
+       data->old_group = old_group;
+       data->action = context->action;
 
-       gtk_drag_finish (context, TRUE, FALSE, GDK_CURRENT_TIME);
+       /* FIXME: We should probably wait for the cb before calling
+        * gtk_drag_finish */
+       empathy_tp_contact_factory_get_from_id (factory, contact_id,
+               contact_list_view_drag_got_contact,
+               data, (GDestroyNotify) contact_list_view_dnd_get_contact_free,
+               G_OBJECT (view));
+
+       g_object_unref (factory);
+
+OUT:
+       g_strfreev (strv);
+       gtk_drag_finish (context, success, FALSE, GDK_CURRENT_TIME);
 }
 
 static gboolean
@@ -414,7 +474,7 @@ contact_list_view_drag_data_get (GtkWidget        *widget,
 
        gtk_tree_path_free (src_path);
 
-       contact = empathy_contact_list_view_get_selected (EMPATHY_CONTACT_LIST_VIEW (widget));
+       contact = empathy_contact_list_view_dup_selected (EMPATHY_CONTACT_LIST_VIEW (widget));
        if (!contact) {
                return;
        }
@@ -1158,7 +1218,7 @@ empathy_contact_list_view_new (EmpathyContactListStore        *store,
 }
 
 EmpathyContact *
-empathy_contact_list_view_get_selected (EmpathyContactListView *view)
+empathy_contact_list_view_dup_selected (EmpathyContactListView *view)
 {
        EmpathyContactListViewPriv *priv;
        GtkTreeSelection          *selection;
@@ -1324,7 +1384,7 @@ contact_list_view_remove_activate_cb (GtkMenuItem            *menuitem,
        EmpathyContactListViewPriv *priv = GET_PRIV (view);
        EmpathyContact             *contact;
                
-       contact = empathy_contact_list_view_get_selected (view);
+       contact = empathy_contact_list_view_dup_selected (view);
 
        if (contact) {
                gchar     *text; 
@@ -1357,7 +1417,7 @@ empathy_contact_list_view_get_contact_menu (EmpathyContactListView *view)
 
        g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST_VIEW (view), NULL);
 
-       contact = empathy_contact_list_view_get_selected (view);
+       contact = empathy_contact_list_view_dup_selected (view);
        if (!contact) {
                return NULL;
        }
index 82990d64f5e9b19c050b3acef7154c6d17c4acd6..bb6766c4a9848e48790010ffd3f5e59a925006e3 100644 (file)
@@ -70,7 +70,7 @@ GType                      empathy_contact_list_view_get_type           (void) G
 EmpathyContactListView *   empathy_contact_list_view_new                (EmpathyContactListStore        *store,
                                                                         EmpathyContactListFeatureFlags  list_features,
                                                                         EmpathyContactFeatureFlags      contact_features);
-EmpathyContact *           empathy_contact_list_view_get_selected       (EmpathyContactListView         *view);
+EmpathyContact *           empathy_contact_list_view_dup_selected       (EmpathyContactListView         *view);
 gchar *                    empathy_contact_list_view_get_selected_group (EmpathyContactListView         *view);
 GtkWidget *                empathy_contact_list_view_get_contact_menu   (EmpathyContactListView         *view);
 GtkWidget *                empathy_contact_list_view_get_group_menu     (EmpathyContactListView         *view);
index 9cd9a0b9fb5f1c9a89eefffa7d587f5713b00e58..a3cf1da26f71aeedf5874d1e26c48d96f6cec19c 100644 (file)
@@ -236,7 +236,7 @@ empathy_contact_file_transfer_menu_item_new (EmpathyContact *contact)
 static void
 contact_info_menu_item_activate_cb (EmpathyContact *contact)
 {
-       empathy_contact_information_dialog_show (contact, NULL, FALSE, FALSE);
+       empathy_contact_information_dialog_show (contact, NULL);
 }
 
 GtkWidget *
@@ -263,7 +263,7 @@ empathy_contact_info_menu_item_new (EmpathyContact *contact)
 static void
 contact_edit_menu_item_activate_cb (EmpathyContact *contact)
 {
-       empathy_contact_information_dialog_show (contact, NULL, TRUE, FALSE);
+       empathy_contact_edit_dialog_show (contact, NULL);
 }
 
 GtkWidget *
index 539629a234de8d31aa50c2d0a41f4b52dd348ea8..f4a302c5bcb1a1d4bcfb326b2c657a34883fa12d 100644 (file)
 
 #include "empathy-contact-selector.h"
 
+/**
+ * SECTION:empathy-contact-selector
+ * @title:EmpathyContactSelector
+ * @short_description: A widget used to choose from a list of contacts.
+ * @include: libempathy-gtk/empathy-contact-selector.h
+ *
+ * #EmpathyContactSelector is a widget which extends #GtkComboBox to provide
+ * a chooser of available contacts.
+ */
+
+/**
+ * EmpathyContactSelector:
+ * @parent: parent object
+ *
+ * Widget which extends #GtkComboBox to provide a chooser of available contacts.
+ */
+
 G_DEFINE_TYPE (EmpathyContactSelector, empathy_contact_selector,
     GTK_TYPE_COMBO_BOX)
 
@@ -320,14 +337,27 @@ empathy_contact_selector_class_init (EmpathyContactSelectorClass *klass)
   object_class->get_property = contact_selector_get_property;
   g_type_class_add_private (klass, sizeof (EmpathyContactSelectorPriv));
 
+  /**
+   * EmpathyContactSelector:contact-list:
+   *
+   * An #EmpathyContactList containing the contacts for the
+   * #EmpathyContactSelector.
+   */
   g_object_class_install_property (object_class, PROP_CONTACT_LIST,
       g_param_spec_object ("contact-list", "contact list", "contact list",
       EMPATHY_TYPE_CONTACT_LIST, G_PARAM_CONSTRUCT_ONLY |
       G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
 }
 
-/* public methods */
-
+/**
+ * empathy_contact_selector_new:
+ * @contact_list: an #EmpathyContactList containing the contacts to list in
+ * the contact selector
+ *
+ * Creates a new #EmpathyContactSelector.
+ *
+ * Return value: A new #EmpathyContactSelector
+ */
 GtkWidget *
 empathy_contact_selector_new (EmpathyContactList *contact_list)
 {
@@ -337,6 +367,16 @@ empathy_contact_selector_new (EmpathyContactList *contact_list)
       "contact-list", contact_list, NULL));
 }
 
+/**
+ * empathy_contact_selector_dup_selected:
+ * @selector: An #EmpathyContactSelector
+ *
+ * Returns a new reference to the contact which is currently selected in
+ * @selector, or %NULL if there is no contact selected. The returned contact
+ * should be unrefed with g_object_unref() when finished with.
+ *
+ * Return value: A new reference to the contact currently selected, or %NULL
+ */
 EmpathyContact *
 empathy_contact_selector_dup_selected (EmpathyContactSelector *selector)
 {
@@ -390,6 +430,19 @@ contact_selector_filter_visible_func (GtkTreeModel *model,
   return visible;
 }
 
+/**
+ * empathy_contact_selector_set_visible:
+ * @selector: an #EmpathyContactSelector
+ * @func: an #EmpathyContactSelectorFilterFunc to filter the contacts
+ * @user_data: data to pass to @func or %NULL
+ *
+ * Sets a filter on the @selector so only contacts that return %TRUE
+ * when passed into @func are visible.
+ *
+ * A typical usage for this function would be to only show contacts that
+ * can send or receive files. In this case, one could use the
+ * empathy_contact_can_send_files() function
+ */
 void
 empathy_contact_selector_set_visible (EmpathyContactSelector *selector,
                                       EmpathyContactSelectorFilterFunc func,
@@ -407,3 +460,14 @@ empathy_contact_selector_set_visible (EmpathyContactSelector *selector,
 
   gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->model));
 }
+
+/**
+ * EmpathyContactSelectorFilterFunc:
+ * @contact: an #EmpathyContact
+ * @user_data: user data or %NULL
+ *
+ * A function which decides whether the contact indicated by @contact
+ * is visible.
+ *
+ * Return value: whether @contact is visible
+ */
index f7af92f2cfc4e010ab26a84e47339fd280d27a62..205b9e411466701a2715cef19b98f4d1f012dcef 100644 (file)
@@ -49,6 +49,8 @@ typedef struct _EmpathyContactSelectorClass EmpathyContactSelectorClass;
 struct _EmpathyContactSelector
 {
   GtkComboBox parent;
+
+  /*<private>*/
   gpointer priv;
 };
 
index ef259b0a44b607da26b11fc717ac1fcd8bbaf403..0821066fa55bb2d724f76e816c291910ef7ada63 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2009 Collabora Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -30,7 +30,7 @@
 #include <libmissioncontrol/mc-account.h>
 #include <telepathy-glib/util.h>
 
-#include <libempathy/empathy-contact-factory.h>
+#include <libempathy/empathy-tp-contact-factory.h>
 #include <libempathy/empathy-contact-manager.h>
 #include <libempathy/empathy-contact-list.h>
 #include <libempathy/empathy-utils.h>
 #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
 #include <libempathy/empathy-debug.h>
 
+/**
+ * SECTION:empathy-contact-widget
+ * @title:EmpathyContactWidget
+ * @short_description: A widget used to display and edit details about a contact
+ * @include: libempathy-empathy-contact-widget.h
+ *
+ * #EmpathyContactWidget is a widget which displays appropriate widgets
+ * with details about a contact, also allowing changing these details,
+ * if desired.
+ */
+
+/**
+ * EmpathyContactWidget:
+ * @parent: parent object
+ *
+ * Widget which displays appropriate widgets with details about a contact,
+ * also allowing changing these details, if desired.
+ */
+
 /* Delay before updating the widget when the id entry changed (seconds) */
 #define ID_CHANGED_TIMEOUT 1
 
 typedef struct
 {
-  EmpathyContactFactory *factory;
+  EmpathyTpContactFactory *factory;
   EmpathyContactManager *manager;
   EmpathyContact *contact;
   EmpathyContactWidgetFlags flags;
@@ -106,8 +125,6 @@ static void contact_widget_contact_update (EmpathyContactWidget *information);
 static void contact_widget_change_contact (EmpathyContactWidget *information);
 static void contact_widget_avatar_changed_cb (EmpathyAvatarChooser *chooser,
     EmpathyContactWidget *information);
-static void contact_widget_account_changed_cb (GtkComboBox *widget,
-    EmpathyContactWidget *information);
 static gboolean contact_widget_id_focus_out_cb (GtkWidget *widget,
     GdkEventFocus *event, EmpathyContactWidget *information);
 static gboolean contact_widget_entry_alias_focus_event_cb (
@@ -153,6 +170,15 @@ enum
   COL_COUNT
 };
 
+/**
+ * empathy_contact_widget_new:
+ * @contact: an #EmpathyContact
+ * @flags: #EmpathyContactWidgetFlags for the new contact widget
+ *
+ * Creates a new #EmpathyContactWidget.
+ *
+ * Return value: a new #EmpathyContactWidget
+ */
 GtkWidget *
 empathy_contact_widget_new (EmpathyContact *contact,
                             EmpathyContactWidgetFlags flags)
@@ -161,9 +187,10 @@ empathy_contact_widget_new (EmpathyContact *contact,
   GtkBuilder *gui;
   gchar *filename;
 
+  g_return_val_if_fail (contact == NULL || EMPATHY_IS_CONTACT (contact), NULL);
+
   information = g_slice_new0 (EmpathyContactWidget);
   information->flags = flags;
-  information->factory = empathy_contact_factory_dup_singleton ();
 
   filename = empathy_file_lookup ("empathy-contact-widget.ui",
       "libempathy-gtk");
@@ -206,12 +233,25 @@ empathy_contact_widget_new (EmpathyContact *contact,
   contact_widget_details_setup (information);
   contact_widget_client_setup (information);
 
-  contact_widget_set_contact (information, contact);
+  if (contact != NULL)
+    contact_widget_set_contact (information, contact);
+
+  else if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT ||
+      information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID)
+    contact_widget_change_contact (information);
 
   return empathy_builder_unref_and_keep_widget (gui,
     information->vbox_contact_widget);
 }
 
+/**
+ * empathy_contact_widget_get_contact:
+ * @widget: an #EmpathyContactWidget
+ *
+ * Get the #EmpathyContact related with the #EmpathyContactWidget @widget.
+ *
+ * Returns: the #EmpathyContact associated with @widget
+ */
 EmpathyContact *
 empathy_contact_widget_get_contact (GtkWidget *widget)
 {
@@ -226,6 +266,13 @@ empathy_contact_widget_get_contact (GtkWidget *widget)
   return information->contact;
 }
 
+/**
+ * empathy_contact_widget_set_contact:
+ * @widget: an #EmpathyContactWidget
+ * @contact: a different #EmpathyContact
+ *
+ * Change the #EmpathyContact related with the #EmpathyContactWidget @widget.
+ */
 void
 empathy_contact_widget_set_contact (GtkWidget *widget,
                                     EmpathyContact *contact)
@@ -242,6 +289,15 @@ empathy_contact_widget_set_contact (GtkWidget *widget,
   contact_widget_set_contact (information, contact);
 }
 
+/**
+ * empathy_contact_widget_set_account_filter:
+ * @widget: an #EmpathyContactWidget
+ * @filter: a #EmpathyAccountChooserFilterFunc
+ * @user_data: user data to pass to @filter, or %NULL
+ *
+ * Set a filter on the #EmpathyAccountChooser included in the
+ * #EmpathyContactWidget.
+ */
 void
 empathy_contact_widget_set_account_filter (
     GtkWidget *widget,
@@ -272,10 +328,6 @@ contact_widget_destroy_cb (GtkWidget *widget,
     {
       g_source_remove (information->widget_id_timeout);
     }
-  if (information->factory)
-    {
-      g_object_unref (information->factory);
-    }   
   if (information->manager)
     {
       g_object_unref (information->manager);
@@ -299,7 +351,9 @@ contact_widget_remove_contact (EmpathyContactWidget *information)
           contact_widget_groups_notify_cb, information);
 
       g_object_unref (information->contact);
+      g_object_unref (information->factory);
       information->contact = NULL;
+      information->factory = NULL;
     }
 }
 
@@ -312,7 +366,13 @@ contact_widget_set_contact (EmpathyContactWidget *information,
 
   contact_widget_remove_contact (information);
   if (contact)
+    {
+      TpConnection *connection;
+
+      connection = empathy_contact_get_connection (contact);
       information->contact = g_object_ref (contact);
+      information->factory = empathy_tp_contact_factory_dup_singleton (connection);
+    }
 
   /* Update information for widgets */
   contact_widget_contact_update (information);
@@ -491,10 +551,10 @@ static void
 update_avatar_chooser_account_cb (EmpathyAccountChooser *account_chooser,
                                   EmpathyAvatarChooser *avatar_chooser)
 {
-  McAccount *account;
+  TpConnection *connection;
 
-  account = empathy_account_chooser_get_account (account_chooser);
-  g_object_set (avatar_chooser, "account", account, NULL);
+  connection = empathy_account_chooser_get_connection (account_chooser);
+  g_object_set (avatar_chooser, "connection", connection, NULL);
 }
 
 static void
@@ -505,8 +565,8 @@ contact_widget_contact_setup (EmpathyContactWidget *information)
     {
       information->widget_account = empathy_account_chooser_new ();
 
-      g_signal_connect (information->widget_account, "changed",
-            G_CALLBACK (contact_widget_account_changed_cb),
+      g_signal_connect_swapped (information->widget_account, "changed",
+            G_CALLBACK (contact_widget_change_contact),
             information);
     }
   else
@@ -636,12 +696,12 @@ contact_widget_contact_update (EmpathyContactWidget *information)
       if (account)
         {
           g_signal_handlers_block_by_func (information->widget_account,
-                   contact_widget_account_changed_cb,
+                   contact_widget_change_contact,
                    information);
           empathy_account_chooser_set_account (
               EMPATHY_ACCOUNT_CHOOSER (information->widget_account), account);
           g_signal_handlers_unblock_by_func (information->widget_account,
-              contact_widget_account_changed_cb, information);
+              contact_widget_change_contact, information);
         }
     }
   else
@@ -683,83 +743,71 @@ contact_widget_contact_update (EmpathyContactWidget *information)
 }
 
 static void
-contact_widget_change_contact_cb (EmpathyContact *contact,
-                                  const GError *error,
-                                  gpointer information,
-                                  GObject *weak_object)
+contact_widget_got_contact_cb (EmpathyTpContactFactory *factory,
+                               EmpathyContact *contact,
+                               const GError *error,
+                               gpointer user_data,
+                               GObject *weak_object)
 {
-  if (error)
-    DEBUG ("Error: %s", error->message);
-  else
-    contact_widget_set_contact (information, contact);
-  g_object_unref (contact);
+  EmpathyContactWidget *information = user_data;
+
+  if (error != NULL)
+    {
+      DEBUG ("Error: %s", error->message);
+      return;
+    }
+
+  contact_widget_set_contact (information, contact);
 }
 
 static void
 contact_widget_change_contact (EmpathyContactWidget *information)
 {
-  EmpathyContact *contact;
-  McAccount *account;
+  EmpathyTpContactFactory *factory;
+  TpConnection *connection;
 
-  account = empathy_account_chooser_get_account (
+  connection = empathy_account_chooser_get_connection (
       EMPATHY_ACCOUNT_CHOOSER (information->widget_account));
-  if (!account)
+  if (!connection)
       return;
 
+  factory = empathy_tp_contact_factory_dup_singleton (connection);
   if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID)
     {
       const gchar *id;
 
       id = gtk_entry_get_text (GTK_ENTRY (information->widget_id));
-      if (EMP_STR_EMPTY (id))
-          return;
-
-      contact = empathy_contact_factory_get_from_id (information->factory,
-          account, id);
+      if (!EMP_STR_EMPTY (id))
+        {
+          empathy_tp_contact_factory_get_from_id (factory, id,
+              contact_widget_got_contact_cb, information, NULL,
+              G_OBJECT (information->vbox_contact_widget));
+        }
     }
   else
     {
-      contact = empathy_contact_factory_get_user (information->factory,
-          account);
-    }
-
-  if (contact)
-    {
-      /* Give the contact ref to the callback */
-      empathy_contact_call_when_ready (contact,
-          EMPATHY_CONTACT_READY_HANDLE |
-          EMPATHY_CONTACT_READY_ID,
-          contact_widget_change_contact_cb,
-          information, NULL,
+      empathy_tp_contact_factory_get_from_handle (factory,
+          tp_connection_get_self_handle (connection),
+          contact_widget_got_contact_cb, information, NULL,
           G_OBJECT (information->vbox_contact_widget));
     }
+
+  g_object_unref (factory);
 }
 
 static void
 contact_widget_avatar_changed_cb (EmpathyAvatarChooser *chooser,
                                   EmpathyContactWidget *information)
 {
-  if (information->contact && empathy_contact_is_user (information->contact))
-    {
-      McAccount *account;
-      const gchar *data;
-      gsize size;
-      const gchar *mime_type;
-
-      account = empathy_contact_get_account (information->contact);
-      empathy_avatar_chooser_get_image_data (
-          EMPATHY_AVATAR_CHOOSER (information->widget_avatar),
-          &data, &size, &mime_type);
-      empathy_contact_factory_set_avatar (information->factory, account,
-          data, size, mime_type);
-    }
-}
-
-static void
-contact_widget_account_changed_cb (GtkComboBox *widget,
-                                   EmpathyContactWidget *information)
-{
-  contact_widget_change_contact (information);
+  const gchar *data;
+  gsize size;
+  const gchar *mime_type;
+
+  empathy_avatar_chooser_get_image_data (
+      EMPATHY_AVATAR_CHOOSER (information->widget_avatar),
+      &data, &size, &mime_type);
+  empathy_tp_contact_factory_set_avatar (information->factory,
+      data, size, mime_type);
 }
 
 static gboolean
@@ -781,7 +829,7 @@ contact_widget_entry_alias_focus_event_cb (GtkEditable *editable,
       const gchar *alias;
 
       alias = gtk_entry_get_text (GTK_ENTRY (editable));
-      empathy_contact_factory_set_alias (information->factory,
+      empathy_tp_contact_factory_set_alias (information->factory,
           information->contact, alias);
     }
 
index 4ba75e17f00a0e2049ad998de77196f2953f2238..0da5580a30149af963defeebe1fd115655de815b 100644 (file)
 
 G_BEGIN_DECLS
 
+/**
+ * EmpathyContactWidgetFlags:
+ * @EMPATHY_CONTACT_WIDGET_EDIT_NONE: Don't show any widgets to edit any details
+ *  of the contact. This should be the option for widgets that merely display
+ *  information about a contact.
+ * @EMPATHY_CONTACT_WIDGET_EDIT_ALIAS: Show a #GtkEntry allowing changes to the
+ *  contact's alias.
+ * @EMPATHY_CONTACT_WIDGET_EDIT_AVATAR: Show an #EmpathyAvatarChooser allowing
+ *  changes to the contact's avatar.
+ * @EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT: Show an #EmpathyAccountChooser allowing
+ *  changes to the contact's account.
+ * @EMPATHY_CONTACT_WIDGET_EDIT_ID: Show a #GtkEntry allowing changes to the
+ *  contact's identifier.
+ * @EMPATHY_CONTACT_WIDGET_EDIT_GROUPS: Show a widget to change the groups the
+ *  contact is in.
+ * @EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP: Make widgets more designed for a tooltip.
+ *  For example, make widgets not selectable.
+ *
+ * Flags used when creating an #EmpathyContactWidget to specify which features
+ * should be available.
+ */
 typedef enum
 {
   EMPATHY_CONTACT_WIDGET_EDIT_NONE    = 0,
index 89ee5b2847388970f8c35552b2532d522de832f3..8f7f47bdaab81c1f0da9eeebad788e7c1fa1d819 100644 (file)
@@ -572,6 +572,7 @@ empathy_irc_network_dialog_show (EmpathyIrcNetwork *network,
   gtk_window_set_modal (GTK_WINDOW (dialog->dialog), TRUE);
 
   irc_network_dialog_network_update_buttons (dialog);
+  gtk_widget_show_all (dialog->dialog);
 
   return dialog->dialog;
 }
index 2cec17783c52c962b06e170900f430d566993273..13d9bcbd34536181438354f610f369f949a4c473 100644 (file)
@@ -618,7 +618,7 @@ log_window_chats_populate (EmpathyLogWindow *window)
        GtkTreeIter           iter;
 
        account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
-       account = empathy_account_chooser_get_account (account_chooser);
+       account = empathy_account_chooser_dup_account (account_chooser);
 
        view = GTK_TREE_VIEW (window->treeview_chats);
        model = gtk_tree_view_get_model (view);
index f6eb46a5fccaa674b74986a5d016651706f2c66d..3e6e3f11d3a10ecf8a8a7b727f042db81fd6d7cc 100644 (file)
@@ -31,7 +31,7 @@
 #include <libmissioncontrol/mission-control.h>
 
 #include <libempathy/empathy-call-factory.h>
-#include <libempathy/empathy-contact-factory.h>
+#include <libempathy/empathy-tp-contact-factory.h>
 #include <libempathy/empathy-contact-manager.h>
 #include <libempathy/empathy-dispatcher.h>
 #include <libempathy/empathy-utils.h>
 #include "empathy-new-message-dialog.h"
 #include "empathy-account-chooser.h"
 
+/**
+ * SECTION:empathy-new-message-dialog
+ * @title: EmpathyNewMessageDialog
+ * @short_description: A dialog to show a new message
+ * @include: libempathy-gtk/empathy-new-message-dialog.h
+ *
+ * #EmpathyNewMessageDialog is a dialog which allows a text chat or
+ * call to be started with any contact on any enabled account.
+ */
+
 typedef struct {
        GtkWidget *dialog;
        GtkWidget *table_contact;
@@ -65,48 +75,54 @@ new_message_dialog_account_changed_cb (GtkWidget               *widget,
                                       EmpathyNewMessageDialog *dialog)
 {
        EmpathyAccountChooser *chooser;
-       McAccount            *account;
+       TpConnection          *connection;
        EmpathyTpContactList *contact_list;
-       GList                *members, *l;
+       GList                *members;
        GtkListStore         *store;
        GtkEntryCompletion   *completion;
        GtkTreeIter           iter;
        gchar                *tmpstr;
 
-       chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
-       account = empathy_account_chooser_get_account (chooser);
-       contact_list = empathy_contact_manager_get_list (dialog->contact_manager,
-                                                        account);
-       members = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (contact_list));
+       /* Remove completions */
        completion = gtk_entry_get_completion (GTK_ENTRY (dialog->entry_id));
        store = GTK_LIST_STORE (gtk_entry_completion_get_model (completion));
        gtk_list_store_clear (store);
 
-       for (l = members; l; l = l->next) {
-               EmpathyContact *contact = l->data;
+       /* Get members of the new account */
+       chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
+       connection = empathy_account_chooser_get_connection (chooser);
+       if (!connection) {
+               return;
+       }
+       contact_list = empathy_contact_manager_get_list (dialog->contact_manager,
+                                                        connection);
+       members = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (contact_list));
+
+       /* Add members to the completion */
+       while (members) {
+               EmpathyContact *contact = members->data;
 
-               if (!empathy_contact_is_online (contact)) {
-                       continue;
-               }
+               if (empathy_contact_is_online (contact)) {
+                       DEBUG ("Adding contact ID %s, Name %s",
+                              empathy_contact_get_id (contact),
+                              empathy_contact_get_name (contact));
 
-               DEBUG ("Adding contact ID %s, Name %s",
-                      empathy_contact_get_id (contact),
-                      empathy_contact_get_name (contact));
+                       tmpstr = g_strdup_printf ("%s (%s)",
+                               empathy_contact_get_name (contact),
+                               empathy_contact_get_id (contact));
 
-               tmpstr = g_strdup_printf ("%s (%s)",
-                                         empathy_contact_get_name (contact),
-                                         empathy_contact_get_id (contact));
+                       gtk_list_store_insert_with_values (store, &iter, -1,
+                               COMPLETION_COL_TEXT, tmpstr,
+                               COMPLETION_COL_ID, empathy_contact_get_id (contact),
+                               COMPLETION_COL_NAME, empathy_contact_get_name (contact),
+                               -1);
 
-               gtk_list_store_insert_with_values (store, &iter, -1,
-                       COMPLETION_COL_TEXT, tmpstr,
-                       COMPLETION_COL_ID, empathy_contact_get_id (contact),
-                       COMPLETION_COL_NAME, empathy_contact_get_name (contact),
-                       -1);
+                       g_free (tmpstr);
+               }
 
-               g_free (tmpstr);
+               g_object_unref (contact);
+               members = g_list_delete_link (members, members);
        }
-
-       g_object_unref (account);
 }
 
 static gboolean
@@ -165,42 +181,52 @@ new_message_dialog_match_func (GtkEntryCompletion *completion,
        return FALSE;
 }
 
+static void
+new_message_dialog_call_got_contact_cb (EmpathyTpContactFactory *factory,
+                                       EmpathyContact          *contact,
+                                       const GError            *error,
+                                       gpointer                 user_data,
+                                       GObject                 *weak_object)
+{
+       EmpathyCallFactory *call_factory;
+
+       if (error != NULL) {
+               DEBUG ("Error: %s", error->message);
+               return;
+       }
+
+       call_factory = empathy_call_factory_get();
+       empathy_call_factory_new_call (call_factory, contact);
+}
+
 static void
 new_message_dialog_response_cb (GtkWidget               *widget,
                                gint                    response,
                                EmpathyNewMessageDialog *dialog)
 {
-       McAccount   *account;
+       TpConnection *connection;
        const gchar *id;
 
-       account = empathy_account_chooser_get_account (EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser));
+       connection = empathy_account_chooser_get_connection (
+               EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser));
        id = gtk_entry_get_text (GTK_ENTRY (dialog->entry_id));
-       if (!account || EMP_STR_EMPTY (id)) {
-               if (account) {
-                       g_object_unref (account);
-               }
+       if (!connection || EMP_STR_EMPTY (id)) {
                gtk_widget_destroy (widget);
                return;
        }
 
        if (response == 1) {
-               EmpathyContactFactory *factory;
-               EmpathyContact *contact;
-               EmpathyCallFactory *call_factory;
-
-               factory = empathy_contact_factory_dup_singleton ();
-               contact = empathy_contact_factory_get_from_id (factory, account, id);
+               EmpathyTpContactFactory *factory;
 
-               call_factory = empathy_call_factory_get();
-               empathy_call_factory_new_call (call_factory, contact);
-
-               g_object_unref (contact);
+               factory = empathy_tp_contact_factory_dup_singleton (connection);
+               empathy_tp_contact_factory_get_from_id (factory, id,
+                       new_message_dialog_call_got_contact_cb,
+                       NULL, NULL, NULL);
                g_object_unref (factory);
        } else if (response == 2) {
-               empathy_dispatcher_chat_with_contact_id (account, id, NULL, NULL);
+               empathy_dispatcher_chat_with_contact_id (connection, id, NULL, NULL);
        }
 
-       g_object_unref (account);
        gtk_widget_destroy (widget);
 }
 
@@ -226,6 +252,14 @@ new_message_dialog_destroy_cb (GtkWidget               *widget,
        g_free (dialog);
 }
 
+/**
+ * empathy_new_message_dialog_show:
+ * @parent: parent #GtkWindow of the dialog
+ *
+ * Create a new #EmpathyNewMessageDialog and show it.
+ *
+ * Return value: the new #EmpathyNewMessageDialog
+ */
 GtkWidget *
 empathy_new_message_dialog_show (GtkWindow *parent)
 {
index 8e9574bc533c10798a195510079395458831785e..f4a325b51f7cb9ef343dd6f60732d923dc1cf742 100644 (file)
 #include "empathy-ui-utils.h"
 #include "empathy-images.h"
 #include "empathy-presence-chooser.h"
+#include "empathy-status-preset-dialog.h"
+
+/**
+ * SECTION:empathy-presence-chooser
+ * @title:EmpathyPresenceChooser
+ * @short_description: A widget used to change presence
+ * @include: libempathy-gtk/empathy-presence-chooser.h
+ *
+ * #EmpathyPresenceChooser is a widget which extends #GtkComboBoxEntry
+ * to change presence.
+ */
+
+/**
+ * EmpathyAccountChooser:
+ * @parent: parent object
+ *
+ * Widget which extends #GtkComboBoxEntry to change presence.
+ */
 
 /* Flashing delay for icons (milliseconds). */
 #define FLASH_TIMEOUT 500
@@ -95,16 +113,6 @@ typedef struct {
        guint        flash_timeout_id;
 } EmpathyPresenceChooserPriv;
 
-typedef struct {
-       GtkWidget    *dialog;
-       GtkWidget    *checkbutton_save;
-       GtkWidget    *comboboxentry_message;
-       GtkWidget    *entry_message;
-       GtkWidget    *combobox_status;
-       GtkTreeModel *model_status;
-} CustomMessageDialog;
-
-static CustomMessageDialog *message_dialog = NULL;
 /* States to be listed in the menu.
  * Each state has a boolean telling if it can have custom message */
 static guint states[] = {MC_PRESENCE_AVAILABLE, TRUE,
@@ -130,7 +138,6 @@ static void            presence_chooser_set_state              (McPresence
                                                                const gchar                *status);
 static void            presence_chooser_custom_activate_cb     (GtkWidget                  *item,
                                                                gpointer                    user_data);
-static void            presence_chooser_dialog_show            (GtkWindow                  *parent);
 
 G_DEFINE_TYPE (EmpathyPresenceChooser, empathy_presence_chooser, GTK_TYPE_COMBO_BOX_ENTRY);
 
@@ -180,7 +187,8 @@ presence_chooser_create_model (EmpathyPresenceChooser *self)
                if (states[i+1]) {
 
                        /* Set custom messages if wanted */
-                       list = empathy_status_presets_get (states[i], 5);
+                       list = empathy_status_presets_get (states[i], -1);
+                       list = g_list_sort (list, (GCompareFunc) g_utf8_collate);
                        for (l = list; l; l = l->next) {
                                gtk_list_store_insert_with_values (store,
                                        NULL, -1,
@@ -576,7 +584,7 @@ presence_chooser_changed_cb (GtkComboBox *self, gpointer user_data)
        }
 
        if (type == ENTRY_TYPE_EDIT_CUSTOM) {
-               GtkWidget *window;
+               GtkWidget *window, *dialog;
 
                presence_chooser_reset_status (EMPATHY_PRESENCE_CHOOSER (self));
 
@@ -586,7 +594,9 @@ presence_chooser_changed_cb (GtkComboBox *self, gpointer user_data)
                        window = NULL;
                }
 
-               presence_chooser_dialog_show (GTK_WINDOW (window));
+               dialog = empathy_status_preset_dialog_new (GTK_WINDOW (window));
+               gtk_dialog_run (GTK_DIALOG (dialog));
+               gtk_widget_destroy (dialog);
        }
        else if (type == ENTRY_TYPE_CUSTOM) {
                gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
@@ -789,6 +799,13 @@ presence_chooser_finalize (GObject *object)
        G_OBJECT_CLASS (empathy_presence_chooser_parent_class)->finalize (object);
 }
 
+/**
+ * empathy_presence_chooser_new:
+ *
+ * Creates a new #EmpathyPresenceChooser widget.
+ *
+ * Return value: A new #EmpathyPresenceChooser widget
+ */
 GtkWidget *
 empathy_presence_chooser_new (void)
 {
@@ -946,6 +963,13 @@ presence_chooser_flash_stop (EmpathyPresenceChooser *chooser,
                                           empathy_icon_name_for_presence (state));
 }
 
+/**
+ * empathy_presence_chooser_create_menu:
+ *
+ * Creates a new #GtkMenu allowing users to change their presence from a menu.
+ *
+ * Return value: a new #GtkMenu for changing presence in a menu.
+ */
 GtkWidget *
 empathy_presence_chooser_create_menu (void)
 {
@@ -1058,220 +1082,9 @@ static void
 presence_chooser_custom_activate_cb (GtkWidget *item,
                                     gpointer   user_data)
 {
-       presence_chooser_dialog_show (NULL);
-}
-
-static McPresence
-presence_chooser_dialog_get_selected (CustomMessageDialog *dialog)
-{
-       GtkTreeModel *model;
-       GtkTreeIter   iter;
-       McPresence    presence = LAST_MC_PRESENCE;
+       GtkWidget *dialog;
 
-       model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->combobox_status));
-       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->combobox_status), &iter)) {
-               gtk_tree_model_get (model, &iter,
-                                   COL_PRESENCE, &presence,
-                                   -1);
-       }
-
-       return presence;
+       dialog = empathy_status_preset_dialog_new (NULL);
+       gtk_dialog_run (GTK_DIALOG (dialog));
+       gtk_widget_destroy (dialog);
 }
-
-static void
-presence_chooser_dialog_status_changed_cb (GtkWidget           *widget,
-                                          CustomMessageDialog *dialog)
-{
-       GtkListStore *store;
-       GtkTreeIter   iter;
-       McPresence    presence = LAST_MC_PRESENCE;
-       GList        *messages, *l;
-
-       presence = presence_chooser_dialog_get_selected (dialog);
-
-       store = gtk_list_store_new (1, G_TYPE_STRING);
-       messages = empathy_status_presets_get (presence, -1);
-       for (l = messages; l; l = l->next) {
-               gtk_list_store_append (store, &iter);
-               gtk_list_store_set (store, &iter, 0, l->data, -1);
-       }
-
-       gtk_entry_set_text (GTK_ENTRY (dialog->entry_message),
-                           messages ? messages->data : "");
-
-       g_list_free (messages);
-
-       gtk_combo_box_set_model (GTK_COMBO_BOX (dialog->comboboxentry_message),
-                                GTK_TREE_MODEL (store));
-
-       g_object_unref (store);
-}
-
-static void
-presence_chooser_dialog_message_changed_cb (GtkWidget           *widget,
-                                           CustomMessageDialog *dialog)
-{
-       McPresence   presence;
-       GList       *messages, *l;
-       const gchar *text;
-       gboolean     found = FALSE;
-
-       presence = presence_chooser_dialog_get_selected (dialog);
-       text = gtk_entry_get_text (GTK_ENTRY (dialog->entry_message));
-
-       messages = empathy_status_presets_get (presence, -1);
-       for (l = messages; l; l = l->next) {
-               if (!tp_strdiff (text, l->data)) {
-                       found = TRUE;
-                       break;
-               }
-       }
-       g_list_free (messages);
-
-       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_save),
-                                     found);
-}
-
-static void
-presence_chooser_dialog_save_toggled_cb (GtkWidget           *widget,
-                                        CustomMessageDialog *dialog)
-{
-       gboolean     active;
-       McPresence   state;
-       const gchar *text;
-
-       active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_save));
-       state = presence_chooser_dialog_get_selected (dialog);
-       text = gtk_entry_get_text (GTK_ENTRY (dialog->entry_message));
-
-       if (active) {
-               empathy_status_presets_set_last (state, text);
-       } else {
-               empathy_status_presets_remove (state, text);
-       }
-}
-
-static void
-presence_chooser_dialog_setup (CustomMessageDialog *dialog)
-{
-       GtkListStore    *store;
-       GtkCellRenderer *renderer;
-       GtkTreeIter      iter;
-       guint            i;
-
-       store = gtk_list_store_new (COL_COUNT,
-                                   G_TYPE_STRING,     /* Icon name */
-                                   G_TYPE_STRING,     /* Label     */
-                                   MC_TYPE_PRESENCE); /* Presence   */
-       gtk_combo_box_set_model (GTK_COMBO_BOX (dialog->combobox_status),
-                                GTK_TREE_MODEL (store));
-
-       renderer = gtk_cell_renderer_pixbuf_new ();
-       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (dialog->combobox_status), renderer, FALSE);
-       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (dialog->combobox_status), renderer,
-                                       "icon-name", COL_ICON,
-                                       NULL);
-       g_object_set (renderer, "stock-size", GTK_ICON_SIZE_BUTTON, NULL);
-
-       renderer = gtk_cell_renderer_text_new ();
-       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (dialog->combobox_status), renderer, TRUE);
-       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (dialog->combobox_status), renderer,
-                                       "text", COL_LABEL,
-                                       NULL);
-
-       for (i = 0; i < G_N_ELEMENTS (states); i += 2) {
-               if (!states[i+1]) {
-                       continue;
-               }
-
-               gtk_list_store_append (store, &iter);
-               gtk_list_store_set (store, &iter,
-                                   COL_ICON, empathy_icon_name_for_presence (states[i]),
-                                   COL_LABEL, empathy_presence_get_default_message (states[i]),
-                                   COL_PRESENCE, states[i],
-                                   -1);
-       }
-
-       gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->combobox_status), 0);
-}
-
-static void
-presence_chooser_dialog_response_cb (GtkWidget           *widget,
-                                    gint                 response,
-                                    CustomMessageDialog *dialog)
-{
-       if (response == GTK_RESPONSE_APPLY) {
-               McPresence   state;
-               const gchar *text;
-
-               state = presence_chooser_dialog_get_selected (dialog);
-               text = gtk_entry_get_text (GTK_ENTRY (dialog->entry_message));
-
-               presence_chooser_set_state (state, text);
-       }
-
-       gtk_widget_destroy (widget);
-}
-
-static void
-presence_chooser_dialog_destroy_cb (GtkWidget           *widget,
-                                   CustomMessageDialog *dialog)
-{
-
-       g_free (dialog);
-       message_dialog = NULL;
-}
-
-static void
-presence_chooser_dialog_show (GtkWindow *parent)
-{
-       GtkBuilder *gui;
-       gchar      *filename;
-
-       if (message_dialog) {
-               gtk_window_present (GTK_WINDOW (message_dialog->dialog));
-               return;
-       }
-
-       message_dialog = g_new0 (CustomMessageDialog, 1);
-
-       filename = empathy_file_lookup ("empathy-presence-chooser.ui",
-                                       "libempathy-gtk");
-       gui = empathy_builder_get_file (filename,
-                                      "custom_message_dialog", &message_dialog->dialog,
-                                      "checkbutton_save", &message_dialog->checkbutton_save,
-                                      "comboboxentry_message", &message_dialog->comboboxentry_message,
-                                      "combobox_status", &message_dialog->combobox_status,
-                                      NULL);
-       g_free (filename);
-
-       empathy_builder_connect (gui, message_dialog,
-                              "custom_message_dialog", "destroy", presence_chooser_dialog_destroy_cb,
-                              "custom_message_dialog", "response", presence_chooser_dialog_response_cb,
-                              "combobox_status", "changed", presence_chooser_dialog_status_changed_cb,
-                              "checkbutton_save", "toggled", presence_chooser_dialog_save_toggled_cb,
-                              NULL);
-
-       g_object_unref (gui);
-
-       /* Setup the message combobox */
-       message_dialog->entry_message = GTK_BIN (message_dialog->comboboxentry_message)->child;
-       gtk_entry_set_activates_default (GTK_ENTRY (message_dialog->entry_message), TRUE);
-       gtk_entry_set_width_chars (GTK_ENTRY (message_dialog->entry_message), 25);
-       g_signal_connect (message_dialog->entry_message, "changed",
-                         G_CALLBACK (presence_chooser_dialog_message_changed_cb),
-                         message_dialog);
-
-       presence_chooser_dialog_setup (message_dialog);
-
-       gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (message_dialog->comboboxentry_message), 0);
-
-       if (parent) {
-               gtk_window_set_transient_for (
-                       GTK_WINDOW (message_dialog->dialog),
-                       parent);
-       }
-
-       gtk_widget_show_all (message_dialog->dialog);
-}
-
index 138e1dc7feec69f0be8ee7efe102a2b689e514b9..dab95f5537a043eace835c24bb55d61574fe5e1e 100644 (file)
@@ -43,6 +43,8 @@ typedef struct _EmpathyPresenceChooserClass EmpathyPresenceChooserClass;
 
 struct _EmpathyPresenceChooser {
        GtkComboBoxEntry parent;
+
+       /*<private>*/
        gpointer priv;
 };
 
diff --git a/libempathy-gtk/empathy-presence-chooser.ui b/libempathy-gtk/empathy-presence-chooser.ui
deleted file mode 100644 (file)
index 6e0a155..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-<?xml version="1.0"?>
-<interface>
-  <requires lib="gtk+" version="2.16"/>
-  <!-- interface-naming-policy toplevel-contextual -->
-  <object class="GtkDialog" id="custom_message_dialog">
-    <property name="visible">True</property>
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Custom message</property>
-    <property name="resizable">False</property>
-    <property name="type_hint">dialog</property>
-    <property name="has_separator">False</property>
-    <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog-vbox6">
-        <property name="visible">True</property>
-        <child>
-          <object class="GtkTable" id="table1">
-            <property name="visible">True</property>
-            <property name="border_width">5</property>
-            <property name="n_rows">3</property>
-            <property name="n_columns">2</property>
-            <property name="column_spacing">6</property>
-            <property name="row_spacing">6</property>
-            <child>
-              <object class="GtkComboBox" id="combobox_status">
-                <property name="visible">True</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="x_options">GTK_FILL</property>
-                <property name="y_options">GTK_FILL</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkComboBoxEntry" id="comboboxentry_message">
-                <property name="visible">True</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="x_options">GTK_FILL</property>
-                <property name="y_options">GTK_FILL</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkCheckButton" id="checkbutton_save">
-                <property name="label" translatable="yes">Save message</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="use_underline">True</property>
-                <property name="draw_indicator">True</property>
-              </object>
-              <packing>
-                <property name="right_attach">2</property>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="label472">
-                <property name="visible">True</property>
-                <property name="xalign">0</property>
-                <property name="label" translatable="yes">Message:</property>
-              </object>
-              <packing>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="x_options">GTK_FILL</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="label471">
-                <property name="visible">True</property>
-                <property name="xalign">0</property>
-                <property name="label" translatable="yes">Status:</property>
-              </object>
-              <packing>
-                <property name="x_options">GTK_FILL</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog-action_area6">
-            <property name="visible">True</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="closebutton1">
-                <property name="label">gtk-cancel</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="receives_default">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="button1">
-                <property name="label">gtk-apply</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="receives_default">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <action-widgets>
-      <action-widget response="-6">closebutton1</action-widget>
-      <action-widget response="-10">button1</action-widget>
-    </action-widgets>
-  </object>
-</interface>
index fd68dd8b01bd50663d819cf7ef1e272de3d46ff3..10eb3791ab552a6e08169c0332511822c2f856f9 100644 (file)
 #include "empathy-profile-chooser.h"
 #include "empathy-ui-utils.h"
 
+/**
+ * SECTION:empathy-profile-chooser
+ * @title: EmpathyProfileChooser
+ * @short_description: A widget used to choose from a list of profiles
+ * @include: libempathy-gtk/empathy-account-chooser.h
+ *
+ * #EmpathyProfileChooser is a widget which provides a chooser of available
+ * profiles.
+ */
+
 enum {
        COL_ICON,
        COL_LABEL,
@@ -37,8 +47,17 @@ enum {
        COL_COUNT
 };
 
+/**
+ * empathy_profile_chooser_dup_selected:
+ * @widget: an #EmpathyProfileChooser
+ *
+ * Returns a new reference to the selected #McProfile in @widget. The returned
+ * #McProfile should be unrefed with g_object_unref() when finished with.
+ *
+ * Return value: a new reference to the selected #McProfile
+ */
 McProfile*
-empathy_profile_chooser_get_selected (GtkWidget *widget)
+empathy_profile_chooser_dup_selected (GtkWidget *widget)
 {
        GtkTreeModel *model;
        GtkTreeIter   iter;
@@ -54,6 +73,14 @@ empathy_profile_chooser_get_selected (GtkWidget *widget)
        return profile;
 }
 
+/**
+ * empathy_profile_chooser_n_profiles:
+ * @widget: an #EmpathyProfileChooser
+ *
+ * Returns the number of profiles in @widget.
+ *
+ * Return value: the number of profiles in @widget
+ */
 gint
 empathy_profile_chooser_n_profiles (GtkWidget *widget)
 {
@@ -115,6 +142,13 @@ profile_chooser_sort_func (GtkTreeModel *model,
        return cmp;
 }
 
+/**
+ * empathy_profile_chooser_new:
+ *
+ * Creates a new #EmpathyProfileChooser widget.
+ *
+ * Return value: a new #EmpathyProfileChooser widget
+ */
 GtkWidget *
 empathy_profile_chooser_new (void)
 {
index 8cdc33d678e0e301f166f455b3be0e1960e4ee0a..74c761cc4e6026245e956f6e908b9b6ad923e405 100644 (file)
@@ -27,7 +27,7 @@
 G_BEGIN_DECLS
 
 GtkWidget * empathy_profile_chooser_new          (void);
-McProfile * empathy_profile_chooser_get_selected (GtkWidget *widget);
+McProfile * empathy_profile_chooser_dup_selected (GtkWidget *widget);
 gint        empathy_profile_chooser_n_profiles   (GtkWidget *widget);
 
 G_END_DECLS
diff --git a/libempathy-gtk/empathy-spell-dialog.c b/libempathy-gtk/empathy-spell-dialog.c
deleted file mode 100644 (file)
index 9ce80ee..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2004-2007 Imendio AB
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#include <glib/gi18n-lib.h>
-#include <gtk/gtk.h>
-
-#include <libempathy/empathy-utils.h>
-
-#include "empathy-chat.h"
-#include "empathy-spell.h"
-#include "empathy-spell-dialog.h"
-#include "empathy-ui-utils.h"
-
-typedef struct {
-       GtkWidget   *window;
-       GtkWidget   *button_replace;
-       GtkWidget   *label_word;
-       GtkWidget   *treeview_words;
-
-       EmpathyChat  *chat;
-
-       gchar       *word;
-       GtkTextIter  start;
-       GtkTextIter  end;
-} EmpathySpellDialog;
-
-enum {
-       COL_SPELL_WORD,
-       COL_SPELL_COUNT
-};
-
-static void spell_dialog_model_populate_columns     (EmpathySpellDialog *dialog);
-static void spell_dialog_model_populate_suggestions (EmpathySpellDialog *dialog);
-static void spell_dialog_model_row_activated_cb     (GtkTreeView       *tree_view,
-                                                    GtkTreePath       *path,
-                                                    GtkTreeViewColumn *column,
-                                                    EmpathySpellDialog *dialog);
-static void spell_dialog_model_selection_changed_cb (GtkTreeSelection  *treeselection,
-                                                    EmpathySpellDialog *dialog);
-static void spell_dialog_model_setup                (EmpathySpellDialog *dialog);
-static void spell_dialog_response_cb                (GtkWidget         *widget,
-                                                    gint               response,
-                                                    EmpathySpellDialog *dialog);
-static void spell_dialog_destroy_cb                 (GtkWidget         *widget,
-                                                    EmpathySpellDialog *dialog);
-
-static void
-spell_dialog_model_populate_columns (EmpathySpellDialog *dialog)
-{
-       GtkTreeModel      *model;
-       GtkTreeViewColumn *column;
-       GtkCellRenderer   *renderer;
-       guint              col_offset;
-
-       model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_words));
-
-       renderer = gtk_cell_renderer_text_new ();
-       col_offset = gtk_tree_view_insert_column_with_attributes (
-               GTK_TREE_VIEW (dialog->treeview_words),
-               -1, _("Word"),
-               renderer,
-               "text", COL_SPELL_WORD,
-               NULL);
-
-       g_object_set_data (G_OBJECT (renderer),
-                          "column", GINT_TO_POINTER (COL_SPELL_WORD));
-
-       column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->treeview_words), col_offset - 1);
-       gtk_tree_view_column_set_sort_column_id (column, COL_SPELL_WORD);
-       gtk_tree_view_column_set_resizable (column, FALSE);
-       gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
-}
-
-static void
-spell_dialog_model_populate_suggestions (EmpathySpellDialog *dialog)
-{
-       GtkTreeModel *model;
-       GtkListStore *store;
-       GList        *suggestions, *l;
-
-       model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_words));
-       store = GTK_LIST_STORE (model);
-
-       suggestions = empathy_spell_get_suggestions (dialog->word);
-       for (l = suggestions; l; l=l->next) {
-               GtkTreeIter  iter;
-               gchar       *word;
-
-               word = l->data;
-
-               gtk_list_store_append (store, &iter);
-               gtk_list_store_set (store, &iter,
-                                   COL_SPELL_WORD, word,
-                                   -1);
-       }
-
-       empathy_spell_free_suggestions (suggestions);
-}
-
-static void
-spell_dialog_model_row_activated_cb (GtkTreeView       *tree_view,
-                              GtkTreePath       *path,
-                              GtkTreeViewColumn *column,
-                              EmpathySpellDialog *dialog)
-{
-       spell_dialog_response_cb (dialog->window, GTK_RESPONSE_OK, dialog);
-}
-
-static void
-spell_dialog_model_selection_changed_cb (GtkTreeSelection  *treeselection,
-                                  EmpathySpellDialog *dialog)
-{
-       gint count;
-
-       count = gtk_tree_selection_count_selected_rows (treeselection);
-       gtk_widget_set_sensitive (dialog->button_replace, (count == 1));
-}
-
-static void
-spell_dialog_model_setup (EmpathySpellDialog *dialog)
-{
-       GtkTreeView      *view;
-       GtkListStore     *store;
-       GtkTreeSelection *selection;
-
-       view = GTK_TREE_VIEW (dialog->treeview_words);
-
-       g_signal_connect (view, "row-activated",
-                         G_CALLBACK (spell_dialog_model_row_activated_cb),
-                         dialog);
-
-       store = gtk_list_store_new (COL_SPELL_COUNT,
-                                   G_TYPE_STRING);   /* word */
-
-       gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
-
-       selection = gtk_tree_view_get_selection (view);
-       gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
-
-       g_signal_connect (selection, "changed",
-                         G_CALLBACK (spell_dialog_model_selection_changed_cb),
-                         dialog);
-
-       spell_dialog_model_populate_columns (dialog);
-       spell_dialog_model_populate_suggestions (dialog);
-
-       g_object_unref (store);
-}
-
-static void
-spell_dialog_destroy_cb (GtkWidget         *widget,
-                        EmpathySpellDialog *dialog)
-{
-       g_object_unref (dialog->chat);
-       g_free (dialog->word);
-
-       g_free (dialog);
-}
-
-static void
-spell_dialog_response_cb (GtkWidget         *widget,
-                         gint               response,
-                         EmpathySpellDialog *dialog)
-{
-       if (response == GTK_RESPONSE_OK) {
-               GtkTreeView      *view;
-               GtkTreeModel     *model;
-               GtkTreeSelection *selection;
-               GtkTreeIter       iter;
-
-               gchar            *new_word;
-
-               view = GTK_TREE_VIEW (dialog->treeview_words);
-               selection = gtk_tree_view_get_selection (view);
-
-               if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
-                       return;
-               }
-
-               gtk_tree_model_get (model, &iter, COL_SPELL_WORD, &new_word, -1);
-
-               empathy_chat_correct_word (dialog->chat,
-                                         &dialog->start,
-                                         &dialog->end,
-                                         new_word);
-
-               g_free (new_word);
-       }
-
-       gtk_widget_destroy (dialog->window);
-}
-
-void
-empathy_spell_dialog_show (EmpathyChat  *chat,
-                         GtkTextIter *start,
-                         GtkTextIter *end,
-                         const gchar *word)
-{
-       EmpathySpellDialog *dialog;
-       GtkBuilder         *gui;
-       gchar              *str;
-       gchar              *filename;
-
-       g_return_if_fail (chat != NULL);
-       g_return_if_fail (word != NULL);
-
-       dialog = g_new0 (EmpathySpellDialog, 1);
-
-       dialog->chat = g_object_ref (chat);
-
-       dialog->word = g_strdup (word);
-
-       dialog->start = *start;
-       dialog->end = *end;
-
-       filename = empathy_file_lookup ("empathy-spell-dialog.ui",
-                                       "libempathy-gtk");
-       gui = empathy_builder_get_file (filename,
-                                    "spell_dialog", &dialog->window,
-                                    "button_replace", &dialog->button_replace,
-                                    "label_word", &dialog->label_word,
-                                    "treeview_words", &dialog->treeview_words,
-                                    NULL);
-       g_free (filename);
-
-       empathy_builder_connect (gui, dialog,
-                             "spell_dialog", "response", spell_dialog_response_cb,
-                             "spell_dialog", "destroy", spell_dialog_destroy_cb,
-                             NULL);
-
-       g_object_unref (gui);
-
-       str = g_markup_printf_escaped ("%s:\n<b>%s</b>",
-                              _("Suggestions for the word"),
-                              word);
-
-       gtk_label_set_markup (GTK_LABEL (dialog->label_word), str);
-       g_free (str);
-
-       spell_dialog_model_setup (dialog);
-
-       gtk_widget_show (dialog->window);
-}
diff --git a/libempathy-gtk/empathy-spell-dialog.h b/libempathy-gtk/empathy-spell-dialog.h
deleted file mode 100644 (file)
index ce02188..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2004-2007 Imendio AB
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors: Martyn Russell <martyn@imendio.com>
- *          Richard Hult <richard@imendio.com>
- */
-
-#ifndef __EMPATHY_SPELL_DIALOG_H__
-#define __EMPATHY_SPELL_DIALOG_H__
-
-#include <gtk/gtktextiter.h>
-#include "empathy-chat.h"
-
-G_BEGIN_DECLS
-
-void empathy_spell_dialog_show (EmpathyChat  *chat,
-                              GtkTextIter *start,
-                              GtkTextIter *end,
-                              const gchar *word);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_SPELL_DIALOG_H__ */
diff --git a/libempathy-gtk/empathy-spell-dialog.ui b/libempathy-gtk/empathy-spell-dialog.ui
deleted file mode 100644 (file)
index 382346c..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-<?xml version="1.0"?>
-<!--*- mode: xml -*-->
-<interface>
-  <object class="GtkDialog" id="spell_dialog">
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Spell Checker</property>
-    <property name="modal">True</property>
-    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
-    <property name="default_width">275</property>
-    <property name="default_height">225</property>
-    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
-    <property name="has_separator">False</property>
-    <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog-vbox7">
-        <property name="visible">True</property>
-        <property name="spacing">2</property>
-        <child>
-          <object class="GtkVBox" id="vbox128">
-            <property name="visible">True</property>
-            <property name="border_width">5</property>
-            <property name="spacing">6</property>
-            <child>
-              <object class="GtkLabel" id="label_word">
-                <property name="visible">True</property>
-                <property name="xalign">0</property>
-                <property name="label" translatable="yes">Suggestions for the word:</property>
-                <property name="use_markup">True</property>
-                <property name="wrap">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow9">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                <property name="shadow_type">GTK_SHADOW_IN</property>
-                <child>
-                  <object class="GtkTreeView" id="treeview_words">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="headers_visible">False</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog-action_area7">
-            <property name="visible">True</property>
-            <property name="layout_style">GTK_BUTTONBOX_END</property>
-            <child>
-              <object class="GtkButton" id="button_cancel">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="label">gtk-cancel</property>
-                <property name="use_stock">True</property>
-              </object>
-            </child>
-            <child>
-              <object class="GtkButton" id="button_replace">
-                <property name="visible">True</property>
-                <property name="sensitive">False</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <child>
-                  <object class="GtkAlignment" id="alignment6">
-                    <property name="visible">True</property>
-                    <property name="xscale">0</property>
-                    <property name="yscale">0</property>
-                    <child>
-                      <object class="GtkHBox" id="hbox135">
-                        <property name="visible">True</property>
-                        <property name="spacing">2</property>
-                        <child>
-                          <object class="GtkImage" id="image245">
-                            <property name="visible">True</property>
-                            <property name="stock">gtk-convert</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="label594">
-                            <property name="visible">True</property>
-                            <property name="label">_Replace</property>
-                            <property name="use_underline">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">GTK_PACK_END</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <action-widgets>
-      <action-widget response="-6">button_cancel</action-widget>
-      <action-widget response="-5">button_replace</action-widget>
-    </action-widgets>
-  </object>
-</interface>
diff --git a/libempathy-gtk/empathy-status-preset-dialog.c b/libempathy-gtk/empathy-status-preset-dialog.c
new file mode 100644 (file)
index 0000000..734ac35
--- /dev/null
@@ -0,0 +1,549 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * empathy-status-preset-dialog.c
+ *
+ * EmpathyStatusPresetDialog - a dialog for adding and removing preset status
+ * messages.
+ *
+ * Copyright (C) 2009 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Davyd Madeley <davyd.madeley@collabora.co.uk>
+ */
+/**
+ * SECTION:empathy-status-preset-dialog
+ * @title: EmpathyStatusPresetDialog
+ * @short_description: a dialog for editing the saved status messages
+ * @include: libempathy-gtk/empathy-status-preset-dialog.h
+ *
+ * #EmpathyStatusPresetDialog is a dialog allowing the user to add/remove/edit
+ * their saved status messages.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#include <libmissioncontrol/mc-enum-types.h>
+
+#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-status-presets.h>
+
+#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
+#include <libempathy/empathy-debug.h>
+
+#include "empathy-ui-utils.h"
+#include "empathy-status-preset-dialog.h"
+
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyStatusPresetDialog)
+
+G_DEFINE_TYPE (EmpathyStatusPresetDialog, empathy_status_preset_dialog, GTK_TYPE_DIALOG);
+
+static McPresence states[] = {
+       MC_PRESENCE_AVAILABLE,
+       MC_PRESENCE_DO_NOT_DISTURB,
+       MC_PRESENCE_AWAY
+};
+
+typedef struct _EmpathyStatusPresetDialogPriv EmpathyStatusPresetDialogPriv;
+struct _EmpathyStatusPresetDialogPriv
+{
+       /* block status_preset_dialog_add_combo_changed() when > 0 */
+       int block_add_combo_changed;
+
+       GtkWidget *presets_treeview;
+       GtkWidget *add_combobox;
+       GtkWidget *add_button;
+
+       GtkTreeIter selected_iter;
+       gboolean add_combo_changed;
+       char *saved_status;
+};
+
+enum
+{
+       PRESETS_STORE_STATE,
+       PRESETS_STORE_ICON_NAME,
+       PRESETS_STORE_STATUS,
+       PRESETS_STORE_N_COLS
+};
+
+enum
+{
+       ADD_COMBO_STATE,
+       ADD_COMBO_ICON_NAME,
+       ADD_COMBO_STATUS,
+       ADD_COMBO_DEFAULT_TEXT,
+       ADD_COMBO_N_COLS
+};
+
+static void
+empathy_status_preset_dialog_finalize (GObject *self)
+{
+       EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
+
+       g_free (priv->saved_status);
+
+       G_OBJECT_CLASS (empathy_status_preset_dialog_parent_class)->finalize (self);
+}
+
+static void
+empathy_status_preset_dialog_class_init (EmpathyStatusPresetDialogClass *class)
+{
+       GObjectClass *gobject_class;
+
+       gobject_class = G_OBJECT_CLASS (class);
+       gobject_class->finalize = empathy_status_preset_dialog_finalize;
+
+       g_type_class_add_private (gobject_class,
+                       sizeof (EmpathyStatusPresetDialogPriv));
+}
+
+static void
+status_preset_dialog_presets_update (EmpathyStatusPresetDialog *self)
+{
+       EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
+       GtkListStore *store;
+       int i;
+
+       store = GTK_LIST_STORE (gtk_tree_view_get_model (
+                               GTK_TREE_VIEW (priv->presets_treeview)));
+
+       gtk_list_store_clear (store);
+
+       for (i = 0; i < G_N_ELEMENTS (states); i++) {
+               GList *presets, *l;
+               const char *icon_name;
+
+               icon_name = empathy_icon_name_for_presence (states[i]);
+               presets = empathy_status_presets_get (states[i], -1);
+               presets = g_list_sort (presets, (GCompareFunc) g_utf8_collate);
+
+               for (l = presets; l; l = l->next) {
+                       char *preset = (char *) l->data;
+
+                       gtk_list_store_insert_with_values (store,
+                                       NULL, -1,
+                                       PRESETS_STORE_STATE, states[i],
+                                       PRESETS_STORE_ICON_NAME, icon_name,
+                                       PRESETS_STORE_STATUS, preset,
+                                       -1);
+               }
+
+               g_list_free (presets);
+       }
+}
+
+static void
+status_preset_add_combo_reset (EmpathyStatusPresetDialog *self)
+{
+       EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
+
+       gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->add_combobox),
+                       &priv->selected_iter);
+}
+
+static void
+status_preset_dialog_setup_add_combobox (EmpathyStatusPresetDialog *self)
+{
+       EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
+       GtkWidget *combobox = priv->add_combobox;
+       GtkListStore *store;
+       GtkCellRenderer *renderer;
+       int i;
+
+       store = gtk_list_store_new (ADD_COMBO_N_COLS,
+                       MC_TYPE_PRESENCE,       /* ADD_COMBO_STATE */
+                       G_TYPE_STRING,          /* ADD_COMBO_ICON_NAME */
+                       G_TYPE_STRING,          /* ADD_COMBO_STATUS */
+                       G_TYPE_STRING);         /* ADD_COMBO_DEFAULT_TEXT */
+
+       gtk_combo_box_set_model (GTK_COMBO_BOX (combobox),
+                                GTK_TREE_MODEL (store));
+       g_object_unref (store);
+
+       gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (combobox),
+                       ADD_COMBO_DEFAULT_TEXT);
+
+       for (i = 0; i < G_N_ELEMENTS (states); i++) {
+               gtk_list_store_insert_with_values (store, NULL, -1,
+                               ADD_COMBO_STATE, states[i],
+                               ADD_COMBO_ICON_NAME, empathy_icon_name_for_presence (states[i]),
+                               ADD_COMBO_STATUS, empathy_presence_get_default_message (states[i]),
+                               ADD_COMBO_DEFAULT_TEXT, "",
+                               -1);
+       }
+
+       gtk_cell_layout_clear (GTK_CELL_LAYOUT (combobox));
+
+       renderer = gtk_cell_renderer_pixbuf_new ();
+       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, FALSE);
+       gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox), renderer,
+                       "icon-name", ADD_COMBO_ICON_NAME);
+
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, TRUE);
+       gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox), renderer,
+                       "text", ADD_COMBO_STATUS);
+       g_object_set (renderer,
+                       "style", PANGO_STYLE_ITALIC,
+                       "foreground", "Gray", /* FIXME - theme */
+                       NULL);
+
+       gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), 0);
+}
+
+static void
+status_preset_dialog_status_edited (GtkCellRendererText *renderer,
+                                   char *path_str,
+                                   char *new_status,
+                                   EmpathyStatusPresetDialog *self)
+{
+       EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
+       GtkTreeModel *model;
+       GtkTreePath *path;
+       GtkTreeIter iter;
+       McPresence state;
+       char *old_status;
+       gboolean valid;
+
+       if (strlen (new_status) == 0) {
+               /* status is empty, ignore */
+               return;
+       }
+
+       model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->presets_treeview));
+       path = gtk_tree_path_new_from_string (path_str);
+       valid = gtk_tree_model_get_iter (model, &iter, path);
+       gtk_tree_path_free (path);
+
+       if (!valid) return;
+
+       gtk_tree_model_get (model, &iter,
+                       PRESETS_STORE_STATE, &state,
+                       PRESETS_STORE_STATUS, &old_status,
+                       -1);
+
+       if (!strcmp (old_status, new_status)) {
+               /* statuses are the same */
+               g_free (old_status);
+               return;
+       }
+
+       DEBUG ("EDITED STATUS (%s) -> (%s)\n", old_status, new_status);
+
+       empathy_status_presets_remove (state, old_status);
+       empathy_status_presets_set_last (state, new_status);
+
+       g_free (old_status);
+
+       status_preset_dialog_presets_update (self);
+}
+
+static void
+status_preset_dialog_setup_presets_treeview (EmpathyStatusPresetDialog *self)
+{
+       EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
+       GtkWidget *treeview = priv->presets_treeview;
+       GtkListStore *store;
+       GtkTreeViewColumn *column;
+       GtkCellRenderer *renderer;
+
+       store = gtk_list_store_new (PRESETS_STORE_N_COLS,
+                       MC_TYPE_PRESENCE,       /* PRESETS_STORE_STATE */
+                       G_TYPE_STRING,          /* PRESETS_STORE_ICON_NAME */
+                       G_TYPE_STRING);         /* PRESETS_STORE_STATUS */
+
+       gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                GTK_TREE_MODEL (store));
+       g_object_unref (store);
+
+       status_preset_dialog_presets_update (self);
+
+       column = gtk_tree_view_column_new ();
+       gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+       renderer = gtk_cell_renderer_pixbuf_new ();
+       gtk_tree_view_column_pack_start (column, renderer, FALSE);
+       gtk_tree_view_column_add_attribute (column, renderer,
+                       "icon-name", PRESETS_STORE_ICON_NAME);
+
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_column_pack_start (column, renderer, TRUE);
+       gtk_tree_view_column_add_attribute (column, renderer,
+                       "text", PRESETS_STORE_STATUS);
+       g_object_set (renderer,
+                       "editable", TRUE,
+                       NULL);
+       g_signal_connect (renderer, "edited",
+                       G_CALLBACK (status_preset_dialog_status_edited), self);
+}
+
+static void
+status_preset_dialog_preset_selection_changed (GtkTreeSelection *selection,
+                                              GtkWidget *remove_button)
+{
+       /* update the sensitivity of the Remove button */
+       gtk_widget_set_sensitive (remove_button,
+                       gtk_tree_selection_get_selected (selection, NULL, NULL));
+}
+
+static void
+status_preset_dialog_preset_remove (GtkButton *button,
+                                   EmpathyStatusPresetDialog *self)
+{
+       EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
+       GtkTreeSelection *selection;
+       GtkTreeModel *model;
+       GtkTreeIter iter;
+       McPresence state;
+       char *status;
+
+       selection = gtk_tree_view_get_selection (
+                       GTK_TREE_VIEW (priv->presets_treeview));
+
+       g_return_if_fail (gtk_tree_selection_get_selected (selection,
+                               &model, &iter));
+
+       gtk_tree_model_get (model, &iter,
+                       PRESETS_STORE_STATE, &state,
+                       PRESETS_STORE_STATUS, &status,
+                       -1);
+
+       DEBUG ("REMOVE PRESET (%i, %s)\n", state, status);
+       empathy_status_presets_remove (state, status);
+
+       g_free (status);
+
+       status_preset_dialog_presets_update (self);
+}
+
+static void
+status_preset_dialog_set_add_combo_changed (EmpathyStatusPresetDialog *self,
+                                           gboolean state,
+                                           gboolean reset_text)
+{
+       EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
+       GtkWidget *entry;
+
+       entry = gtk_bin_get_child (GTK_BIN (priv->add_combobox));
+
+       priv->add_combo_changed = state;
+       gtk_widget_set_sensitive (priv->add_button, state);
+
+       if (state) {
+               gtk_widget_modify_text (entry, GTK_STATE_NORMAL, NULL);
+       } else {
+               GdkColor colour;
+
+               gdk_color_parse ("Gray", &colour); /* FIXME - theme */
+               gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &colour);
+
+               if (reset_text) {
+                       priv->block_add_combo_changed++;
+                       gtk_entry_set_text (GTK_ENTRY (entry),
+                                       _("Enter Custom Message"));
+                       priv->block_add_combo_changed--;
+               }
+       }
+}
+
+static void
+status_preset_dialog_add_combo_changed (GtkComboBox *combo,
+                                       EmpathyStatusPresetDialog *self)
+{
+       EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
+       GtkWidget *entry;
+       GtkTreeModel *model;
+       GtkTreeIter iter;
+
+       if (priv->block_add_combo_changed) return;
+
+       model = gtk_combo_box_get_model (combo);
+       entry = gtk_bin_get_child (GTK_BIN (combo));
+
+       if (gtk_combo_box_get_active_iter (combo, &iter)) {
+               char *icon_name;
+
+               priv->selected_iter = iter;
+               gtk_tree_model_get (model, &iter,
+                               PRESETS_STORE_ICON_NAME, &icon_name,
+                               -1);
+
+               gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
+                               GTK_ENTRY_ICON_PRIMARY,
+                               icon_name);
+
+               g_free (icon_name);
+
+               status_preset_dialog_set_add_combo_changed (self, FALSE, TRUE);
+               if (priv->saved_status && strlen (priv->saved_status) > 0) {
+                       gtk_entry_set_text (GTK_ENTRY (entry),
+                                       priv->saved_status);
+               }
+       } else {
+               g_free (priv->saved_status);
+               priv->saved_status = g_strdup (
+                               gtk_entry_get_text (GTK_ENTRY (entry)));
+
+               status_preset_dialog_set_add_combo_changed (self,
+                               strlen (priv->saved_status) > 0, FALSE);
+       }
+}
+
+static void
+status_preset_dialog_add_preset (GtkWidget *widget,
+                                EmpathyStatusPresetDialog *self)
+{
+       EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
+       GtkTreeModel *model;
+       GtkWidget *entry;
+       McPresence state;
+       const char *status;
+
+       g_return_if_fail (priv->add_combo_changed);
+
+       model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->add_combobox));
+       entry = gtk_bin_get_child (GTK_BIN (priv->add_combobox));
+
+       status = gtk_entry_get_text (GTK_ENTRY (entry));
+       gtk_tree_model_get (model, &priv->selected_iter,
+                       PRESETS_STORE_STATE, &state,
+                       -1);
+
+       DEBUG ("ADD PRESET (%i, %s)\n", state, status);
+       empathy_status_presets_set_last (state, status);
+
+       status_preset_dialog_presets_update (self);
+       status_preset_add_combo_reset (self);
+}
+
+static gboolean
+status_preset_dialog_add_combo_press_event (GtkWidget *widget,
+                                           GdkEventButton *event,
+                                           EmpathyStatusPresetDialog *self)
+{
+       if (!GTK_WIDGET_HAS_FOCUS (widget)) {
+               /* if the widget isn't focused, focus it and select the text */
+               gtk_widget_grab_focus (widget);
+               gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static gboolean
+status_preset_dialog_add_combo_focus_out (GtkWidget *widget,
+                                         GdkEventFocus *event,
+                                         EmpathyStatusPresetDialog *self)
+{
+       EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
+       const char *status;
+
+       gtk_editable_set_position (GTK_EDITABLE (widget), 0);
+
+       status = gtk_entry_get_text (GTK_ENTRY (widget));
+       status_preset_dialog_set_add_combo_changed (self,
+                       priv->add_combo_changed && strlen (status) > 0,
+                       TRUE);
+
+       return FALSE;
+}
+
+static void
+empathy_status_preset_dialog_init (EmpathyStatusPresetDialog *self)
+{
+       EmpathyStatusPresetDialogPriv *priv = self->priv =
+               G_TYPE_INSTANCE_GET_PRIVATE (self,
+                       EMPATHY_TYPE_STATUS_PRESET_DIALOG,
+                       EmpathyStatusPresetDialogPriv);
+       GtkBuilder *gui;
+       GtkWidget *toplevel_vbox, *remove_button, *entry;
+       char *filename;
+
+       gtk_window_set_title (GTK_WINDOW (self),
+                       _("Edit Custom Messages"));
+       gtk_dialog_set_has_separator (GTK_DIALOG (self), FALSE);
+       gtk_dialog_add_button (GTK_DIALOG (self),
+                       GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
+
+       filename = empathy_file_lookup ("empathy-status-preset-dialog.ui",
+                       "libempathy-gtk");
+       gui = empathy_builder_get_file (filename,
+                       "toplevel-vbox", &toplevel_vbox,
+                       "presets-treeview", &priv->presets_treeview,
+                       "remove-button", &remove_button,
+                       "add-combobox", &priv->add_combobox,
+                       "add-button", &priv->add_button,
+                       NULL);
+       g_free (filename);
+
+       g_signal_connect (gtk_tree_view_get_selection (
+                               GTK_TREE_VIEW (priv->presets_treeview)),
+                       "changed",
+                       G_CALLBACK (status_preset_dialog_preset_selection_changed),
+                       remove_button);
+
+       entry = gtk_bin_get_child (GTK_BIN (priv->add_combobox));
+       g_signal_connect (entry, "activate",
+                       G_CALLBACK (status_preset_dialog_add_preset), self);
+       g_signal_connect (entry, "button-press-event",
+                       G_CALLBACK (status_preset_dialog_add_combo_press_event),
+                       self);
+       g_signal_connect (entry, "focus-out-event",
+                       G_CALLBACK (status_preset_dialog_add_combo_focus_out),
+                       self);
+
+       empathy_builder_connect (gui, self,
+                       "remove-button", "clicked", status_preset_dialog_preset_remove,
+                       "add-combobox", "changed", status_preset_dialog_add_combo_changed,
+                       "add-button", "clicked", status_preset_dialog_add_preset,
+                       NULL);
+
+       status_preset_dialog_setup_presets_treeview (self);
+       status_preset_dialog_setup_add_combobox (self);
+
+       gtk_box_pack_start(GTK_BOX (GTK_DIALOG (self)->vbox), toplevel_vbox,
+                       TRUE, TRUE, 0);
+
+       g_object_unref (gui);
+}
+
+/**
+ * empathy_status_preset_dialog_new:
+ * @parent: the parent window of this dialog (or NULL)
+ *
+ * Creates a new #EmpathyStatusPresetDialog that allows the user to
+ * add/remove/edit their saved status messages.
+ *
+ * Returns: the newly constructed dialog.
+ */
+GtkWidget *
+empathy_status_preset_dialog_new (GtkWindow *parent)
+{
+       GtkWidget *self = g_object_new (EMPATHY_TYPE_STATUS_PRESET_DIALOG,
+                       NULL);
+
+       if (parent) {
+               gtk_window_set_transient_for (GTK_WINDOW (self), parent);
+       }
+
+       return self;
+}
diff --git a/libempathy-gtk/empathy-status-preset-dialog.h b/libempathy-gtk/empathy-status-preset-dialog.h
new file mode 100644 (file)
index 0000000..e53c3d8
--- /dev/null
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * empathy-status-preset-dialog.c
+ *
+ * EmpathyStatusPresetDialog - a dialog for adding and removing preset status
+ * messages.
+ *
+ * Copyright (C) 2009 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Davyd Madeley <davyd.madeley@collabora.co.uk>
+ */
+
+#ifndef __EMPATHY_STATUS_PRESET_DIALOG_H__
+#define __EMPATHY_STATUS_PRESET_DIALOG_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_STATUS_PRESET_DIALOG      (empathy_status_preset_dialog_get_type ())
+#define EMPATHY_STATUS_PRESET_DIALOG(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_STATUS_PRESET_DIALOG, EmpathyStatusPresetDialog))
+#define EMPATHY_STATUS_PRESET_DIALOG_CLASS(obj)        (G_TYPE_CHECK_CLASS_CAST ((obj), EMPATHY_TYPE_STATUS_PRESET_DIALOG, EmpathyStatusPresetDialogClass))
+#define EMPATHY_IS_STATUS_PRESET_DIALOG(obj)   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_STATUS_PRESET_DIALOG))
+#define EMPATHY_IS_STATUS_PRESET_DIALOG_CLASS(obj)     (G_TYPE_CHECK_CLASS_TYPE ((obj), EMPATHY_TYPE_STATUS_PRESET_DIALOG))
+#define EMPATHY_STATUS_PRESET_DIALOG_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_STATUS_PRESET_DIALOG, EmpathyStatusPresetDialogClass))
+
+typedef struct _EmpathyStatusPresetDialog EmpathyStatusPresetDialog;
+typedef struct _EmpathyStatusPresetDialogClass EmpathyStatusPresetDialogClass;
+
+struct _EmpathyStatusPresetDialog
+{
+       GtkDialog parent;
+
+       /*< private >*/
+       gpointer priv;
+};
+
+struct _EmpathyStatusPresetDialogClass
+{
+       GtkDialogClass parent_class;
+};
+
+GType empathy_status_preset_dialog_get_type (void);
+GtkWidget *empathy_status_preset_dialog_new (GtkWindow *parent);
+
+G_END_DECLS
+
+#endif
diff --git a/libempathy-gtk/empathy-status-preset-dialog.ui b/libempathy-gtk/empathy-status-preset-dialog.ui
new file mode 100644 (file)
index 0000000..ead8ab8
--- /dev/null
@@ -0,0 +1,116 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkVBox" id="toplevel-vbox">
+    <property name="visible">True</property>
+    <property name="border_width">6</property>
+    <property name="orientation">vertical</property>
+    <property name="spacing">6</property>
+    <child>
+      <object class="GtkLabel" id="label2">
+        <property name="visible">True</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">Saved Presets</property>
+        <property name="mnemonic_widget">add-combobox</property>
+        <attributes>
+          <attribute name="weight" value="bold"/>
+        </attributes>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkScrolledWindow" id="scrolledwindow1">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="hscrollbar_policy">never</property>
+        <property name="shadow_type">etched-in</property>
+        <child>
+          <object class="GtkTreeView" id="presets-treeview">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="headers_visible">False</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="position">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkHButtonBox" id="hbuttonbox1">
+        <property name="visible">True</property>
+        <property name="layout_style">end</property>
+        <child>
+          <object class="GtkButton" id="remove-button">
+            <property name="label" translatable="yes">gtk-remove</property>
+            <property name="visible">True</property>
+            <property name="sensitive">False</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="use_stock">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="position">2</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="label1">
+        <property name="visible">True</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">Add _New Preset</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">add-combobox</property>
+        <attributes>
+          <attribute name="weight" value="bold"/>
+        </attributes>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="position">3</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkHBox" id="hbox1">
+        <property name="visible">True</property>
+        <property name="spacing">3</property>
+        <child>
+          <object class="GtkComboBoxEntry" id="add-combobox">
+            <property name="visible">True</property>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="add-button">
+            <property name="label" translatable="yes">gtk-add</property>
+            <property name="visible">True</property>
+            <property name="sensitive">False</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="use_stock">True</property>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="position">4</property>
+      </packing>
+    </child>
+  </object>
+</interface>
index 0561ecac050e7f192cfcede7c4ec485b0ed02df9..5b435f1d5d9cd9aff3ee05b80ebec9f0c2ad1f07 100644 (file)
@@ -208,9 +208,9 @@ theme_boxes_maybe_append_header (EmpathyThemeBoxes *theme,
        DEBUG ("Maybe add fancy header");
 
        /* Only insert a header if the previously inserted block is not the same
-        * as this one. This catches all the different cases:
+        * as this one.
         */
-       if (last_contact && empathy_contact_equal (last_contact, contact)) {
+       if (last_contact == contact) {
                return;
        }
 
index aa34928998e4feac39d6dcd23127a49e47be6e54..9a249e65be2663beea79c4d37cfa9dbea5b05644 100644 (file)
@@ -102,7 +102,7 @@ builder_get_file_valist (const gchar *filename,
 
        gui = gtk_builder_new ();
        if (!gtk_builder_add_from_file (gui, filename, &error)) {
-               DEBUG ("Error: %s", error->message);
+               g_critical ("GtkBuilder Error: %s", error->message);
                g_clear_error (&error);
                g_object_unref (gui);
                return NULL;
index f82f4cc0fd1c08af946afb3e33328c0ff8ad9df2..ba1f6f8c71cba5edeac9e722e949aa90aa89345c 100644 (file)
@@ -21,10 +21,9 @@ libempathy_la_SOURCES =                                      \
        empathy-account-manager.c                       \
        empathy-chatroom.c                              \
        empathy-chatroom-manager.c                      \
-       empathy-call-factory.c                  \
-       empathy-call-handler.c                  \
+       empathy-call-factory.c                          \
+       empathy-call-handler.c                          \
        empathy-contact.c                               \
-       empathy-contact-factory.c                       \
        empathy-contact-groups.c                        \
        empathy-contact-list.c                          \
        empathy-contact-manager.c                       \
@@ -47,7 +46,6 @@ libempathy_la_SOURCES =                                       \
        empathy-tp-contact-factory.c                    \
        empathy-tp-contact-list.c                       \
        empathy-tp-file.c                               \
-       empathy-tp-group.c                              \
        empathy-tp-roomlist.c                           \
        empathy-tp-tube.c                               \
        empathy-tube-handler.c                          \
@@ -72,7 +70,6 @@ libempathy_headers =                          \
        empathy-call-factory.h                  \
        empathy-call-handler.h                  \
        empathy-contact.h                       \
-       empathy-contact-factory.h               \
        empathy-contact-groups.h                \
        empathy-contact-list.h                  \
        empathy-contact-manager.h               \
@@ -95,7 +92,6 @@ libempathy_headers =                          \
        empathy-tp-contact-factory.h            \
        empathy-tp-contact-list.h               \
        empathy-tp-file.h                       \
-       empathy-tp-group.h                      \
        empathy-tp-roomlist.h                   \
        empathy-tp-tube.h                       \
        empathy-tube-handler.h                  \
index 5962a86767a17d1eb6c59ec8afc60c4fb9ca4a98..b84543176757fcddb7c169c1950270f0f5cd74d3 100644 (file)
 #include "empathy-marshal.h"
 #include "empathy-utils.h"
 
+#define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
+#include <libempathy/empathy-debug.h>
+
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountManager)
 
 typedef struct {
   McAccountMonitor *monitor;
   MissionControl   *mc;
 
-  GHashTable       *accounts;
+  GHashTable       *accounts; /* McAccount -> AccountData */
+  GHashTable       *connections; /* TpConnection -> McAccount */
   int               connected;
   int               connecting;
   gboolean          dispose_run;
 } EmpathyAccountManagerPriv;
 
 typedef struct {
+  TpConnection *connection;
   McPresence presence;
   TpConnectionStatus status;
   gboolean is_enabled;
@@ -54,6 +59,7 @@ enum {
   ACCOUNT_CHANGED,
   ACCOUNT_CONNECTION_CHANGED,
   ACCOUNT_PRESENCE_CHANGED,
+  NEW_CONNECTION,
   LAST_SIGNAL
 };
 
@@ -112,10 +118,74 @@ account_data_free (AccountData *data)
       g_source_remove (data->source_id);
       data->source_id = 0;
     }
+  if (data->connection != NULL)
+    {
+      g_object_unref (data->connection);
+      data->connection = NULL;
+    }
 
   g_slice_free (AccountData, data);
 }
 
+static void
+connection_invalidated_cb (TpProxy *connection,
+                           guint    domain,
+                           gint     code,
+                           gchar   *message,
+                           EmpathyAccountManager *manager)
+{
+  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
+  McAccount *account;
+  AccountData *data;
+
+  DEBUG ("Message: %s", message);
+
+  account = g_hash_table_lookup (priv->connections, connection);
+  g_assert (account != NULL);
+
+  data = g_hash_table_lookup (priv->accounts, account);
+  g_assert (data != NULL);
+
+  g_object_unref (data->connection);
+  data->connection = NULL;
+
+  g_hash_table_remove (priv->connections, connection);
+}
+
+static void
+connection_ready_cb (TpConnection *connection,
+                     const GError *error,
+                     gpointer manager)
+{
+  /* Errors will be handled in invalidated callback */
+  if (error != NULL)
+    return;
+
+  g_signal_emit (manager, signals[NEW_CONNECTION], 0, connection);
+}
+
+static void
+account_manager_update_connection (EmpathyAccountManager *manager,
+                                   AccountData *data,
+                                   McAccount *account)
+{
+  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
+
+  if (data->connection)
+    return;
+
+  data->connection = mission_control_get_tpconnection (priv->mc, account, NULL);
+  if (data->connection != NULL)
+    {
+      g_signal_connect (data->connection, "invalidated",
+          G_CALLBACK (connection_invalidated_cb), manager);
+      g_hash_table_insert (priv->connections, g_object_ref (data->connection),
+          g_object_ref (account));
+      tp_connection_call_when_ready (data->connection, connection_ready_cb,
+          manager);
+    }
+}
+
 static void
 account_created_cb (McAccountMonitor *mon,
                     gchar *account_name,
@@ -132,6 +202,7 @@ account_created_cb (McAccountMonitor *mon,
       AccountData *data;
 
       data = account_data_new_default (priv->mc, account);
+      g_hash_table_insert (priv->accounts, g_object_ref (account), data);
 
       initial_status = mission_control_get_connection_status (priv->mc,
                                                              account, NULL);
@@ -141,12 +212,10 @@ account_created_cb (McAccountMonitor *mon,
       else if (initial_status == TP_CONNECTION_STATUS_CONNECTING)
        priv->connecting++;
 
-      /* the reference returned by mc_account_lookup is owned by the
-       * hash table.
-       */
-      g_hash_table_insert (priv->accounts, account, data);
+      account_manager_update_connection (manager, data, account);
 
       g_signal_emit (manager, signals[ACCOUNT_CREATED], 0, account);
+      g_object_unref (account);
     }
 }
 
@@ -313,10 +382,11 @@ account_status_changed_idle_cb (ChangedSignalData *signal_data)
 
           if (status == TP_CONNECTION_STATUS_CONNECTED)
             {
-                if (data->source_id > 0) {
-                  g_source_remove (data->source_id);
-                  data->source_id = 0;
-                }
+                if (data->source_id > 0)
+                  {
+                    g_source_remove (data->source_id);
+                    data->source_id = 0;
+                  }
 
                 data->source_id = g_timeout_add_seconds (10,
                                                          remove_data_timeout,
@@ -325,6 +395,8 @@ account_status_changed_idle_cb (ChangedSignalData *signal_data)
           emit_connection = TRUE;
         }
 
+      account_manager_update_connection (manager, data, account);
+
       if (emit_presence)
         g_signal_emit (manager, signals[ACCOUNT_PRESENCE_CHANGED], 0,
                        account, presence, old_p);
@@ -381,6 +453,8 @@ empathy_account_manager_init (EmpathyAccountManager *manager)
                                           empathy_account_equal,
                                           g_object_unref, 
                                           (GDestroyNotify) account_data_free);
+  priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+                                             g_object_unref, g_object_unref);
 
   mc_accounts = mc_accounts_list ();
 
@@ -412,6 +486,7 @@ do_finalize (GObject *obj)
   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
 
   g_hash_table_unref (priv->accounts);
+  g_hash_table_unref (priv->connections);
 
   G_OBJECT_CLASS (empathy_account_manager_parent_class)->finalize (obj);
 }
@@ -562,6 +637,16 @@ empathy_account_manager_class_init (EmpathyAccountManagerClass *klass)
                   3, MC_TYPE_ACCOUNT,
                   G_TYPE_INT,  /* actual presence */
                   G_TYPE_INT); /* previous presence */
+
+  signals[NEW_CONNECTION] =
+    g_signal_new ("new-connection",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__OBJECT,
+                  G_TYPE_NONE,
+                  1, TP_TYPE_CONNECTION);
   
   g_type_class_add_private (oclass, sizeof (EmpathyAccountManagerPriv));
 }
@@ -634,3 +719,91 @@ empathy_account_manager_get_count (EmpathyAccountManager *manager)
 
   return g_hash_table_size (priv->accounts);
 }
+
+McAccount *
+empathy_account_manager_get_account (EmpathyAccountManager *manager,
+                                     TpConnection          *connection)
+{
+  EmpathyAccountManagerPriv *priv;
+
+  g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), 0);
+
+  priv = GET_PRIV (manager);
+
+  return g_hash_table_lookup (priv->connections, connection);
+}
+
+GList *
+empathy_account_manager_dup_accounts (EmpathyAccountManager *manager)
+{
+  EmpathyAccountManagerPriv *priv;
+  GList *ret;
+
+  g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), NULL);
+
+  priv = GET_PRIV (manager);
+
+  ret = g_hash_table_get_keys (priv->accounts);
+  g_list_foreach (ret, (GFunc) g_object_ref, NULL);
+
+  return ret;
+}
+
+/**
+ * empathy_account_manager_get_connection:
+ * @manager: a #EmpathyAccountManager
+ * @account: a #McAccount
+ *
+ * Get the connection of the accounts, or NULL if account is offline or the
+ * connection is not yet ready. This function does not return a new ref.
+ *
+ * Returns: the connection of the accounts.
+ **/
+TpConnection *
+empathy_account_manager_get_connection (EmpathyAccountManager *manager,
+                                        McAccount *account)
+{
+  EmpathyAccountManagerPriv *priv;
+  AccountData *data;
+
+  g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), NULL);
+  g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+
+  priv = GET_PRIV (manager);
+
+  data = g_hash_table_lookup (priv->accounts, account);
+  if (data && data->connection && tp_connection_is_ready (data->connection))
+    return data->connection;
+
+  return NULL;
+}
+
+/**
+ * empathy_account_manager_dup_connections:
+ * @manager: a #EmpathyAccountManager
+ *
+ * Get a #GList of all ready #TpConnection. The list must be freed with
+ * g_list_free, and its elements must be unreffed.
+ *
+ * Returns: the list of connections
+ **/
+GList *
+empathy_account_manager_dup_connections (EmpathyAccountManager *manager)
+{
+  EmpathyAccountManagerPriv *priv;
+  GHashTableIter iter;
+  gpointer connection;
+  GList *ret = NULL;
+
+  g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), NULL);
+
+  priv = GET_PRIV (manager);
+
+  g_hash_table_iter_init (&iter, priv->connections);
+  while (g_hash_table_iter_next (&iter, &connection, NULL)) 
+    if (connection != NULL && tp_connection_is_ready (connection))
+      ret = g_list_prepend (ret, g_object_ref (connection));
+
+  return ret;
+}
+
index b9aecb09f559868b2463a2167b8c6ccaa28be851..ac90a34f7eb3600391bba5a0c6ffdd1789ca1298 100644 (file)
@@ -61,6 +61,16 @@ gboolean                empathy_account_manager_is_account_just_connected
                                  McAccount             *account);
 int                     empathy_account_manager_get_count
                                 (EmpathyAccountManager *manager);
+McAccount *             empathy_account_manager_get_account
+                                (EmpathyAccountManager *manager,
+                                 TpConnection          *connection);
+GList *                 empathy_account_manager_dup_accounts
+                                (EmpathyAccountManager *manager);
+TpConnection *          empathy_account_manager_get_connection
+                                (EmpathyAccountManager *manager,
+                                 McAccount             *account);
+GList *                 empathy_account_manager_dup_connections
+                                (EmpathyAccountManager *manager);
 
 G_END_DECLS
 
index 39d5899bdaa04f6503a944d5f8d3f39ae5d0fde8..820de6de59592cd6f4ff0a62ccc218ae7ea80110 100644 (file)
@@ -402,30 +402,38 @@ empathy_call_handler_request_cb (EmpathyDispatchOperation *operation,
   empathy_dispatch_operation_claim (operation);
 }
 
-static void
-empathy_call_handler_contact_ready_cb (EmpathyContact *contact,
-  const GError *error, gpointer user_data, GObject *object)
+void
+empathy_call_handler_start_call (EmpathyCallHandler *handler)
 {
-  EmpathyCallHandler *self = EMPATHY_CALL_HANDLER (object);
-  EmpathyCallHandlerPriv *priv = GET_PRIV (self);
+
+  EmpathyCallHandlerPriv *priv = GET_PRIV (handler);
   EmpathyDispatcher *dispatcher;
-  McAccount *account;
+  TpConnection *connection;
   GStrv allowed;
   GValue *value;
-  GHashTable *request = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
-      (GDestroyNotify) tp_g_value_slice_free);
+  GHashTable *request;
+
+  if (priv->call != NULL)
+    {
+      empathy_call_handler_start_tpfs (handler);
+      empathy_tp_call_accept_incoming_call (priv->call);
+      return;
+    }
 
   g_assert (priv->contact != NULL);
 
   dispatcher = empathy_dispatcher_dup_singleton ();
-  account = empathy_contact_get_account (priv->contact);
-  allowed = empathy_dispatcher_find_channel_class (dispatcher, account,
+  connection = empathy_contact_get_connection (priv->contact);
+  allowed = empathy_dispatcher_find_channel_class (dispatcher, connection,
     TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, TP_HANDLE_TYPE_CONTACT);
 
   if (!tp_strv_contains ((const gchar * const *) allowed,
       TP_IFACE_CHANNEL ".TargetHandle"))
     return;
 
+  request = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+      (GDestroyNotify) tp_g_value_slice_free);
+
   /* org.freedesktop.Telepathy.Channel.ChannelType */
   value = tp_g_value_slice_new (G_TYPE_STRING);
   g_value_set_string (value, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA);
@@ -441,27 +449,9 @@ empathy_call_handler_contact_ready_cb (EmpathyContact *contact,
   g_value_set_uint (value, empathy_contact_get_handle (priv->contact));
   g_hash_table_insert (request, TP_IFACE_CHANNEL ".TargetHandle", value);
 
-  empathy_dispatcher_create_channel (dispatcher, account,
-    request, empathy_call_handler_request_cb, self);
+  empathy_dispatcher_create_channel (dispatcher, connection,
+    request, empathy_call_handler_request_cb, handler);
 
   g_object_unref (dispatcher);
 }
 
-void
-empathy_call_handler_start_call (EmpathyCallHandler *handler)
-{
-
-  EmpathyCallHandlerPriv *priv = GET_PRIV (handler);
-
-  if (priv->call == NULL)
-    {
-      empathy_contact_call_when_ready (priv->contact,
-        EMPATHY_CONTACT_READY_HANDLE,
-        empathy_call_handler_contact_ready_cb, NULL, NULL, G_OBJECT (handler));
-    }
-  else
-    {
-      empathy_call_handler_start_tpfs (handler);
-      empathy_tp_call_accept_incoming_call (priv->call);
-    }
-}
index 6765d9e48301b372b58ef80a80be794c389c0f76..e57dae7d325503e0f0580c3168f6a0aa59526239 100644 (file)
@@ -1,7 +1,6 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2004-2007 Imendio AB
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2009 Collabora Ltd.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -33,6 +32,7 @@
 
 #include "empathy-tp-chat.h"
 #include "empathy-chatroom-manager.h"
+#include "empathy-account-manager.h"
 #include "empathy-utils.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
 static EmpathyChatroomManager *chatroom_manager_singleton = NULL;
 
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyChatroomManager)
-typedef struct {
-       GList      *chatrooms;
+typedef struct
+{
+  GList *chatrooms;
   gchar *file;
+  EmpathyAccountManager *account_manager;
   /* source id of the autosave timer */
   gint save_timer_id;
 } EmpathyChatroomManagerPriv;
 
-static void     chatroom_manager_finalize          (GObject                    *object);
-static gboolean chatroom_manager_get_all           (EmpathyChatroomManager      *manager);
-static gboolean chatroom_manager_file_parse        (EmpathyChatroomManager      *manager,
-                                                   const gchar                *filename);
-static void     chatroom_manager_parse_chatroom    (EmpathyChatroomManager      *manager,
-                                                   xmlNodePtr                  node);
-static gboolean chatroom_manager_file_save         (EmpathyChatroomManager      *manager);
-static void reset_save_timeout (EmpathyChatroomManager *self);
-
 enum {
-       CHATROOM_ADDED,
-       CHATROOM_REMOVED,
-       LAST_SIGNAL
+  CHATROOM_ADDED,
+  CHATROOM_REMOVED,
+  LAST_SIGNAL
 };
 
 static guint signals[LAST_SIGNAL];
@@ -78,6 +71,238 @@ enum
 
 G_DEFINE_TYPE (EmpathyChatroomManager, empathy_chatroom_manager, G_TYPE_OBJECT);
 
+/*
+ * API to save/load and parse the chatrooms file.
+ */
+
+static gboolean
+chatroom_manager_file_save (EmpathyChatroomManager *manager)
+{
+       EmpathyChatroomManagerPriv *priv;
+       xmlDocPtr                  doc;
+       xmlNodePtr                 root;
+       GList                     *l;
+
+       priv = GET_PRIV (manager);
+
+       doc = xmlNewDoc ("1.0");
+       root = xmlNewNode (NULL, "chatrooms");
+       xmlDocSetRootElement (doc, root);
+
+       for (l = priv->chatrooms; l; l = l->next) {
+               EmpathyChatroom *chatroom;
+               xmlNodePtr       node;
+               const gchar     *account_id;
+
+               chatroom = l->data;
+
+               if (!empathy_chatroom_is_favorite (chatroom)) {
+                       continue;
+               }
+
+               account_id = mc_account_get_unique_name (empathy_chatroom_get_account (chatroom));
+
+               node = xmlNewChild (root, NULL, "chatroom", NULL);
+               xmlNewTextChild (node, NULL, "name", empathy_chatroom_get_name (chatroom));
+               xmlNewTextChild (node, NULL, "room", empathy_chatroom_get_room (chatroom));
+               xmlNewTextChild (node, NULL, "account", account_id);
+               xmlNewTextChild (node, NULL, "auto_connect",
+                       empathy_chatroom_get_auto_connect (chatroom) ? "yes" : "no");
+       }
+
+       /* Make sure the XML is indented properly */
+       xmlIndentTreeOutput = 1;
+
+       DEBUG ("Saving file:'%s'", priv->file);
+       xmlSaveFormatFileEnc (priv->file, doc, "utf-8", 1);
+       xmlFreeDoc (doc);
+
+       xmlCleanupParser ();
+       xmlMemoryDump ();
+
+       return TRUE;
+}
+
+static gboolean
+save_timeout (EmpathyChatroomManager *self)
+{
+  EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
+
+  priv->save_timer_id = 0;
+  chatroom_manager_file_save (self);
+
+  return FALSE;
+}
+
+static void
+reset_save_timeout (EmpathyChatroomManager *self)
+{
+  EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
+
+  if (priv->save_timer_id > 0)
+    {
+      g_source_remove (priv->save_timer_id);
+    }
+
+  priv->save_timer_id = g_timeout_add_seconds (SAVE_TIMER,
+      (GSourceFunc) save_timeout, self);
+}
+
+static void
+chatroom_changed_cb (EmpathyChatroom *chatroom,
+                     GParamSpec *spec,
+                     EmpathyChatroomManager *self)
+{
+  reset_save_timeout (self);
+}
+
+static void
+add_chatroom (EmpathyChatroomManager *self,
+              EmpathyChatroom *chatroom)
+{
+  EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
+
+  priv->chatrooms = g_list_prepend (priv->chatrooms, g_object_ref (chatroom));
+
+  g_signal_connect (chatroom, "notify",
+      G_CALLBACK (chatroom_changed_cb), self);
+}
+
+static void
+chatroom_manager_parse_chatroom (EmpathyChatroomManager *manager,
+                                xmlNodePtr             node)
+{
+       EmpathyChatroomManagerPriv *priv;
+       EmpathyChatroom            *chatroom;
+       McAccount                 *account;
+       xmlNodePtr                 child;
+       gchar                     *str;
+       gchar                     *name;
+       gchar                     *room;
+       gchar                     *account_id;
+       gboolean                   auto_connect;
+
+       priv = GET_PRIV (manager);
+
+       /* default values. */
+       name = NULL;
+       room = NULL;
+       auto_connect = TRUE;
+       account_id = NULL;
+
+       for (child = node->children; child; child = child->next) {
+               gchar *tag;
+
+               if (xmlNodeIsText (child)) {
+                       continue;
+               }
+
+               tag = (gchar *) child->name;
+               str = (gchar *) xmlNodeGetContent (child);
+
+               if (strcmp (tag, "name") == 0) {
+                       name = g_strdup (str);
+               }
+               else if (strcmp (tag, "room") == 0) {
+                       room = g_strdup (str);
+               }
+               else if (strcmp (tag, "auto_connect") == 0) {
+                       if (strcmp (str, "yes") == 0) {
+                               auto_connect = TRUE;
+                       } else {
+                               auto_connect = FALSE;
+                       }
+               }
+               else if (strcmp (tag, "account") == 0) {
+                       account_id = g_strdup (str);
+               }
+
+               xmlFree (str);
+       }
+
+       account = mc_account_lookup (account_id);
+       if (!account) {
+               g_free (name);
+               g_free (room);
+               g_free (account_id);
+               return;
+       }
+
+       chatroom = empathy_chatroom_new_full (account, room, name, auto_connect);
+       empathy_chatroom_set_favorite (chatroom, TRUE);
+       add_chatroom (manager, chatroom);
+       g_signal_emit (manager, signals[CHATROOM_ADDED], 0, chatroom);
+
+       g_object_unref (account);
+       g_free (name);
+       g_free (room);
+       g_free (account_id);
+}
+
+static gboolean
+chatroom_manager_file_parse (EmpathyChatroomManager *manager,
+                            const gchar           *filename)
+{
+       EmpathyChatroomManagerPriv *priv;
+       xmlParserCtxtPtr           ctxt;
+       xmlDocPtr                  doc;
+       xmlNodePtr                 chatrooms;
+       xmlNodePtr                 node;
+
+       priv = GET_PRIV (manager);
+
+       DEBUG ("Attempting to parse file:'%s'...", filename);
+
+       ctxt = xmlNewParserCtxt ();
+
+       /* Parse and validate the file. */
+       doc = xmlCtxtReadFile (ctxt, filename, NULL, 0);
+       if (!doc) {
+               g_warning ("Failed to parse file:'%s'", filename);
+               xmlFreeParserCtxt (ctxt);
+               return FALSE;
+       }
+
+       if (!empathy_xml_validate (doc, CHATROOMS_DTD_FILENAME)) {
+               g_warning ("Failed to validate file:'%s'", filename);
+               xmlFreeDoc(doc);
+               xmlFreeParserCtxt (ctxt);
+               return FALSE;
+       }
+
+       /* The root node, chatrooms. */
+       chatrooms = xmlDocGetRootElement (doc);
+
+       for (node = chatrooms->children; node; node = node->next) {
+               if (strcmp ((gchar *) node->name, "chatroom") == 0) {
+                       chatroom_manager_parse_chatroom (manager, node);
+               }
+       }
+
+       DEBUG ("Parsed %d chatrooms", g_list_length (priv->chatrooms));
+
+       xmlFreeDoc(doc);
+       xmlFreeParserCtxt (ctxt);
+
+       return TRUE;
+}
+
+static gboolean
+chatroom_manager_get_all (EmpathyChatroomManager *manager)
+{
+       EmpathyChatroomManagerPriv *priv;
+
+       priv = GET_PRIV (manager);
+
+       /* read file in */
+       if (g_file_test (priv->file, G_FILE_TEST_EXISTS) &&
+           !chatroom_manager_file_parse (manager, priv->file)) {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
 static void
 empathy_chatroom_manager_get_property (GObject *object,
                                        guint property_id,
@@ -119,6 +344,41 @@ empathy_chatroom_manager_set_property (GObject *object,
     }
 }
 
+static void
+chatroom_manager_finalize (GObject *object)
+{
+  EmpathyChatroomManager *self = EMPATHY_CHATROOM_MANAGER (object);
+  EmpathyChatroomManagerPriv *priv;
+  GList *l;
+
+  priv = GET_PRIV (object);
+
+  g_object_unref (priv->account_manager);
+
+  if (priv->save_timer_id > 0)
+    {
+      /* have to save before destroy the object */
+      g_source_remove (priv->save_timer_id);
+      priv->save_timer_id = 0;
+      chatroom_manager_file_save (self);
+    }
+
+  for (l = priv->chatrooms; l != NULL; l = g_list_next (l))
+    {
+      EmpathyChatroom *chatroom = l->data;
+
+      g_signal_handlers_disconnect_by_func (chatroom, chatroom_changed_cb,
+          self);
+
+      g_object_unref (chatroom);
+    }
+
+  g_list_free (priv->chatrooms);
+  g_free (priv->file);
+
+  (G_OBJECT_CLASS (empathy_chatroom_manager_parent_class)->finalize) (object);
+}
+
 static GObject *
 empathy_chatroom_manager_constructor (GType type,
                                       guint n_props,
@@ -141,6 +401,8 @@ empathy_chatroom_manager_constructor (GType type,
   chatroom_manager_singleton = self;
   g_object_add_weak_pointer (obj, (gpointer) &chatroom_manager_singleton);
 
+  priv->account_manager = empathy_account_manager_dup_singleton ();
+
   if (priv->file == NULL)
     {
       /* Set the default file path */
@@ -152,230 +414,137 @@ empathy_chatroom_manager_constructor (GType type,
 
       priv->file = g_build_filename (dir, CHATROOMS_XML_FILENAME, NULL);
       g_free (dir);
-    }
-
-  chatroom_manager_get_all (self);
-  return obj;
-}
-
-static void
-empathy_chatroom_manager_class_init (EmpathyChatroomManagerClass *klass)
-{
-       GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GParamSpec *param_spec;
-
-  object_class->constructor = empathy_chatroom_manager_constructor;
-  object_class->get_property = empathy_chatroom_manager_get_property;
-  object_class->set_property = empathy_chatroom_manager_set_property;
-       object_class->finalize = chatroom_manager_finalize;
-
-  param_spec = g_param_spec_string (
-      "file",
-      "path of the favorite file",
-      "The path of the XML file containing user's favorites",
-      NULL,
-      G_PARAM_CONSTRUCT_ONLY |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NAME |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_FILE, param_spec);
-
-       signals[CHATROOM_ADDED] =
-               g_signal_new ("chatroom-added",
-                             G_TYPE_FROM_CLASS (klass),
-                             G_SIGNAL_RUN_LAST,
-                             0,
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__OBJECT,
-                             G_TYPE_NONE,
-                             1, EMPATHY_TYPE_CHATROOM);
-       signals[CHATROOM_REMOVED] =
-               g_signal_new ("chatroom-removed",
-                             G_TYPE_FROM_CLASS (klass),
-                             G_SIGNAL_RUN_LAST,
-                             0,
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__OBJECT,
-                             G_TYPE_NONE,
-                             1, EMPATHY_TYPE_CHATROOM);
-
-       g_type_class_add_private (object_class,
-                                 sizeof (EmpathyChatroomManagerPriv));
-}
-
-static void
-empathy_chatroom_manager_init (EmpathyChatroomManager *manager)
-{
-       EmpathyChatroomManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
-               EMPATHY_TYPE_CHATROOM_MANAGER, EmpathyChatroomManagerPriv);
-
-       manager->priv = priv;
-}
-
-static void
-chatroom_changed_cb (EmpathyChatroom *chatroom,
-                     GParamSpec *spec,
-                     EmpathyChatroomManager *self)
-{
-  reset_save_timeout (self);
-}
-
-static void
-chatroom_manager_finalize (GObject *object)
-{
-  EmpathyChatroomManager *self = EMPATHY_CHATROOM_MANAGER (object);
-       EmpathyChatroomManagerPriv *priv;
-  GList *l;
-
-       priv = GET_PRIV (object);
-
-  if (priv->save_timer_id > 0)
-    {
-      /* have to save before destroy the object */
-      g_source_remove (priv->save_timer_id);
-      priv->save_timer_id = 0;
-      chatroom_manager_file_save (self);
-    }
-
-  for (l = priv->chatrooms; l != NULL; l = g_list_next (l))
-    {
-      EmpathyChatroom *chatroom = l->data;
-
-      g_signal_handlers_disconnect_by_func (chatroom, chatroom_changed_cb,
-          self);
-
-      g_object_unref (chatroom);
-    }
-
-       g_list_free (priv->chatrooms);
-  g_free (priv->file);
-
-       (G_OBJECT_CLASS (empathy_chatroom_manager_parent_class)->finalize) (object);
-}
-
-EmpathyChatroomManager *
-empathy_chatroom_manager_dup_singleton (const gchar *file)
-{
-       return EMPATHY_CHATROOM_MANAGER (g_object_new (EMPATHY_TYPE_CHATROOM_MANAGER,
-               "file", file, NULL));
-}
-
-static gboolean
-save_timeout (EmpathyChatroomManager *self)
-{
-  EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
-
-  priv->save_timer_id = 0;
-  chatroom_manager_file_save (self);
+    }
 
-  return FALSE;
+  chatroom_manager_get_all (self);
+  return obj;
 }
 
 static void
-reset_save_timeout (EmpathyChatroomManager *self)
+empathy_chatroom_manager_class_init (EmpathyChatroomManagerClass *klass)
 {
-  EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GParamSpec *param_spec;
 
-  if (priv->save_timer_id > 0)
-    {
-      g_source_remove (priv->save_timer_id);
-    }
+  object_class->constructor = empathy_chatroom_manager_constructor;
+  object_class->get_property = empathy_chatroom_manager_get_property;
+  object_class->set_property = empathy_chatroom_manager_set_property;
+       object_class->finalize = chatroom_manager_finalize;
 
-  priv->save_timer_id = g_timeout_add_seconds (SAVE_TIMER,
-      (GSourceFunc) save_timeout, self);
+  param_spec = g_param_spec_string (
+      "file",
+      "path of the favorite file",
+      "The path of the XML file containing user's favorites",
+      NULL,
+      G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NAME |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_FILE, param_spec);
+
+  signals[CHATROOM_ADDED] = g_signal_new ("chatroom-added",
+      G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST,
+      0, NULL, NULL,
+      g_cclosure_marshal_VOID__OBJECT,
+      G_TYPE_NONE,
+      1, EMPATHY_TYPE_CHATROOM);
+
+  signals[CHATROOM_REMOVED] = g_signal_new ("chatroom-removed",
+      G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST,
+      0, NULL, NULL,
+      g_cclosure_marshal_VOID__OBJECT,
+      G_TYPE_NONE,
+      1, EMPATHY_TYPE_CHATROOM);
+
+  g_type_class_add_private (object_class, sizeof (EmpathyChatroomManagerPriv));
 }
 
 static void
-add_chatroom (EmpathyChatroomManager *self,
-              EmpathyChatroom *chatroom)
+empathy_chatroom_manager_init (EmpathyChatroomManager *manager)
 {
-  EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
+  EmpathyChatroomManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
+      EMPATHY_TYPE_CHATROOM_MANAGER, EmpathyChatroomManagerPriv);
 
-  priv->chatrooms = g_list_prepend (priv->chatrooms, g_object_ref (chatroom));
+  manager->priv = priv;
+}
 
-  g_signal_connect (chatroom, "notify",
-      G_CALLBACK (chatroom_changed_cb), self);
+EmpathyChatroomManager *
+empathy_chatroom_manager_dup_singleton (const gchar *file)
+{
+  return EMPATHY_CHATROOM_MANAGER (g_object_new (EMPATHY_TYPE_CHATROOM_MANAGER,
+      "file", file, NULL));
 }
 
 gboolean
 empathy_chatroom_manager_add (EmpathyChatroomManager *manager,
                             EmpathyChatroom        *chatroom)
 {
-       EmpathyChatroomManagerPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_CHATROOM_MANAGER (manager), FALSE);
-       g_return_val_if_fail (EMPATHY_IS_CHATROOM (chatroom), FALSE);
-
-       priv = GET_PRIV (manager);
+  EmpathyChatroomManagerPriv *priv;
 
-       /* don't add more than once */
-       if (!empathy_chatroom_manager_find (manager,
-                                          empathy_chatroom_get_account (chatroom),
-                                          empathy_chatroom_get_room (chatroom))) {
-      gboolean favorite;
+  g_return_val_if_fail (EMPATHY_IS_CHATROOM_MANAGER (manager), FALSE);
+  g_return_val_if_fail (EMPATHY_IS_CHATROOM (chatroom), FALSE);
 
-      g_object_get (chatroom, "favorite", &favorite, NULL);
+  priv = GET_PRIV (manager);
 
-    add_chatroom (manager, chatroom);
+  /* don't add more than once */
+  if (!empathy_chatroom_manager_find (manager,
+      empathy_chatroom_get_account (chatroom),
+      empathy_chatroom_get_room (chatroom)))
+    {
+      add_chatroom (manager, chatroom);
 
-    if (favorite)
-      {
+      if (empathy_chatroom_is_favorite (chatroom))
         reset_save_timeout (manager);
-      }
-
-               g_signal_emit (manager, signals[CHATROOM_ADDED], 0, chatroom);
 
-               return TRUE;
-       }
+      g_signal_emit (manager, signals[CHATROOM_ADDED], 0, chatroom);
+      return TRUE;
+    }
 
-       return FALSE;
+  return FALSE;
 }
 
 void
 empathy_chatroom_manager_remove (EmpathyChatroomManager *manager,
-                               EmpathyChatroom        *chatroom)
+                                 EmpathyChatroom        *chatroom)
 {
-       EmpathyChatroomManagerPriv *priv;
-       GList                     *l;
-
-       g_return_if_fail (EMPATHY_IS_CHATROOM_MANAGER (manager));
-       g_return_if_fail (EMPATHY_IS_CHATROOM (chatroom));
-
-       priv = GET_PRIV (manager);
+  EmpathyChatroomManagerPriv *priv;
+  GList *l;
 
-       for (l = priv->chatrooms; l; l = l->next) {
-               EmpathyChatroom *this_chatroom;
+  g_return_if_fail (EMPATHY_IS_CHATROOM_MANAGER (manager));
+  g_return_if_fail (EMPATHY_IS_CHATROOM (chatroom));
 
-               this_chatroom = l->data;
+  priv = GET_PRIV (manager);
 
-               if (this_chatroom == chatroom ||
-        empathy_chatroom_equal (chatroom, this_chatroom)) {
-        gboolean favorite;
-                       priv->chatrooms = g_list_delete_link (priv->chatrooms, l);
+  for (l = priv->chatrooms; l; l = l->next)
+    {
+      EmpathyChatroom *this_chatroom;
 
-      g_object_get (chatroom, "favorite", &favorite, NULL);
+      this_chatroom = l->data;
 
-      if (favorite)
+      if (this_chatroom == chatroom ||
+          empathy_chatroom_equal (chatroom, this_chatroom))
         {
-          reset_save_timeout (manager);
-        }
-
-                       g_signal_emit (manager, signals[CHATROOM_REMOVED], 0, this_chatroom);
+          priv->chatrooms = g_list_delete_link (priv->chatrooms, l);
+          if (empathy_chatroom_is_favorite (chatroom))
+            reset_save_timeout (manager);
 
-      g_signal_handlers_disconnect_by_func (chatroom, chatroom_changed_cb,
-          manager);
+          g_signal_emit (manager, signals[CHATROOM_REMOVED], 0, this_chatroom);
+          g_signal_handlers_disconnect_by_func (chatroom, chatroom_changed_cb,
+              manager);
 
-                       g_object_unref (this_chatroom);
-                       break;
-               }
-       }
+          g_object_unref (this_chatroom);
+          break;
+        }
+    }
 }
 
 EmpathyChatroom *
 empathy_chatroom_manager_find (EmpathyChatroomManager *manager,
-                             McAccount             *account,
-                             const gchar           *room)
+                               McAccount *account,
+                               const gchar *room)
 {
        EmpathyChatroomManagerPriv *priv;
        GList                     *l;
@@ -457,7 +626,7 @@ empathy_chatroom_manager_get_count (EmpathyChatroomManager *manager,
                chatroom = l->data;
 
                if (empathy_account_equal (account,
-                                         empathy_chatroom_get_account (chatroom))) {
+                                          empathy_chatroom_get_account (chatroom))) {
                        count++;
                }
        }
@@ -465,225 +634,36 @@ empathy_chatroom_manager_get_count (EmpathyChatroomManager *manager,
        return count;
 }
 
-/*
- * API to save/load and parse the chatrooms file.
- */
-
-static gboolean
-chatroom_manager_get_all (EmpathyChatroomManager *manager)
-{
-       EmpathyChatroomManagerPriv *priv;
-
-       priv = GET_PRIV (manager);
-
-       /* read file in */
-       if (g_file_test (priv->file, G_FILE_TEST_EXISTS) &&
-           !chatroom_manager_file_parse (manager, priv->file))
-    return FALSE;
-
-       return TRUE;
-}
-
-static gboolean
-chatroom_manager_file_parse (EmpathyChatroomManager *manager,
-                            const gchar           *filename)
-{
-       EmpathyChatroomManagerPriv *priv;
-       xmlParserCtxtPtr           ctxt;
-       xmlDocPtr                  doc;
-       xmlNodePtr                 chatrooms;
-       xmlNodePtr                 node;
-
-       priv = GET_PRIV (manager);
-
-       DEBUG ("Attempting to parse file:'%s'...", filename);
-
-       ctxt = xmlNewParserCtxt ();
-
-       /* Parse and validate the file. */
-       doc = xmlCtxtReadFile (ctxt, filename, NULL, 0);
-       if (!doc) {
-               g_warning ("Failed to parse file:'%s'", filename);
-               xmlFreeParserCtxt (ctxt);
-               return FALSE;
-       }
-
-       if (!empathy_xml_validate (doc, CHATROOMS_DTD_FILENAME)) {
-               g_warning ("Failed to validate file:'%s'", filename);
-               xmlFreeDoc(doc);
-               xmlFreeParserCtxt (ctxt);
-               return FALSE;
-       }
-
-       /* The root node, chatrooms. */
-       chatrooms = xmlDocGetRootElement (doc);
-
-       for (node = chatrooms->children; node; node = node->next) {
-               if (strcmp ((gchar *) node->name, "chatroom") == 0) {
-                       chatroom_manager_parse_chatroom (manager, node);
-               }
-       }
-
-       DEBUG ("Parsed %d chatrooms", g_list_length (priv->chatrooms));
-
-       xmlFreeDoc(doc);
-       xmlFreeParserCtxt (ctxt);
-
-       return TRUE;
-}
-
-static void
-chatroom_manager_parse_chatroom (EmpathyChatroomManager *manager,
-                                xmlNodePtr             node)
-{
-       EmpathyChatroomManagerPriv *priv;
-       EmpathyChatroom            *chatroom;
-       McAccount                 *account;
-       xmlNodePtr                 child;
-       gchar                     *str;
-       gchar                     *name;
-       gchar                     *room;
-       gchar                     *account_id;
-       gboolean                   auto_connect;
-
-       priv = GET_PRIV (manager);
-
-       /* default values. */
-       name = NULL;
-       room = NULL;
-       auto_connect = TRUE;
-       account_id = NULL;
-
-       for (child = node->children; child; child = child->next) {
-               gchar *tag;
-
-               if (xmlNodeIsText (child)) {
-                       continue;
-               }
-
-               tag = (gchar *) child->name;
-               str = (gchar *) xmlNodeGetContent (child);
-
-               if (strcmp (tag, "name") == 0) {
-                       name = g_strdup (str);
-               }
-               else if (strcmp (tag, "room") == 0) {
-                       room = g_strdup (str);
-               }
-               else if (strcmp (tag, "auto_connect") == 0) {
-                       if (strcmp (str, "yes") == 0) {
-                               auto_connect = TRUE;
-                       } else {
-                               auto_connect = FALSE;
-                       }
-               }
-               else if (strcmp (tag, "account") == 0) {
-                       account_id = g_strdup (str);
-               }
-
-               xmlFree (str);
-       }
-
-       account = mc_account_lookup (account_id);
-       if (!account) {
-               g_free (name);
-               g_free (room);
-               g_free (account_id);
-               return;
-       }
-
-       chatroom = empathy_chatroom_new_full (account, room, name, auto_connect);
-  g_object_set (chatroom, "favorite", TRUE, NULL);
-  add_chatroom (manager, chatroom);
-       g_signal_emit (manager, signals[CHATROOM_ADDED], 0, chatroom);
-
-       g_object_unref (account);
-       g_free (name);
-       g_free (room);
-       g_free (account_id);
-}
-
-static gboolean
-chatroom_manager_file_save (EmpathyChatroomManager *manager)
-{
-       EmpathyChatroomManagerPriv *priv;
-       xmlDocPtr                  doc;
-       xmlNodePtr                 root;
-       GList                     *l;
-
-       priv = GET_PRIV (manager);
-
-       doc = xmlNewDoc ("1.0");
-       root = xmlNewNode (NULL, "chatrooms");
-       xmlDocSetRootElement (doc, root);
-
-       for (l = priv->chatrooms; l; l = l->next) {
-               EmpathyChatroom *chatroom;
-               xmlNodePtr      node;
-               const gchar    *account_id;
-    gboolean favorite;
-
-               chatroom = l->data;
-
-    g_object_get (chatroom, "favorite", &favorite, NULL);
-    if (!favorite)
-      continue;
-
-               account_id = mc_account_get_unique_name (empathy_chatroom_get_account (chatroom));
-
-               node = xmlNewChild (root, NULL, "chatroom", NULL);
-               xmlNewTextChild (node, NULL, "name", empathy_chatroom_get_name (chatroom));
-               xmlNewTextChild (node, NULL, "room", empathy_chatroom_get_room (chatroom));
-               xmlNewTextChild (node, NULL, "account", account_id);
-               xmlNewTextChild (node, NULL, "auto_connect", empathy_chatroom_get_auto_connect (chatroom) ? "yes" : "no");
-       }
-
-       /* Make sure the XML is indented properly */
-       xmlIndentTreeOutput = 1;
-
-       DEBUG ("Saving file:'%s'", priv->file);
-       xmlSaveFormatFileEnc (priv->file, doc, "utf-8", 1);
-       xmlFreeDoc (doc);
-
-       xmlCleanupParser ();
-       xmlMemoryDump ();
-
-       return TRUE;
-}
-
 static void
 chatroom_manager_chat_destroyed_cb (EmpathyTpChat *chat,
-  gpointer user_data)
+  gpointer manager)
 {
-  EmpathyChatroomManager *manager = EMPATHY_CHATROOM_MANAGER (user_data);
-  McAccount *account = empathy_tp_chat_get_account (chat);
-  EmpathyChatroom *chatroom;
-  const gchar *roomname;
-  gboolean favorite;
-
-  roomname = empathy_tp_chat_get_id (chat);
-  chatroom = empathy_chatroom_manager_find (manager, account, roomname);
+  EmpathyChatroomManagerPriv *priv = GET_PRIV (manager);
+  GList *l;
 
-  if (chatroom == NULL)
-    return;
+  for (l = priv->chatrooms; l; l = l->next)
+    {
+      EmpathyChatroom *chatroom = l->data;
 
-  g_object_set (chatroom, "tp-chat", NULL, NULL);
-  g_object_get (chatroom, "favorite", &favorite, NULL);
+      if (empathy_chatroom_get_tp_chat (chatroom) != chat)
+        continue;
 
-  if (!favorite)
-    {
-      /* Remove the chatroom from the list, unless it's in the list of
-       * favourites..
-       * FIXME this policy should probably not be in libempathy */
-      empathy_chatroom_manager_remove (manager, chatroom);
+      empathy_chatroom_set_tp_chat (chatroom, NULL);
+      if (!empathy_chatroom_is_favorite (chatroom))
+        {
+          /* Remove the chatroom from the list, unless it's in the list of
+           * favourites..
+           * FIXME this policy should probably not be in libempathy */
+          empathy_chatroom_manager_remove (manager, chatroom);
+        }
     }
 }
 
 static void
 chatroom_manager_observe_channel_cb (EmpathyDispatcher *dispatcher,
-  EmpathyDispatchOperation *operation, gpointer user_data)
+  EmpathyDispatchOperation *operation, gpointer manager)
 {
-  EmpathyChatroomManager *manager = EMPATHY_CHATROOM_MANAGER (user_data);
+  EmpathyChatroomManagerPriv *priv = GET_PRIV (manager);
   EmpathyChatroom *chatroom;
   TpChannel *channel;
   EmpathyTpChat *chat;
@@ -691,6 +671,7 @@ chatroom_manager_observe_channel_cb (EmpathyDispatcher *dispatcher,
   GQuark channel_type;
   TpHandleType handle_type;
   McAccount *account;
+  TpConnection *connection;
 
   channel_type = empathy_dispatch_operation_get_channel_type_id (operation);
 
@@ -706,7 +687,9 @@ chatroom_manager_observe_channel_cb (EmpathyDispatcher *dispatcher,
 
   chat = EMPATHY_TP_CHAT (
     empathy_dispatch_operation_get_channel_wrapper (operation));
-  account = empathy_tp_chat_get_account (chat);
+  connection = empathy_tp_chat_get_connection (chat);
+  account = empathy_account_manager_get_account (priv->account_manager,
+      connection);
 
   roomname = empathy_tp_chat_get_id (chat);
 
@@ -716,13 +699,13 @@ chatroom_manager_observe_channel_cb (EmpathyDispatcher *dispatcher,
     {
       chatroom = empathy_chatroom_new_full (account, roomname, roomname,
         FALSE);
-      g_object_set (G_OBJECT (chatroom), "tp-chat", chat, NULL);
+      empathy_chatroom_set_tp_chat (chatroom, chat);
       empathy_chatroom_manager_add (manager, chatroom);
       g_object_unref (chatroom);
     }
   else
     {
-      g_object_set (G_OBJECT (chatroom), "tp-chat", chat, NULL);
+        empathy_chatroom_set_tp_chat (chatroom, chat);
     }
 
   /* A TpChat is always destroyed as it only gets unreffed after the channel
index 8ffd8a51e11ce2b4766aaa3099bfb68e49f15662..6575bb9982288dacbba51a346bd562d027484278 100644 (file)
@@ -111,17 +111,14 @@ empathy_chatroom_class_init (EmpathyChatroomClass *klass)
                                                               FALSE,
                                                               G_PARAM_READWRITE));
 
-  g_object_class_install_property (object_class,
-      PROP_FAVORITE,
-      g_param_spec_boolean ("favorite",
-        "Favorite",
-        "TRUE if the chatroom is in user's favorite list",
-        FALSE,
-        G_PARAM_READWRITE |
-        G_PARAM_CONSTRUCT |
-        G_PARAM_STATIC_NAME |
-        G_PARAM_STATIC_NICK |
-        G_PARAM_STATIC_BLURB));
+       g_object_class_install_property (object_class,
+                                        PROP_FAVORITE,
+                                        g_param_spec_boolean ("favorite",
+                                                              "Favorite",
+                                                              "TRUE if the chatroom is in user's favorite list",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE |
+                                                              G_PARAM_CONSTRUCT));
 
        g_object_class_install_property (object_class,
                                         PROP_TP_CHAT,
@@ -284,30 +281,14 @@ chatroom_set_property (GObject      *object,
                empathy_chatroom_set_auto_connect (EMPATHY_CHATROOM (object),
                                                  g_value_get_boolean (value));
                break;
-  case PROP_FAVORITE:
-    priv->favorite = g_value_get_boolean (value);
-    if (!priv->favorite)
-      {
-        empathy_chatroom_set_auto_connect (EMPATHY_CHATROOM (object),
-            FALSE);
-      }
-    break;
-       case PROP_TP_CHAT: {
-               GObject *chat = g_value_dup_object (value);
-
-               if (chat == (GObject *) priv->tp_chat)
-                       break;
-
-               g_assert (chat == NULL || priv->tp_chat == NULL);
-
-               if (priv->tp_chat != NULL) {
-                       g_object_unref (priv->tp_chat);
-                       priv->tp_chat = NULL;
-               } else {
-                       priv->tp_chat = EMPATHY_TP_CHAT (chat);
-               }
+       case PROP_FAVORITE:
+               empathy_chatroom_set_favorite (EMPATHY_CHATROOM (object),
+                                              g_value_get_boolean (value));
+               break;
+       case PROP_TP_CHAT:
+               empathy_chatroom_set_tp_chat (EMPATHY_CHATROOM (object),
+                                             g_value_get_object (value));
                break;
-       }
   case PROP_SUBJECT:
     empathy_chatroom_set_subject (EMPATHY_CHATROOM (object),
         g_value_get_string (value));
@@ -476,12 +457,11 @@ empathy_chatroom_set_auto_connect (EmpathyChatroom *chatroom,
 
        priv->auto_connect = auto_connect;
 
-  if (priv->auto_connect)
-    {
-      /* auto_connect implies favorite */
-      priv->favorite = TRUE;
-      g_object_notify (G_OBJECT (chatroom), "favorite");
-    }
+       if (priv->auto_connect) {
+               /* auto_connect implies favorite */
+               priv->favorite = TRUE;
+               g_object_notify (G_OBJECT (chatroom), "favorite");
+       }
 
        g_object_notify (G_OBJECT (chatroom), "auto-connect");
 }
@@ -504,12 +484,13 @@ empathy_chatroom_equal (gconstpointer v1,
        room_a = empathy_chatroom_get_room (EMPATHY_CHATROOM (v1));
        room_b = empathy_chatroom_get_room (EMPATHY_CHATROOM (v2));
 
-       return empathy_account_equal (account_a, account_b) && !tp_strdiff (room_a,
-      room_b);
+       return empathy_account_equal (account_a, account_b) &&
+              !tp_strdiff (room_a, room_b);
 }
 
 EmpathyTpChat *
-empathy_chatroom_get_tp_chat (EmpathyChatroom *chatroom) {
+empathy_chatroom_get_tp_chat (EmpathyChatroom *chatroom)
+{
        EmpathyChatroomPriv *priv;
 
        g_return_val_if_fail (EMPATHY_IS_CHATROOM (chatroom), NULL);
@@ -631,3 +612,59 @@ empathy_chatroom_set_invite_only (EmpathyChatroom *chatroom,
   g_object_notify (G_OBJECT (chatroom), "invite-only");
 }
 
+void
+empathy_chatroom_set_tp_chat (EmpathyChatroom *chatroom,
+                             EmpathyTpChat   *tp_chat)
+{
+       EmpathyChatroomPriv *priv;
+
+       g_return_if_fail (EMPATHY_IS_CHATROOM (chatroom));
+       g_return_if_fail (tp_chat == NULL || EMPATHY_IS_TP_CHAT (tp_chat));
+
+       priv = GET_PRIV (chatroom);
+
+       if (priv->tp_chat == tp_chat) {
+               return;
+       }
+
+       if (priv->tp_chat != NULL) {
+               g_object_unref (priv->tp_chat);
+       }
+
+       priv->tp_chat = tp_chat ? g_object_ref (tp_chat) : NULL;
+       g_object_notify (G_OBJECT (chatroom), "tp-chat");
+}
+
+gboolean
+empathy_chatroom_is_favorite (EmpathyChatroom *chatroom)
+{
+       EmpathyChatroomPriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_CHATROOM (chatroom), FALSE);
+
+       priv = GET_PRIV (chatroom);
+
+       return priv->favorite;
+}
+
+void
+empathy_chatroom_set_favorite (EmpathyChatroom *chatroom,
+                              gboolean         favorite)
+{
+       EmpathyChatroomPriv *priv;
+
+       g_return_if_fail (EMPATHY_IS_CHATROOM (chatroom));
+
+       priv = GET_PRIV (chatroom);
+
+       if (priv->favorite == favorite) {
+               return;
+       }
+
+       priv->favorite = favorite;
+       if (!priv->favorite) {
+               empathy_chatroom_set_auto_connect (chatroom, FALSE);
+       }
+       g_object_notify (G_OBJECT (chatroom), "favorite");
+}
+
index 08e3bc1eb04e383e6771127e833b1479265a396d..560517d489eab78331530bfb698c45f57d375030 100644 (file)
@@ -84,6 +84,11 @@ void            empathy_chatroom_set_invite_only  (EmpathyChatroom *chatroom,
 gboolean        empathy_chatroom_equal            (gconstpointer    v1,
                                                   gconstpointer    v2);
 EmpathyTpChat * empathy_chatroom_get_tp_chat      (EmpathyChatroom *chatroom);
+void            empathy_chatroom_set_tp_chat      (EmpathyChatroom *chatroom,
+                                                  EmpathyTpChat   *tp_chat);
+gboolean        empathy_chatroom_is_favorite      (EmpathyChatroom *chatroom);
+void            empathy_chatroom_set_favorite     (EmpathyChatroom *chatroom,
+                                                  gboolean         favorite);
 
 G_END_DECLS
 
diff --git a/libempathy/empathy-contact-factory.c b/libempathy/empathy-contact-factory.c
deleted file mode 100644 (file)
index c350057..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Authors: Xavier Claessens <xclaesse@gmail.com>
- */
-
-#include <config.h>
-
-#include "empathy-contact-factory.h"
-#include "empathy-utils.h"
-
-#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyContactFactory)
-typedef struct {
-       GHashTable *accounts;
-} EmpathyContactFactoryPriv;
-
-G_DEFINE_TYPE (EmpathyContactFactory, empathy_contact_factory, G_TYPE_OBJECT);
-
-static EmpathyContactFactory * factory_singleton = NULL;
-
-EmpathyTpContactFactory *
-empathy_contact_factory_get_tp_factory (EmpathyContactFactory *factory,
-                                       McAccount             *account)
-{
-       EmpathyContactFactoryPriv *priv = GET_PRIV (factory);
-       EmpathyTpContactFactory   *tp_factory;
-
-       tp_factory = g_hash_table_lookup (priv->accounts, account);
-       if (!tp_factory) {
-               tp_factory = empathy_tp_contact_factory_new (account);
-               g_hash_table_insert (priv->accounts, account, tp_factory);
-       }
-
-       return g_object_ref (tp_factory);
-}
-
-EmpathyContact *
-empathy_contact_factory_get_user (EmpathyContactFactory *factory,
-                                 McAccount             *account)
-{
-       EmpathyTpContactFactory *tp_factory;
-
-       tp_factory = empathy_contact_factory_get_tp_factory (factory, account);
-
-       return empathy_tp_contact_factory_get_user (tp_factory);
-}
-
-EmpathyContact *
-empathy_contact_factory_get_from_id (EmpathyContactFactory *factory,
-                                    McAccount             *account,
-                                    const gchar           *id)
-{
-       EmpathyTpContactFactory *tp_factory;
-
-       tp_factory = empathy_contact_factory_get_tp_factory (factory, account);
-
-       return empathy_tp_contact_factory_get_from_id (tp_factory, id);
-}
-
-EmpathyContact *
-empathy_contact_factory_get_from_handle (EmpathyContactFactory *factory,
-                                        McAccount             *account,
-                                        guint                  handle)
-{
-       EmpathyTpContactFactory *tp_factory;
-
-       tp_factory = empathy_contact_factory_get_tp_factory (factory, account);
-
-       return empathy_tp_contact_factory_get_from_handle (tp_factory, handle);
-}
-
-GList *
-empathy_contact_factory_get_from_handles (EmpathyContactFactory *factory,
-                                         McAccount             *account,
-                                         const GArray          *handles)
-{
-       EmpathyTpContactFactory *tp_factory;
-
-       tp_factory = empathy_contact_factory_get_tp_factory (factory, account);
-
-       return empathy_tp_contact_factory_get_from_handles (tp_factory, handles);
-}
-
-void
-empathy_contact_factory_set_alias (EmpathyContactFactory *factory,
-                                  EmpathyContact        *contact,
-                                  const gchar           *alias)
-{
-       EmpathyTpContactFactory *tp_factory;
-       McAccount               *account;
-
-       account = empathy_contact_get_account (contact);
-       tp_factory = empathy_contact_factory_get_tp_factory (factory, account);
-
-       return empathy_tp_contact_factory_set_alias (tp_factory, contact, alias);
-}
-
-void
-empathy_contact_factory_set_avatar (EmpathyContactFactory *factory,
-                                   McAccount             *account,
-                                   const gchar           *data,
-                                   gsize                  size,
-                                   const gchar           *mime_type)
-{
-       EmpathyTpContactFactory *tp_factory;
-
-       tp_factory = empathy_contact_factory_get_tp_factory (factory, account);
-
-       return empathy_tp_contact_factory_set_avatar (tp_factory,
-                                                     data, size, mime_type);
-}
-
-static void
-contact_factory_finalize (GObject *object)
-{
-       EmpathyContactFactoryPriv *priv = GET_PRIV (object);
-
-       g_hash_table_destroy (priv->accounts);
-
-       G_OBJECT_CLASS (empathy_contact_factory_parent_class)->finalize (object);
-}
-
-static GObject *
-contact_factory_constructor (GType type,
-                            guint n_props,
-                            GObjectConstructParam *props)
-{
-       GObject *retval;
-
-       if (factory_singleton) {
-               retval = g_object_ref (factory_singleton);
-       } else {
-               retval = G_OBJECT_CLASS (empathy_contact_factory_parent_class)->constructor
-                       (type, n_props, props);
-
-               factory_singleton = EMPATHY_CONTACT_FACTORY (retval);
-               g_object_add_weak_pointer (retval, (gpointer) &factory_singleton);
-       }
-
-       return retval;
-}
-
-static void
-empathy_contact_factory_class_init (EmpathyContactFactoryClass *klass)
-{
-       GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-       object_class->finalize = contact_factory_finalize;
-       object_class->constructor = contact_factory_constructor;
-
-       g_type_class_add_private (object_class, sizeof (EmpathyContactFactoryPriv));
-}
-
-static void
-empathy_contact_factory_init (EmpathyContactFactory *factory)
-{
-       EmpathyContactFactoryPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (factory,
-               EMPATHY_TYPE_CONTACT_FACTORY, EmpathyContactFactoryPriv);
-
-       factory->priv = priv;
-       priv->accounts = g_hash_table_new_full (empathy_account_hash,
-                                               empathy_account_equal,
-                                               g_object_unref,
-                                               g_object_unref);
-}
-
-EmpathyContactFactory *
-empathy_contact_factory_dup_singleton (void)
-{
-       return g_object_new (EMPATHY_TYPE_CONTACT_FACTORY, NULL);
-}
-
diff --git a/libempathy/empathy-contact-factory.h b/libempathy/empathy-contact-factory.h
deleted file mode 100644 (file)
index 16df02b..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Authors: Xavier Claessens <xclaesse@gmail.com>
- */
-
-#ifndef __EMPATHY_CONTACT_FACTORY_H__
-#define __EMPATHY_CONTACT_FACTORY_H__
-
-#include <glib.h>
-
-#include <libmissioncontrol/mc-account.h>
-
-#include "empathy-contact.h"
-#include "empathy-tp-contact-factory.h"
-
-G_BEGIN_DECLS
-
-#define EMPATHY_TYPE_CONTACT_FACTORY         (empathy_contact_factory_get_type ())
-#define EMPATHY_CONTACT_FACTORY(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_CONTACT_FACTORY, EmpathyContactFactory))
-#define EMPATHY_CONTACT_FACTORY_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), EMPATHY_TYPE_CONTACT_FACTORY, EmpathyContactFactoryClass))
-#define EMPATHY_IS_CONTACT_FACTORY(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_CONTACT_FACTORY))
-#define EMPATHY_IS_CONTACT_FACTORY_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_CONTACT_FACTORY))
-#define EMPATHY_CONTACT_FACTORY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_CONTACT_FACTORY, EmpathyContactFactoryClass))
-
-typedef struct _EmpathyContactFactory      EmpathyContactFactory;
-typedef struct _EmpathyContactFactoryClass EmpathyContactFactoryClass;
-
-struct _EmpathyContactFactory {
-       GObject parent;
-       gpointer priv;
-};
-
-struct _EmpathyContactFactoryClass {
-       GObjectClass parent_class;
-};
-
-GType                  empathy_contact_factory_get_type         (void) G_GNUC_CONST;
-EmpathyContactFactory *empathy_contact_factory_dup_singleton    (void);
-EmpathyTpContactFactory *empathy_contact_factory_get_tp_factory (EmpathyContactFactory *factory,
-                                                                McAccount             *account);
-EmpathyContact *       empathy_contact_factory_get_user         (EmpathyContactFactory *factory,
-                                                                McAccount             *account);
-EmpathyContact *       empathy_contact_factory_get_from_id      (EmpathyContactFactory *factory,
-                                                                McAccount             *account,
-                                                                const gchar           *id);
-EmpathyContact *       empathy_contact_factory_get_from_handle  (EmpathyContactFactory *factory,
-                                                                McAccount             *account,
-                                                                guint                  handle);
-GList *                empathy_contact_factory_get_from_handles (EmpathyContactFactory *factory,
-                                                                McAccount             *account,
-                                                                const GArray          *handles);
-void                   empathy_contact_factory_set_alias        (EmpathyContactFactory *factory,
-                                                                EmpathyContact        *contact,
-                                                                const gchar           *alias);
-void                   empathy_contact_factory_set_avatar       (EmpathyContactFactory *factory,
-                                                                McAccount             *account,
-                                                                const gchar           *data,
-                                                                gsize                  size,
-                                                                const gchar           *mime_type);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_CONTACT_FACTORY_H__ */
index 409f41c449625afa215c33015fd9eda341f02216..66c4514aff7748d7c001aca4048c7fbc3dccf358 100644 (file)
@@ -86,9 +86,6 @@ contact_manager_groups_changed_cb (EmpathyTpContactList  *list,
                               contact, group, is_member);
 }
 
-static void contact_manager_destroy_cb (EmpathyTpContactList  *list,
-                                       EmpathyContactManager *manager);
-
 static void
 contact_manager_disconnect_foreach (gpointer key,
                                    gpointer value,
@@ -107,75 +104,60 @@ contact_manager_disconnect_foreach (gpointer key,
        g_signal_handlers_disconnect_by_func (list,
                                              contact_manager_groups_changed_cb,
                                              manager);
-       g_signal_handlers_disconnect_by_func (list,
-                                             contact_manager_destroy_cb,
-                                             manager);
 }
 
 static void
-contact_manager_destroy_cb (EmpathyTpContactList  *list,
-                           EmpathyContactManager *manager)
+contact_manager_invalidated_cb (TpProxy *connection,
+                               guint    domain,
+                               gint     code,
+                               gchar   *message,
+                               EmpathyContactManager *manager)
 {
        EmpathyContactManagerPriv *priv = GET_PRIV (manager);
-       McAccount                 *account;
+       EmpathyTpContactList *list;
 
-       account = empathy_tp_contact_list_get_account (list);
+       DEBUG ("Removing connection: %s (%s)",
+               tp_proxy_get_object_path (TP_PROXY (connection)),
+               message);
 
-       DEBUG ("Removing account: %s", mc_account_get_display_name (account));
-
-       contact_manager_disconnect_foreach (account, list, manager);
-       g_hash_table_remove (priv->lists, account);
+       list = g_hash_table_lookup (priv->lists, connection);
+       if (list) {
+               empathy_tp_contact_list_remove_all (list);
+               g_hash_table_remove (priv->lists, connection);          
+       }
 }
 
 static void
-contact_manager_add_account (EmpathyContactManager *manager,
-                            McAccount             *account)
+contact_manager_new_connection_cb (EmpathyAccountManager *account_manager,
+                                  TpConnection *connection,
+                                  EmpathyContactManager *self)
 {
-       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+       EmpathyContactManagerPriv *priv = GET_PRIV (self);
        EmpathyTpContactList      *list;
 
-       if (g_hash_table_lookup (priv->lists, account)) {
+       if (g_hash_table_lookup (priv->lists, connection)) {
                return;
        }
 
-       DEBUG ("Adding new account: %s", mc_account_get_display_name (account));
-
-       list = empathy_tp_contact_list_new (account);
-       if (!list) {
-               return;
-       }
+       DEBUG ("Adding new connection: %s",
+               tp_proxy_get_object_path (TP_PROXY (connection)));
 
-       g_hash_table_insert (priv->lists, g_object_ref (account), list);
+       list = empathy_tp_contact_list_new (connection);
+       g_hash_table_insert (priv->lists, g_object_ref (connection), list);
+       g_signal_connect (connection, "invalidated",
+                         G_CALLBACK (contact_manager_invalidated_cb),
+                         self);
 
        /* Connect signals */
        g_signal_connect (list, "members-changed",
                          G_CALLBACK (contact_manager_members_changed_cb),
-                         manager);
+                         self);
        g_signal_connect (list, "pendings-changed",
                          G_CALLBACK (contact_manager_pendings_changed_cb),
-                         manager);
+                         self);
        g_signal_connect (list, "groups-changed",
                          G_CALLBACK (contact_manager_groups_changed_cb),
-                         manager);
-       g_signal_connect (list, "destroy",
-                         G_CALLBACK (contact_manager_destroy_cb),
-                         manager);
-}
-
-static void
-contact_manager_connection_changed_cb (EmpathyAccountManager *account_manager,
-                                      McAccount *account,
-                                      TpConnectionStatusReason  reason,
-                                      TpConnectionStatus current,
-                                      TpConnectionStatus previous,
-                                      EmpathyContactManager *manager)
-{
-       if (current != TP_CONNECTION_STATUS_CONNECTED) {
-               /* We only care about newly connected accounts */
-               return;
-       }
-
-       contact_manager_add_account (manager, account);
+                         self);
 }
 
 static void
@@ -189,7 +171,7 @@ contact_manager_finalize (GObject *object)
        g_hash_table_destroy (priv->lists);
 
        g_signal_handlers_disconnect_by_func (priv->account_manager,
-                                             contact_manager_connection_changed_cb,
+                                             contact_manager_new_connection_cb,
                                              object);
        g_object_unref (priv->account_manager);
 
@@ -232,34 +214,30 @@ empathy_contact_manager_class_init (EmpathyContactManagerClass *klass)
 static void
 empathy_contact_manager_init (EmpathyContactManager *manager)
 {
-       GSList                    *accounts, *l;
-       MissionControl            *mc;
+       GList *connections, *l;
        EmpathyContactManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
                EMPATHY_TYPE_CONTACT_MANAGER, EmpathyContactManagerPriv);
 
        manager->priv = priv;
-       priv->lists = g_hash_table_new_full (empathy_account_hash,
-                                            empathy_account_equal,
+       priv->lists = g_hash_table_new_full (empathy_proxy_hash,
+                                            empathy_proxy_equal,
                                             (GDestroyNotify) g_object_unref,
                                             (GDestroyNotify) g_object_unref);
        priv->account_manager = empathy_account_manager_dup_singleton ();
        priv->contact_monitor = NULL;
 
-       g_signal_connect (priv->account_manager,
-                         "account-connection-changed",
-                         G_CALLBACK (contact_manager_connection_changed_cb), manager);
-
-       mc = empathy_mission_control_dup_singleton ();
+       g_signal_connect (priv->account_manager, "new-connection",
+                         G_CALLBACK (contact_manager_new_connection_cb),
+                         manager);
 
        /* Get ContactList for existing connections */
-       accounts = mission_control_get_online_connections (mc, NULL);
-       for (l = accounts; l; l = l->next) {
-               contact_manager_add_account (manager, l->data);
+       connections = empathy_account_manager_dup_connections (priv->account_manager);
+       for (l = connections; l; l = l->next) {
+               contact_manager_new_connection_cb (priv->account_manager,
+                                                  l->data, manager);
                g_object_unref (l->data);
        }
-
-       g_slist_free (accounts);
-       g_object_unref (mc);
+       g_list_free (connections);
 }
 
 EmpathyContactManager *
@@ -270,14 +248,14 @@ empathy_contact_manager_dup_singleton (void)
 
 EmpathyTpContactList *
 empathy_contact_manager_get_list (EmpathyContactManager *manager,
-                                 McAccount             *account)
+                                 TpConnection          *connection)
 {
        EmpathyContactManagerPriv *priv = GET_PRIV (manager);
 
        g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
-       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+       g_return_val_if_fail (TP_IS_CONNECTION (connection), NULL);
 
-       return g_hash_table_lookup (priv->lists, account);
+       return g_hash_table_lookup (priv->lists, connection);
 }
 
 static void
@@ -287,12 +265,12 @@ contact_manager_add (EmpathyContactList *manager,
 {
        EmpathyContactManagerPriv *priv = GET_PRIV (manager);
        EmpathyContactList        *list;
-       McAccount                 *account;
+       TpConnection              *connection;
 
        g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
 
-       account = empathy_contact_get_account (contact);
-       list = g_hash_table_lookup (priv->lists, account);
+       connection = empathy_contact_get_connection (contact);
+       list = g_hash_table_lookup (priv->lists, connection);
 
        if (list) {
                empathy_contact_list_add (list, contact, message);
@@ -301,17 +279,17 @@ contact_manager_add (EmpathyContactList *manager,
 
 static void
 contact_manager_remove (EmpathyContactList *manager,
-                       EmpathyContact      *contact,
+                       EmpathyContact     *contact,
                        const gchar        *message)
 {
        EmpathyContactManagerPriv *priv = GET_PRIV (manager);
        EmpathyContactList        *list;
-       McAccount                 *account;
+       TpConnection              *connection;
 
        g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
 
-       account = empathy_contact_get_account (contact);
-       list = g_hash_table_lookup (priv->lists, account);
+       connection = empathy_contact_get_connection (contact);
+       list = g_hash_table_lookup (priv->lists, connection);
 
        if (list) {
                empathy_contact_list_remove (list, contact, message);
@@ -319,7 +297,7 @@ contact_manager_remove (EmpathyContactList *manager,
 }
 
 static void
-contact_manager_get_members_foreach (McAccount             *account,
+contact_manager_get_members_foreach (TpConnection          *connection,
                                     EmpathyTpContactList  *list,
                                     GList                **contacts)
 {
@@ -357,7 +335,7 @@ contact_manager_get_monitor (EmpathyContactList *manager)
 }
 
 static void
-contact_manager_get_pendings_foreach (McAccount             *account,
+contact_manager_get_pendings_foreach (TpConnection          *connection,
                                      EmpathyTpContactList  *list,
                                      GList                **contacts)
 {
@@ -383,7 +361,7 @@ contact_manager_get_pendings (EmpathyContactList *manager)
 }
 
 static void
-contact_manager_get_all_groups_foreach (McAccount             *account,
+contact_manager_get_all_groups_foreach (TpConnection          *connection,
                                        EmpathyTpContactList  *list,
                                        GList                **all_groups)
 {
@@ -424,12 +402,12 @@ contact_manager_get_groups (EmpathyContactList *manager,
 {
        EmpathyContactManagerPriv *priv = GET_PRIV (manager);
        EmpathyContactList        *list;
-       McAccount                 *account;
+       TpConnection              *connection;
 
        g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
 
-       account = empathy_contact_get_account (contact);
-       list = g_hash_table_lookup (priv->lists, account);
+       connection = empathy_contact_get_connection (contact);
+       list = g_hash_table_lookup (priv->lists, connection);
 
        if (list) {
                return empathy_contact_list_get_groups (list, contact);
@@ -445,12 +423,12 @@ contact_manager_add_to_group (EmpathyContactList *manager,
 {
        EmpathyContactManagerPriv *priv = GET_PRIV (manager);
        EmpathyContactList        *list;
-       McAccount                 *account;
+       TpConnection              *connection;
 
        g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
 
-       account = empathy_contact_get_account (contact);
-       list = g_hash_table_lookup (priv->lists, account);
+       connection = empathy_contact_get_connection (contact);
+       list = g_hash_table_lookup (priv->lists, connection);
 
        if (list) {
                empathy_contact_list_add_to_group (list, contact, group);
@@ -464,12 +442,12 @@ contact_manager_remove_from_group (EmpathyContactList *manager,
 {
        EmpathyContactManagerPriv *priv = GET_PRIV (manager);
        EmpathyContactList        *list;
-       McAccount                 *account;
+       TpConnection              *connection;
 
        g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
 
-       account = empathy_contact_get_account (contact);
-       list = g_hash_table_lookup (priv->lists, account);
+       connection = empathy_contact_get_connection (contact);
+       list = g_hash_table_lookup (priv->lists, connection);
 
        if (list) {
                empathy_contact_list_remove_from_group (list, contact, group);
@@ -482,7 +460,7 @@ typedef struct {
 } RenameGroupData;
 
 static void
-contact_manager_rename_group_foreach (McAccount            *account,
+contact_manager_rename_group_foreach (TpConnection         *connection,
                                      EmpathyTpContactList *list,
                                      RenameGroupData      *data)
 {
@@ -508,7 +486,7 @@ contact_manager_rename_group (EmpathyContactList *manager,
                              &data);
 }
 
-static void contact_manager_remove_group_foreach (McAccount    *account,
+static void contact_manager_remove_group_foreach (TpConnection         *connection,
                                                  EmpathyTpContactList *list,
                                                  const gchar *group)
 {
@@ -547,14 +525,14 @@ contact_manager_iface_init (EmpathyContactListIface *iface)
 
 gboolean
 empathy_contact_manager_can_add (EmpathyContactManager *manager,
-                                McAccount             *account)
+                                TpConnection          *connection)
 {
        EmpathyContactManagerPriv *priv = GET_PRIV (manager);
        EmpathyTpContactList      *list;
        
        g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), FALSE);
 
-       list = g_hash_table_lookup (priv->lists, account);
+       list = g_hash_table_lookup (priv->lists, connection);
        if (list == NULL)
                return FALSE;
 
index 57e8764e4a3d6d56671e410a84e6d3db56234b82..fbe9e2df01b58fffe41394204b03859308609e38 100644 (file)
@@ -24,8 +24,6 @@
 
 #include <glib.h>
 
-#include <libmissioncontrol/mc-account.h>
-
 #include "empathy-contact.h"
 #include "empathy-tp-contact-list.h"
 #include "empathy-contact-list.h"
@@ -54,9 +52,9 @@ struct _EmpathyContactManagerClass {
 GType                  empathy_contact_manager_get_type (void) G_GNUC_CONST;
 EmpathyContactManager *empathy_contact_manager_dup_singleton  (void);
 EmpathyTpContactList * empathy_contact_manager_get_list (EmpathyContactManager *manager,
-                                                        McAccount             *account);
+                                                        TpConnection          *connection);
 gboolean               empathy_contact_manager_can_add  (EmpathyContactManager *manager,
-                                                        McAccount             *account);
+                                                        TpConnection          *connection);
 
 G_END_DECLS
 
index 1cac48513d55969a89a2ef7a6c14ea85caef3346..fe8cf8234f5016d0c488f29cc63be694d2b3ab5f 100644 (file)
@@ -1,27 +1,22 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
 /*
- * Copyright (C) 2004 Imendio AB
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2009 Collabora Ltd.
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful,
+ * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * Authors: Mikael Hallendal <micke@imendio.com>
- *          Martyn Russell <martyn@imendio.com>
- *          Xavier Claessens <xclaesse@gmail.com>
- *          Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
  */
 
 #include "config.h"
@@ -34,7 +29,7 @@
 #include <libmissioncontrol/mc-enum-types.h>
 
 #include "empathy-contact.h"
-#include "empathy-contact-factory.h"
+#include "empathy-account-manager.h"
 #include "empathy-utils.h"
 #include "empathy-enum-types.h"
 #include "empathy-marshal.h"
 
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyContact)
 typedef struct {
-  EmpathyContactFactory *factory;
+  TpContact *tp_contact;
+  McAccount *account;
   gchar *id;
   gchar *name;
   EmpathyAvatar *avatar;
-  McAccount *account;
   McPresence presence;
   gchar *presence_message;
   guint handle;
   EmpathyCapabilities capabilities;
   gboolean is_user;
   guint hash;
-  EmpathyContactReady ready;
-  GList *ready_callbacks;
 } EmpathyContactPriv;
 
-typedef struct {
-    EmpathyContactReady ready;
-    EmpathyContactReadyCb *callback;
-    gpointer user_data;
-    GDestroyNotify destroy;
-    GObject *weak_object;
-} ReadyCbData;
-
 static void contact_finalize (GObject *object);
 static void contact_get_property (GObject *object, guint param_id,
     GValue *value, GParamSpec *pspec);
@@ -78,16 +63,16 @@ G_DEFINE_TYPE (EmpathyContact, empathy_contact, G_TYPE_OBJECT);
 enum
 {
   PROP_0,
+  PROP_TP_CONTACT,
+  PROP_ACCOUNT,
   PROP_ID,
   PROP_NAME,
   PROP_AVATAR,
-  PROP_ACCOUNT,
   PROP_PRESENCE,
   PROP_PRESENCE_MESSAGE,
   PROP_HANDLE,
   PROP_CAPABILITIES,
   PROP_IS_USER,
-  PROP_READY
 };
 
 enum {
@@ -97,19 +82,49 @@ enum {
 
 static guint signals[LAST_SIGNAL];
 
+static void
+tp_contact_notify_cb (TpContact *tp_contact,
+                      GParamSpec *param,
+                      GObject *contact)
+{
+  EmpathyContactPriv *priv = GET_PRIV (contact);
+
+  /* Forward property notifications */
+  if (!tp_strdiff (param->name, "alias"))
+    g_object_notify (contact, "name");
+  else if (!tp_strdiff (param->name, "presence-type")) {
+    McPresence presence;
+
+    presence = empathy_contact_get_presence (EMPATHY_CONTACT (contact));
+    g_signal_emit (contact, signals[PRESENCE_CHANGED], 0, presence, priv->presence);
+    priv->presence = presence;
+    g_object_notify (contact, "presence");
+  }
+  else if (!tp_strdiff (param->name, "presence-message"))
+    g_object_notify (contact, "presence-message");
+  else if (!tp_strdiff (param->name, "identifier"))
+    g_object_notify (contact, "id");
+  else if (!tp_strdiff (param->name, "handle"))
+    g_object_notify (contact, "handle");
+}
+
 static void
 contact_dispose (GObject *object)
 {
   EmpathyContactPriv *priv = GET_PRIV (object);
 
+  if (priv->tp_contact)
+    {
+      g_signal_handlers_disconnect_by_func (priv->tp_contact,
+          tp_contact_notify_cb, object);
+      g_object_unref (priv->tp_contact);
+    }
+  priv->tp_contact = NULL;
+
   if (priv->account)
     g_object_unref (priv->account);
   priv->account = NULL;
 
-  if (priv->factory)
-    g_object_unref (priv->factory);
-  priv->factory = NULL;
-
   G_OBJECT_CLASS (empathy_contact_parent_class)->dispose (object);
 }
 
@@ -125,13 +140,29 @@ empathy_contact_class_init (EmpathyContactClass *class)
   object_class->get_property = contact_get_property;
   object_class->set_property = contact_set_property;
 
+  g_object_class_install_property (object_class,
+      PROP_TP_CONTACT,
+      g_param_spec_object ("tp-contact",
+        "TpContact",
+        "The TpContact associated with the contact",
+        TP_TYPE_CONTACT,
+        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (object_class,
+      PROP_ACCOUNT,
+      g_param_spec_object ("account",
+        "The account",
+        "The account associated with the contact",
+        MC_TYPE_ACCOUNT,
+        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   g_object_class_install_property (object_class,
       PROP_ID,
       g_param_spec_string ("id",
         "Contact id",
         "String identifying contact",
         NULL,
-        G_PARAM_READWRITE));
+        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_class,
       PROP_NAME,
@@ -139,7 +170,7 @@ empathy_contact_class_init (EmpathyContactClass *class)
         "Contact Name",
         "The name of the contact",
         NULL,
-        G_PARAM_READWRITE));
+        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_class,
       PROP_AVATAR,
@@ -147,15 +178,7 @@ empathy_contact_class_init (EmpathyContactClass *class)
         "Avatar image",
         "The avatar image",
         EMPATHY_TYPE_AVATAR,
-        G_PARAM_READWRITE));
-
-  g_object_class_install_property (object_class,
-      PROP_ACCOUNT,
-      g_param_spec_object ("account",
-        "Contact Account",
-        "The account associated with the contact",
-        MC_TYPE_ACCOUNT,
-        G_PARAM_READWRITE));
+        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_class,
       PROP_PRESENCE,
@@ -165,7 +188,7 @@ empathy_contact_class_init (EmpathyContactClass *class)
         MC_PRESENCE_UNSET,
         LAST_MC_PRESENCE,
         MC_PRESENCE_UNSET,
-        G_PARAM_READWRITE));
+        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_class,
       PROP_PRESENCE_MESSAGE,
@@ -173,7 +196,7 @@ empathy_contact_class_init (EmpathyContactClass *class)
         "Contact presence message",
         "Presence message of contact",
         NULL,
-        G_PARAM_READWRITE));
+        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_class,
       PROP_HANDLE,
@@ -183,7 +206,7 @@ empathy_contact_class_init (EmpathyContactClass *class)
         0,
         G_MAXUINT,
         0,
-        G_PARAM_READWRITE));
+        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_class,
       PROP_CAPABILITIES,
@@ -192,7 +215,7 @@ empathy_contact_class_init (EmpathyContactClass *class)
         "Capabilities of the contact",
         EMPATHY_TYPE_CAPABILITIES,
         EMPATHY_CAPABILITIES_UNKNOWN,
-        G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+        G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_class,
       PROP_IS_USER,
@@ -200,16 +223,7 @@ empathy_contact_class_init (EmpathyContactClass *class)
         "Contact is-user",
         "Is contact the user",
         FALSE,
-        G_PARAM_READWRITE));
-
-  g_object_class_install_property (object_class,
-      PROP_READY,
-      g_param_spec_flags ("ready",
-        "Contact ready flags",
-        "Flags for ready properties",
-        EMPATHY_TYPE_CONTACT_READY,
-        EMPATHY_CONTACT_READY_NONE,
-        G_PARAM_READABLE));
+        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   signals[PRESENCE_CHANGED] =
     g_signal_new ("presence-changed",
@@ -232,17 +246,12 @@ empathy_contact_init (EmpathyContact *contact)
     EMPATHY_TYPE_CONTACT, EmpathyContactPriv);
 
   contact->priv = priv;
-
-  /* Keep a ref to the factory to be sure it is not finalized while there is
-   * still contacts alive. */
-  priv->factory = empathy_contact_factory_dup_singleton ();
 }
 
 static void
 contact_finalize (GObject *object)
 {
   EmpathyContactPriv *priv;
-  GList *l;
 
   priv = GET_PRIV (object);
 
@@ -252,66 +261,68 @@ contact_finalize (GObject *object)
   g_free (priv->id);
   g_free (priv->presence_message);
 
-  for (l = priv->ready_callbacks; l != NULL; l = g_list_next (l))
-    {
-      ReadyCbData *d = (ReadyCbData *)l->data;
-
-      if (d->destroy != NULL)
-        d->destroy (d->user_data);
-      g_slice_free (ReadyCbData, d);
-    }
-
-  g_list_free (priv->ready_callbacks);
-  priv->ready_callbacks = NULL;
-
   if (priv->avatar)
       empathy_avatar_unref (priv->avatar);
 
   G_OBJECT_CLASS (empathy_contact_parent_class)->finalize (object);
 }
 
+static void
+set_tp_contact (EmpathyContact *contact,
+                TpContact *tp_contact)
+{
+  EmpathyContactPriv *priv = GET_PRIV (contact);
+
+  if (tp_contact == NULL)
+    return;
+
+  g_assert (priv->tp_contact == NULL);
+  priv->tp_contact = g_object_ref (tp_contact);
+  priv->presence = empathy_contact_get_presence (contact);
+
+  g_signal_connect (priv->tp_contact, "notify",
+    G_CALLBACK (tp_contact_notify_cb), contact);
+}
+
 static void
 contact_get_property (GObject *object,
                       guint param_id,
                       GValue *value,
                       GParamSpec *pspec)
 {
-  EmpathyContactPriv *priv;
-
-  priv = GET_PRIV (object);
+  EmpathyContact *contact = EMPATHY_CONTACT (object);
 
   switch (param_id)
     {
+      case PROP_TP_CONTACT:
+        g_value_set_object (value, empathy_contact_get_tp_contact (contact));
+        break;
+      case PROP_ACCOUNT:
+        g_value_set_object (value, empathy_contact_get_account (contact));
+        break;
       case PROP_ID:
-        g_value_set_string (value, priv->id);
+        g_value_set_string (value, empathy_contact_get_id (contact));
         break;
       case PROP_NAME:
-        g_value_set_string (value,
-            empathy_contact_get_name (EMPATHY_CONTACT (object)));
+        g_value_set_string (value, empathy_contact_get_name (contact));
         break;
       case PROP_AVATAR:
-        g_value_set_boxed (value, priv->avatar);
-        break;
-      case PROP_ACCOUNT:
-        g_value_set_object (value, priv->account);
+        g_value_set_boxed (value, empathy_contact_get_avatar (contact));
         break;
       case PROP_PRESENCE:
-        g_value_set_uint (value, priv->presence);
+        g_value_set_uint (value, empathy_contact_get_presence (contact));
         break;
       case PROP_PRESENCE_MESSAGE:
-        g_value_set_string (value, priv->presence_message);
+        g_value_set_string (value, empathy_contact_get_presence_message (contact));
         break;
       case PROP_HANDLE:
-        g_value_set_uint (value, priv->handle);
+        g_value_set_uint (value, empathy_contact_get_handle (contact));
         break;
       case PROP_CAPABILITIES:
-        g_value_set_flags (value, priv->capabilities);
+        g_value_set_flags (value, empathy_contact_get_capabilities (contact));
         break;
       case PROP_IS_USER:
-        g_value_set_boolean (value, priv->is_user);
-        break;
-      case PROP_READY:
-        g_value_set_flags (value, priv->ready);
+        g_value_set_boolean (value, empathy_contact_is_user (contact));
         break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -325,47 +336,41 @@ contact_set_property (GObject *object,
                       const GValue *value,
                       GParamSpec *pspec)
 {
-  EmpathyContactPriv *priv;
-
-  priv = GET_PRIV (object);
+  EmpathyContact *contact = EMPATHY_CONTACT (object);
+  EmpathyContactPriv *priv = GET_PRIV (object);
 
   switch (param_id)
     {
+      case PROP_TP_CONTACT:
+        set_tp_contact (contact, g_value_get_object (value));
+        break;
+      case PROP_ACCOUNT:
+        g_assert (priv->account == NULL);
+        priv->account = g_value_dup_object (value);
+        break;
       case PROP_ID:
-        empathy_contact_set_id (EMPATHY_CONTACT (object),
-        g_value_get_string (value));
+        empathy_contact_set_id (contact, g_value_get_string (value));
         break;
       case PROP_NAME:
-        empathy_contact_set_name (EMPATHY_CONTACT (object),
-        g_value_get_string (value));
+        empathy_contact_set_name (contact, g_value_get_string (value));
         break;
       case PROP_AVATAR:
-        empathy_contact_set_avatar (EMPATHY_CONTACT (object),
-        g_value_get_boxed (value));
-        break;
-      case PROP_ACCOUNT:
-        empathy_contact_set_account (EMPATHY_CONTACT (object),
-        MC_ACCOUNT (g_value_get_object (value)));
+        empathy_contact_set_avatar (contact, g_value_get_boxed (value));
         break;
       case PROP_PRESENCE:
-        empathy_contact_set_presence (EMPATHY_CONTACT (object),
-        g_value_get_uint (value));
+        empathy_contact_set_presence (contact, g_value_get_uint (value));
         break;
       case PROP_PRESENCE_MESSAGE:
-        empathy_contact_set_presence_message (EMPATHY_CONTACT (object),
-        g_value_get_string (value));
+        empathy_contact_set_presence_message (contact, g_value_get_string (value));
         break;
       case PROP_HANDLE:
-        empathy_contact_set_handle (EMPATHY_CONTACT (object),
-        g_value_get_uint (value));
+        empathy_contact_set_handle (contact, g_value_get_uint (value));
         break;
       case PROP_CAPABILITIES:
-        empathy_contact_set_capabilities (EMPATHY_CONTACT (object),
-        g_value_get_flags (value));
+        empathy_contact_set_capabilities (contact, g_value_get_flags (value));
         break;
       case PROP_IS_USER:
-        empathy_contact_set_is_user (EMPATHY_CONTACT (object),
-        g_value_get_boolean (value));
+        empathy_contact_set_is_user (contact, g_value_get_boolean (value));
         break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -373,120 +378,43 @@ contact_set_property (GObject *object,
     };
 }
 
-static gboolean
-contact_is_ready (EmpathyContact *contact, EmpathyContactReady ready)
-{
-  EmpathyContactPriv *priv = GET_PRIV (contact);
-
-  /* When the name is NULL, empathy_contact_get_name() fallback to the id.
-   * When the caller want to wait the name to be ready, it also want to wait
-   * the id to be ready in case of fallback. */
-  if ((ready & EMPATHY_CONTACT_READY_NAME) && EMP_STR_EMPTY (priv->name))
-      ready |= EMPATHY_CONTACT_READY_ID;
-
-  return (priv->ready & ready) == ready;
-}
-
-static void
-contact_weak_object_notify (gpointer data, GObject *old_object)
-{
-  EmpathyContact *contact = EMPATHY_CONTACT (data);
-  EmpathyContactPriv *priv = GET_PRIV (contact);
-
-  GList *l, *ln;
-
-  for (l = priv->ready_callbacks ; l != NULL ; l = ln )
-    {
-      ReadyCbData *d = (ReadyCbData *)l->data;
-      ln = g_list_next (l);
-
-      if (d->weak_object == old_object)
-        {
-          if (d->destroy != NULL)
-            d->destroy (d->user_data);
-
-          priv->ready_callbacks = g_list_delete_link (priv->ready_callbacks,
-            l);
-
-          g_slice_free (ReadyCbData, d);
-        }
-    }
-}
-
-static void
-contact_call_ready_callback (EmpathyContact *contact, const GError *error,
-  ReadyCbData *data)
-{
-  data->callback (contact, error, data->user_data, data->weak_object);
-  if (data->destroy != NULL)
-    data->destroy (data->user_data);
-
-  if (data->weak_object)
-    g_object_weak_unref (data->weak_object,
-      contact_weak_object_notify, contact);
-}
-
-
-static void
-contact_set_ready_flag (EmpathyContact *contact,
-                        EmpathyContactReady flag)
-{
-  EmpathyContactPriv *priv = GET_PRIV (contact);
-
-  if (!(priv->ready & flag))
-    {
-      GList *l, *ln;
-
-      priv->ready |= flag;
-      g_object_notify (G_OBJECT (contact), "ready");
-
-      for (l = priv->ready_callbacks ; l != NULL ; l = ln )
-        {
-          ReadyCbData *d = (ReadyCbData *)l->data;
-          ln = g_list_next (l);
-
-          if (contact_is_ready (contact, d->ready))
-            {
-              contact_call_ready_callback (contact, NULL, d);
-              priv->ready_callbacks = g_list_delete_link
-                (priv->ready_callbacks, l);
-              g_slice_free (ReadyCbData, d);
-            }
-        }
-    }
-}
-
-static void
-contact_remove_ready_flag (EmpathyContact *contact,
-                           EmpathyContactReady flag)
+EmpathyContact *
+empathy_contact_new (TpContact *tp_contact)
 {
-  EmpathyContactPriv *priv = GET_PRIV (contact);
+  g_return_val_if_fail (TP_IS_CONTACT (tp_contact), NULL);
 
-  if (priv->ready & flag)
-    {
-      priv->ready ^= flag;
-      g_object_notify (G_OBJECT (contact), "ready");
-    }
+  return g_object_new (EMPATHY_TYPE_CONTACT,
+      "tp-contact", tp_contact,
+      NULL);
 }
 
 EmpathyContact *
-empathy_contact_new (McAccount *account)
+empathy_contact_new_for_log (McAccount *account,
+                             const gchar *id,
+                             const gchar *name,
+                             gboolean is_user)
 {
+  g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+  g_return_val_if_fail (id != NULL, NULL);
+
   return g_object_new (EMPATHY_TYPE_CONTACT,
       "account", account,
+      "id", id,
+      "name", name,
+      "is-user", is_user,
       NULL);
 }
 
-EmpathyContact *
-empathy_contact_new_full (McAccount  *account,
-                          const gchar *id,
-                          const gchar *name)
+TpContact *
+empathy_contact_get_tp_contact (EmpathyContact *contact)
 {
-  return g_object_new (EMPATHY_TYPE_CONTACT,
-      "account", account,
-       "name", name,
-       "id", id,
-       NULL);
+  EmpathyContactPriv *priv;
+
+  g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+  priv = GET_PRIV (contact);
+
+  return priv->tp_contact;
 }
 
 const gchar *
@@ -498,6 +426,9 @@ empathy_contact_get_id (EmpathyContact *contact)
 
   priv = GET_PRIV (contact);
 
+  if (priv->tp_contact != NULL)
+    return tp_contact_get_identifier (priv->tp_contact);
+
   return priv->id;
 }
 
@@ -524,7 +455,6 @@ empathy_contact_set_id (EmpathyContact *contact,
       if (EMP_STR_EMPTY (priv->name))
           g_object_notify (G_OBJECT (contact), "name");
     }
-  contact_set_ready_flag (contact, EMPATHY_CONTACT_READY_ID);
 
   g_object_unref (contact);
 }
@@ -538,6 +468,9 @@ empathy_contact_get_name (EmpathyContact *contact)
 
   priv = GET_PRIV (contact);
 
+  if (priv->tp_contact != NULL)
+    return tp_contact_get_alias (priv->tp_contact);
+
   if (EMP_STR_EMPTY (priv->name))
       return empathy_contact_get_id (contact);
 
@@ -561,7 +494,6 @@ empathy_contact_set_name (EmpathyContact *contact,
       priv->name = g_strdup (name);
       g_object_notify (G_OBJECT (contact), "name");
     }
-  contact_set_ready_flag (contact, EMPATHY_CONTACT_READY_NAME);
   g_object_unref (contact);
 }
 
@@ -611,28 +543,61 @@ empathy_contact_get_account (EmpathyContact *contact)
 
   priv = GET_PRIV (contact);
 
+  if (priv->account == NULL && priv->tp_contact != NULL)
+    {
+      EmpathyAccountManager *manager;
+      TpConnection *connection;
+
+      /* FIXME: This assume the account manager already exists */
+      manager = empathy_account_manager_dup_singleton ();
+      connection = tp_contact_get_connection (priv->tp_contact);
+      priv->account = empathy_account_manager_get_account (manager, connection);
+      g_object_ref (priv->account);
+      g_object_unref (manager);
+    }
+
   return priv->account;
 }
 
-void
-empathy_contact_set_account (EmpathyContact *contact,
-                             McAccount *account)
+TpConnection *
+empathy_contact_get_connection (EmpathyContact *contact)
 {
   EmpathyContactPriv *priv;
 
-  g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-  g_return_if_fail (MC_IS_ACCOUNT (account));
+  g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
 
   priv = GET_PRIV (contact);
 
-  if (account == priv->account)
-    return;
+  if (priv->tp_contact != NULL)
+    return tp_contact_get_connection (priv->tp_contact);
 
-  if (priv->account)
-      g_object_unref (priv->account);
-  priv->account = g_object_ref (account);
+  return NULL;
+}
+
+static McPresence
+presence_type_to_mc_presence (TpConnectionPresenceType type)
+{
+  switch (type)
+    {
+      case TP_CONNECTION_PRESENCE_TYPE_UNSET:
+      case TP_CONNECTION_PRESENCE_TYPE_UNKNOWN:
+      case TP_CONNECTION_PRESENCE_TYPE_ERROR:
+        return MC_PRESENCE_UNSET;
+      case TP_CONNECTION_PRESENCE_TYPE_OFFLINE:
+        return MC_PRESENCE_OFFLINE;
+      case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE:
+        return MC_PRESENCE_AVAILABLE;
+      case TP_CONNECTION_PRESENCE_TYPE_AWAY:
+        return MC_PRESENCE_AWAY;
+      case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY:
+        return MC_PRESENCE_EXTENDED_AWAY;
+      case TP_CONNECTION_PRESENCE_TYPE_HIDDEN:
+        return MC_PRESENCE_HIDDEN;
+      case TP_CONNECTION_PRESENCE_TYPE_BUSY:
+        return MC_PRESENCE_DO_NOT_DISTURB;
+    }
 
-  g_object_notify (G_OBJECT (contact), "account");
+  return MC_PRESENCE_UNSET;
 }
 
 McPresence
@@ -644,6 +609,10 @@ empathy_contact_get_presence (EmpathyContact *contact)
 
   priv = GET_PRIV (contact);
 
+  if (priv->tp_contact != NULL)
+    return presence_type_to_mc_presence (tp_contact_get_presence_type (
+        priv->tp_contact));
+
   return priv->presence;
 }
 
@@ -678,6 +647,9 @@ empathy_contact_get_presence_message (EmpathyContact *contact)
 
   priv = GET_PRIV (contact);
 
+  if (priv->tp_contact != NULL)
+    return tp_contact_get_presence_message (priv->tp_contact);
+
   return priv->presence_message;
 }
 
@@ -707,6 +679,9 @@ empathy_contact_get_handle (EmpathyContact *contact)
 
   priv = GET_PRIV (contact);
 
+  if (priv->tp_contact != NULL)
+    return tp_contact_get_handle (priv->tp_contact);
+
   return priv->handle;
 }
 
@@ -726,12 +701,6 @@ empathy_contact_set_handle (EmpathyContact *contact,
       priv->handle = handle;
       g_object_notify (G_OBJECT (contact), "handle");
     }
-
-  if (handle != 0)
-    contact_set_ready_flag (contact, EMPATHY_CONTACT_READY_HANDLE);
-  else
-    contact_remove_ready_flag (contact, EMPATHY_CONTACT_READY_HANDLE);
-
   g_object_unref (contact);
 }
 
@@ -798,28 +767,24 @@ empathy_contact_set_is_user (EmpathyContact *contact,
 gboolean
 empathy_contact_is_online (EmpathyContact *contact)
 {
-  EmpathyContactPriv *priv;
-
   g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
 
-  priv = GET_PRIV (contact);
-
-  return (priv->presence > MC_PRESENCE_OFFLINE);
+  return (empathy_contact_get_presence (contact) > MC_PRESENCE_OFFLINE);
 }
 
 const gchar *
 empathy_contact_get_status (EmpathyContact *contact)
 {
-  EmpathyContactPriv *priv;
+  const gchar *message;
 
   g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), "");
 
-  priv = GET_PRIV (contact);
-
-  if (priv->presence_message)
-    return priv->presence_message;
+  message = empathy_contact_get_presence_message (contact);
+  if (!EMP_STR_EMPTY (message))
+    return message;
 
-  return empathy_presence_get_default_message (priv->presence);
+  return empathy_presence_get_default_message (
+      empathy_contact_get_presence (contact));
 }
 
 gboolean
@@ -847,112 +812,12 @@ empathy_contact_can_send_files (EmpathyContact *contact)
   return priv->capabilities & EMPATHY_CAPABILITIES_FT;
 }
 
-EmpathyContactReady
-empathy_contact_get_ready (EmpathyContact *contact)
-{
-  EmpathyContactPriv *priv;
-
-  g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
-
-  priv = GET_PRIV (contact);
-
-  return priv->ready;
-}
-
-gboolean
-empathy_contact_equal (gconstpointer v1,
-                       gconstpointer v2)
-{
-  McAccount *account_a;
-  McAccount *account_b;
-  const gchar *id_a;
-  const gchar *id_b;
-
-  g_return_val_if_fail (EMPATHY_IS_CONTACT (v1), FALSE);
-  g_return_val_if_fail (EMPATHY_IS_CONTACT (v2), FALSE);
-
-  account_a = empathy_contact_get_account (EMPATHY_CONTACT (v1));
-  account_b = empathy_contact_get_account (EMPATHY_CONTACT (v2));
-
-  id_a = empathy_contact_get_id (EMPATHY_CONTACT (v1));
-  id_b = empathy_contact_get_id (EMPATHY_CONTACT (v2));
-
-  return empathy_account_equal (account_a, account_b) &&
-      !tp_strdiff (id_a, id_b);
-}
-
-guint
-empathy_contact_hash (gconstpointer key)
-{
-  EmpathyContactPriv *priv;
-
-  g_return_val_if_fail (EMPATHY_IS_CONTACT (key), +1);
-
-  priv = GET_PRIV (EMPATHY_CONTACT (key));
-
-  if (priv->hash == 0)
-    {
-      priv->hash = empathy_account_hash (priv->account) ^
-          g_str_hash (priv->id);
-    }
-
-  return priv->hash;
-}
-
-void empathy_contact_call_when_ready (EmpathyContact *contact,
-  EmpathyContactReady ready, EmpathyContactReadyCb *callback,
-  gpointer user_data, GDestroyNotify destroy, GObject *weak_object)
-{
-  EmpathyContactPriv *priv = GET_PRIV (contact);
-
-  g_return_if_fail (contact != NULL);
-  g_return_if_fail (callback != NULL);
-
-  if (contact_is_ready (contact, ready))
-    {
-      callback (contact, NULL, user_data, weak_object);
-      if (destroy != NULL)
-        destroy (user_data);
-    }
-  else
-    {
-      ReadyCbData *d = g_slice_new0 (ReadyCbData);
-      d->ready = ready;
-      d->callback = callback;
-      d->user_data = user_data;
-      d->destroy = destroy;
-      d->weak_object = weak_object;
-
-      if (weak_object != NULL)
-        g_object_weak_ref (weak_object, contact_weak_object_notify, contact);
-
-      priv->ready_callbacks = g_list_prepend (priv->ready_callbacks, d);
-    }
-}
-
-static gboolean
-contact_is_ready_func (GObject *contact,
-                       gpointer user_data)
-{
-  return contact_is_ready (EMPATHY_CONTACT (contact),
-    GPOINTER_TO_UINT (user_data));
-}
-
-void
-empathy_contact_run_until_ready (EmpathyContact *contact,
-                                 EmpathyContactReady ready,
-                                 GMainLoop **loop)
-{
-  empathy_run_until_ready_full (contact, "notify::ready",
-      contact_is_ready_func, GUINT_TO_POINTER (ready),
-      loop);
-}
-
 static gchar *
 contact_get_avatar_filename (EmpathyContact *contact,
                              const gchar *token)
 {
   EmpathyContactPriv *priv = GET_PRIV (contact);
+  McAccount *account;
   gchar *avatar_path;
   gchar *avatar_file;
   gchar *token_escaped;
@@ -963,11 +828,13 @@ contact_get_avatar_filename (EmpathyContact *contact,
 
   contact_escaped = tp_escape_as_identifier (priv->id);
   token_escaped = tp_escape_as_identifier (token);
+  account = empathy_contact_get_account (contact);
 
+  /* FIXME: Do not use the account, but proto/cm instead */
   avatar_path = g_build_filename (g_get_user_cache_dir (),
       PACKAGE_NAME,
       "avatars",
-      mc_account_get_unique_name (priv->account),
+      mc_account_get_unique_name (account),
       contact_escaped,
       NULL);
   g_mkdir_with_parents (avatar_path, 0700);
index 52c969f6163838ff03ec3e8b1e49a4a2f0401a01..c10561d0f479e04ea5bf33c13c82e269c2d32f98 100644 (file)
@@ -1,26 +1,22 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * Copyright (C) 2004 Imendio AB
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2009 Collabora Ltd.
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful,
+ * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * Authors: Mikael Hallendal <micke@imendio.com>
- *          Martyn Russell <martyn@imendio.com>
- *          Xavier Claessens <xclaesse@gmail.com>
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
  */
 
 #ifndef __EMPATHY_CONTACT_H__
@@ -28,8 +24,8 @@
 
 #include <glib-object.h>
 
+#include <telepathy-glib/contact.h>
 #include <libmissioncontrol/mc-account.h>
-#include <libmissioncontrol/mission-control.h>
 
 G_BEGIN_DECLS
 
@@ -70,18 +66,11 @@ typedef enum {
   EMPATHY_CAPABILITIES_UNKNOWN = 1 << 7
 } EmpathyCapabilities;
 
-typedef enum {
-  EMPATHY_CONTACT_READY_NONE = 0,
-  EMPATHY_CONTACT_READY_ID = 1 << 0,
-  EMPATHY_CONTACT_READY_HANDLE = 1 << 1,
-  EMPATHY_CONTACT_READY_NAME = 1 << 2,
-  EMPATHY_CONTACT_READY_ALL = (1 << 3) - 1,
-} EmpathyContactReady;
-
 GType empathy_contact_get_type (void) G_GNUC_CONST;
-EmpathyContact * empathy_contact_new (McAccount *account);
-EmpathyContact * empathy_contact_new_full (McAccount *account, const gchar *id,
-    const gchar *name);
+EmpathyContact * empathy_contact_new (TpContact *tp_contact);
+EmpathyContact * empathy_contact_new_for_log (McAccount *account,
+    const gchar *id, const gchar *name, gboolean is_user);
+TpContact * empathy_contact_get_tp_contact (EmpathyContact *contact);
 const gchar * empathy_contact_get_id (EmpathyContact *contact);
 void empathy_contact_set_id (EmpathyContact *contact, const gchar *id);
 const gchar * empathy_contact_get_name (EmpathyContact *contact);
@@ -90,7 +79,7 @@ EmpathyAvatar * empathy_contact_get_avatar (EmpathyContact *contact);
 void empathy_contact_set_avatar (EmpathyContact *contact,
     EmpathyAvatar *avatar);
 McAccount * empathy_contact_get_account (EmpathyContact *contact);
-void empathy_contact_set_account (EmpathyContact *contact, McAccount *account);
+TpConnection * empathy_contact_get_connection (EmpathyContact *contact);
 McPresence empathy_contact_get_presence (EmpathyContact *contact);
 void empathy_contact_set_presence (EmpathyContact *contact,
     McPresence presence);
@@ -102,7 +91,6 @@ void empathy_contact_set_handle (EmpathyContact *contact, guint handle);
 EmpathyCapabilities empathy_contact_get_capabilities (EmpathyContact *contact);
 void empathy_contact_set_capabilities (EmpathyContact *contact,
     EmpathyCapabilities capabilities);
-EmpathyContactReady empathy_contact_get_ready (EmpathyContact *contact);
 gboolean empathy_contact_is_user (EmpathyContact *contact);
 void empathy_contact_set_is_user (EmpathyContact *contact,
     gboolean is_user);
@@ -110,19 +98,8 @@ gboolean empathy_contact_is_online (EmpathyContact *contact);
 const gchar * empathy_contact_get_status (EmpathyContact *contact);
 gboolean empathy_contact_can_voip (EmpathyContact *contact);
 gboolean empathy_contact_can_send_files (EmpathyContact *contact);
-gboolean empathy_contact_equal (gconstpointer v1, gconstpointer v2);
 guint empathy_contact_hash (gconstpointer key);
 
-typedef void (EmpathyContactReadyCb)
-  (EmpathyContact *contact, const GError *error, gpointer user_data,
-   GObject *weak_object);
-void empathy_contact_call_when_ready (EmpathyContact *contact,
-  EmpathyContactReady ready, EmpathyContactReadyCb *callback, gpointer
-  user_data, GDestroyNotify destroy, GObject *weak_object);
-
-void empathy_contact_run_until_ready (EmpathyContact *contact,
-    EmpathyContactReady ready, GMainLoop **loop);
-
 void empathy_contact_load_avatar_data (EmpathyContact *contact,
     const guchar *data, const gsize len, const gchar *format,
     const gchar *token);
index 1786e4169039c37a110ea3116c26613ef4782a91..cfe1111819baa5e28b86a848295c6e323d2d0c63 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "empathy-dispatch-operation.h"
 #include <libempathy/empathy-enum-types.h>
+#include <libempathy/empathy-tp-contact-factory.h>
 #include <libempathy/empathy-tp-chat.h>
 #include <libempathy/empathy-tp-call.h>
 #include <libempathy/empathy-tp-file.h>
@@ -172,11 +173,38 @@ empathy_dispatch_operation_invalidated (TpProxy *proxy, guint domain,
   g_signal_emit (self, signals[INVALIDATED], 0, domain, code, message);
 }
 
+static void
+dispatcher_operation_got_contact_cb (EmpathyTpContactFactory *factory,
+                                     EmpathyContact *contact,
+                                     const GError *error,
+                                     gpointer user_data,
+                                     GObject *self)
+{
+  EmpathyDispatchOperationPriv *priv = GET_PRIV (self);
+
+  if (error)
+    {
+      /* FIXME: We should cancel the operation */
+      DEBUG ("Error: %s", error->message);
+      return;
+    }
+
+  if (priv->contact != NULL)
+    g_object_unref (priv->contact);
+  priv->contact = g_object_ref (contact);
+  g_object_notify (G_OBJECT (self), "contact");
+
+  tp_channel_call_when_ready (priv->channel,
+    empathy_dispatch_operation_channel_ready_cb, self);
+}
+
 static void
 empathy_dispatch_operation_constructed (GObject *object)
 {
   EmpathyDispatchOperation *self = EMPATHY_DISPATCH_OPERATION (object);
   EmpathyDispatchOperationPriv *priv = GET_PRIV (self);
+  TpHandle handle;
+  TpHandleType handle_type;
 
   empathy_dispatch_operation_set_status (self,
     EMPATHY_DISPATCHER_OPERATION_STATE_PREPARING);
@@ -185,6 +213,19 @@ empathy_dispatch_operation_constructed (GObject *object)
     g_signal_connect (priv->channel, "invalidated",
       G_CALLBACK (empathy_dispatch_operation_invalidated), self);
 
+  handle = tp_channel_get_handle (priv->channel, &handle_type);
+
+  if (handle_type == TP_CONN_HANDLE_TYPE_CONTACT && priv->contact == NULL)
+    {
+      EmpathyTpContactFactory *factory;
+
+      factory = empathy_tp_contact_factory_dup_singleton (priv->connection);
+      empathy_tp_contact_factory_get_from_handle (factory, handle,
+       dispatcher_operation_got_contact_cb, NULL, NULL, object);
+      g_object_unref (factory);
+      return;
+    }
+
   tp_channel_call_when_ready (priv->channel,
     empathy_dispatch_operation_channel_ready_cb, self);
 }
@@ -364,6 +405,23 @@ empathy_dispatcher_operation_tp_chat_ready_cb (GObject *object,
     EMPATHY_DISPATCHER_OPERATION_STATE_PENDING);
 }
 
+static void
+empathy_dispatcher_operation_tp_file_ready_cb (GObject *object,
+  GParamSpec *spec, gpointer user_data)
+{
+  EmpathyDispatchOperation *self = EMPATHY_DISPATCH_OPERATION (user_data);
+  EmpathyDispatchOperationPriv *priv = GET_PRIV (self);
+
+  if (!empathy_tp_file_is_ready (EMPATHY_TP_FILE (priv->channel_wrapper)))
+    return;
+
+  g_signal_handler_disconnect (priv->channel_wrapper, priv->ready_handler);
+  priv->ready_handler = 0;
+
+  empathy_dispatch_operation_set_status (self,
+    EMPATHY_DISPATCHER_OPERATION_STATE_PENDING);
+}
+
 static void
 empathy_dispatch_operation_channel_ready_cb (TpChannel *channel,
   const GError *error, gpointer user_data)
@@ -395,18 +453,23 @@ empathy_dispatch_operation_channel_ready_cb (TpChannel *channel,
             G_CALLBACK (empathy_dispatcher_operation_tp_chat_ready_cb), self);
           return;
         }
-
     }
   else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA)
     {
-       EmpathyTpCall *call = empathy_tp_call_new (channel);
-       priv->channel_wrapper = G_OBJECT (call);
-
+      EmpathyTpCall *call = empathy_tp_call_new (channel);
+      priv->channel_wrapper = G_OBJECT (call);
     }
   else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER)
     {
-       EmpathyTpFile *file = empathy_tp_file_new (channel);
-       priv->channel_wrapper = G_OBJECT (file);
+      EmpathyTpFile *file = empathy_tp_file_new (channel);
+      priv->channel_wrapper = G_OBJECT (file);
+
+      if (!empathy_tp_file_is_ready (file))
+        {
+          priv->ready_handler = g_signal_connect (file, "notify::ready",
+            G_CALLBACK (empathy_dispatcher_operation_tp_file_ready_cb), self);
+          return;
+        }
     }
 
 ready:
@@ -524,7 +587,7 @@ empathy_dispatch_operation_get_tp_connection (
 
   priv = GET_PRIV (operation);
 
-  return g_object_ref (priv->connection);
+  return priv->connection;
 }
 
 TpChannel *
index 12c7da96730187ee9a038697900bc70a8cedddce..c8a0f9e60b043e5effd618a6ab3d71930267c841 100644 (file)
@@ -31,7 +31,6 @@
 #include <telepathy-glib/gtypes.h>
 
 #include <libmissioncontrol/mission-control.h>
-#include <libmissioncontrol/mc-account.h>
 
 #include <extensions/extensions.h>
 
@@ -39,7 +38,7 @@
 #include "empathy-utils.h"
 #include "empathy-tube-handler.h"
 #include "empathy-account-manager.h"
-#include "empathy-contact-factory.h"
+#include "empathy-tp-contact-factory.h"
 #include "empathy-tp-file.h"
 #include "empathy-chatroom-manager.h"
 #include "empathy-utils.h"
@@ -54,8 +53,6 @@ typedef struct
   MissionControl *mc;
   /* connection to connection data mapping */
   GHashTable *connections;
-  /* accounts to connection mapping */
-  GHashTable *accounts;
   gpointer token;
   GSList *tubes;
 
@@ -102,7 +99,6 @@ typedef struct
 
 typedef struct
 {
-  McAccount *account;
   /* ObjectPath => DispatchData.. */
   GHashTable *dispatched_channels;
   /* ObjectPath -> EmpathyDispatchOperations */
@@ -185,10 +181,9 @@ free_dispatcher_request_data (DispatcherRequestData *r)
 }
 
 static ConnectionData *
-new_connection_data (McAccount *account)
+new_connection_data (void)
 {
   ConnectionData *cd = g_slice_new0 (ConnectionData);
-  cd->account = g_object_ref (account);
 
   cd->dispatched_channels = g_hash_table_new_full (g_str_hash, g_str_equal,
       g_free, (GDestroyNotify) free_dispatch_data);
@@ -206,7 +201,7 @@ static void
 free_connection_data (ConnectionData *cd)
 {
   GList *l;
-  g_object_unref (cd->account);
+
   g_hash_table_destroy (cd->dispatched_channels);
   g_hash_table_destroy (cd->dispatching_channels);
   int i;
@@ -233,12 +228,8 @@ dispatcher_connection_invalidated_cb (TpConnection *connection,
                                       EmpathyDispatcher *dispatcher)
 {
   EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher);
-  ConnectionData *cd;
 
   DEBUG ("Error: %s", message);
-  cd = g_hash_table_lookup (priv->connections, connection);
-
-  g_hash_table_remove (priv->accounts, cd->account);
   g_hash_table_remove (priv->connections, connection);
 }
 
@@ -362,7 +353,6 @@ dispatch_operation_claimed_cb (EmpathyDispatchOperation *operation,
   connection = empathy_dispatch_operation_get_tp_connection (operation);
   cd = g_hash_table_lookup (priv->connections, connection);
   g_assert (cd != NULL);
-  g_object_unref (G_OBJECT (connection));
 
   object_path = empathy_dispatch_operation_get_object_path (operation);
 
@@ -406,7 +396,6 @@ dispatch_operation_ready_cb (EmpathyDispatchOperation *operation,
   connection =  empathy_dispatch_operation_get_tp_connection (operation);
   cd = g_hash_table_lookup (priv->connections, connection);
   g_assert (cd != NULL);
-  g_object_unref (G_OBJECT (connection));
 
   g_object_ref (operation);
   g_object_ref (dispatcher);
@@ -511,7 +500,6 @@ dispatcher_connection_new_channel (EmpathyDispatcher *dispatcher,
   TpChannel         *channel;
   ConnectionData *cd;
   EmpathyDispatchOperation *operation;
-  EmpathyContact *contact = NULL;
   int i;
   /* Channel types we never want to dispatch because they're either deprecated
    * or can't sensibly be dispatch (e.g. channels that should always be
@@ -575,15 +563,7 @@ dispatcher_connection_new_channel (EmpathyDispatcher *dispatcher,
 
   priv->channels = g_list_prepend (priv->channels, channel);
 
-  if (handle_type == TP_CONN_HANDLE_TYPE_CONTACT)
-    {
-      EmpathyContactFactory *factory = empathy_contact_factory_dup_singleton ();
-      contact = empathy_contact_factory_get_from_handle (factory,
-        cd->account, handle);
-      g_object_unref (factory);
-    }
-
-  operation = empathy_dispatch_operation_new (connection, channel, contact,
+  operation = empathy_dispatch_operation_new (connection, channel, NULL,
     incoming);
 
   g_object_unref (channel);
@@ -786,21 +766,21 @@ dispatcher_connection_advertise_capabilities_cb (TpConnection    *connection,
 }
 
 static void
-dispatcher_connection_ready_cb (TpConnection *connection,
-                                const GError *error,
-                                gpointer dispatcher)
+dispatcher_new_connection_cb (EmpathyAccountManager *manager,
+                              TpConnection *connection,
+                              EmpathyDispatcher *dispatcher)
 {
+  EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher);
   GPtrArray   *capabilities;
   GType        cap_type;
   GValue       cap = {0, };
   const gchar *remove = NULL;
 
-  if (error)
-    {
-      dispatcher_connection_invalidated_cb (connection, error->domain,
-        error->code, error->message, dispatcher);
-      return;
-    }
+  if (g_hash_table_lookup (priv->connections, connection) != NULL)
+    return;
+
+  g_hash_table_insert (priv->connections, g_object_ref (connection),
+    new_connection_data ());
 
   g_signal_connect (connection, "invalidated",
     G_CALLBACK (dispatcher_connection_invalidated_cb), dispatcher);
@@ -815,7 +795,7 @@ dispatcher_connection_ready_cb (TpConnection *connection,
       tp_cli_dbus_properties_call_get_all (connection, -1,
         TP_IFACE_CONNECTION_INTERFACE_REQUESTS,
         dispatcher_connection_got_all,
-        NULL, NULL, dispatcher);
+        NULL, NULL, G_OBJECT (dispatcher));
     }
   else
     {
@@ -852,44 +832,6 @@ dispatcher_connection_ready_cb (TpConnection *connection,
   g_ptr_array_free (capabilities, TRUE);
 }
 
-static void
-dispatcher_update_account (EmpathyDispatcher *dispatcher,
-                           McAccount *account)
-{
-  EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher);
-  TpConnection *connection;
-
-  connection = g_hash_table_lookup (priv->accounts, account);
-  if (connection != NULL)
-    return;
-
-  connection = mission_control_get_tpconnection (priv->mc, account, NULL);
-  if (connection == NULL)
-    return;
-
-  g_hash_table_insert (priv->connections, g_object_ref (connection),
-    new_connection_data (account));
-
-  g_hash_table_insert (priv->accounts, g_object_ref (account),
-    g_object_ref (connection));
-
-  tp_connection_call_when_ready (connection, dispatcher_connection_ready_cb,
-    dispatcher);
-
-  g_object_unref (connection);
-}
-
-static void
-dispatcher_account_connection_cb (EmpathyAccountManager *manager,
-                                  McAccount *account,
-                                  TpConnectionStatusReason reason,
-                                  TpConnectionStatus status,
-                                  TpConnectionStatus previous,
-                                  EmpathyDispatcher *dispatcher)
-{
-  dispatcher_update_account (dispatcher, account);
-}
-
 static GObject*
 dispatcher_constructor (GType type,
                         guint n_construct_params,
@@ -922,7 +864,7 @@ dispatcher_finalize (GObject *object)
   gpointer connection;
 
   g_signal_handlers_disconnect_by_func (priv->account_manager,
-      dispatcher_account_connection_cb, object);
+      dispatcher_new_connection_cb, object);
 
   for (l = priv->channels; l; l = l->next)
     {
@@ -942,7 +884,6 @@ dispatcher_finalize (GObject *object)
   g_object_unref (priv->account_manager);
   g_object_unref (priv->mc);
 
-  g_hash_table_destroy (priv->accounts);
   g_hash_table_destroy (priv->connections);
 }
 
@@ -991,7 +932,7 @@ empathy_dispatcher_class_init (EmpathyDispatcherClass *klass)
 static void
 empathy_dispatcher_init (EmpathyDispatcher *dispatcher)
 {
-  GList *accounts, *l;
+  GList *connections, *l;
   EmpathyDispatcherPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (dispatcher,
     EMPATHY_TYPE_DISPATCHER, EmpathyDispatcherPriv);
 
@@ -999,27 +940,22 @@ empathy_dispatcher_init (EmpathyDispatcher *dispatcher)
   priv->mc = empathy_mission_control_dup_singleton ();
   priv->account_manager = empathy_account_manager_dup_singleton ();
 
-  g_signal_connect (priv->account_manager,
-    "account-connection-changed",
-    G_CALLBACK (dispatcher_account_connection_cb),
+  g_signal_connect (priv->account_manager, "new-connection",
+    G_CALLBACK (dispatcher_new_connection_cb),
     dispatcher);
 
-  priv->accounts = g_hash_table_new_full (empathy_account_hash,
-        empathy_account_equal, g_object_unref, g_object_unref);
-
   priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal,
     g_object_unref, (GDestroyNotify) free_connection_data);
 
   priv->channels = NULL;
 
-  accounts = mc_accounts_list_by_enabled (TRUE);
-
-  for (l = accounts; l; l = l->next)
+  connections = empathy_account_manager_dup_connections (priv->account_manager);
+  for (l = connections; l; l = l->next)
     {
-      dispatcher_update_account (dispatcher, l->data);
+      dispatcher_new_connection_cb (priv->account_manager, l->data, dispatcher);
       g_object_unref (l->data);
     }
-  g_list_free (accounts);
+  g_list_free (connections);
 }
 
 EmpathyDispatcher *
@@ -1167,50 +1103,6 @@ dispatcher_request_channel (DispatcherRequestData *request_data)
     request_data, NULL, G_OBJECT (request_data->dispatcher));
 }
 
-void
-empathy_dispatcher_call_with_contact (EmpathyContact *contact,
-                                      EmpathyDispatcherRequestCb *callback,
-                                      gpointer user_data)
-{
-  EmpathyDispatcher *dispatcher = empathy_dispatcher_dup_singleton();
-  EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher);
-  McAccount *account;
-  TpConnection *connection;
-  ConnectionData *cd;
-  DispatcherRequestData *request_data;
-
-  g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
-  account = empathy_contact_get_account (contact);
-  connection = g_hash_table_lookup (priv->accounts, account);
-
-  g_assert (connection != NULL);
-  cd = g_hash_table_lookup (priv->connections, connection);
-  request_data  = new_dispatcher_request_data (dispatcher, connection,
-    TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, TP_HANDLE_TYPE_NONE, 0, NULL,
-    contact, callback, user_data);
-
-  cd->outstanding_requests = g_list_prepend
-    (cd->outstanding_requests, request_data);
-
-  dispatcher_request_channel (request_data);
-
-  g_object_unref (dispatcher);
-}
-
-static void
-dispatcher_chat_with_contact_cb (EmpathyContact *contact,
-                                 const GError *error,
-                                 gpointer user_data,
-                                 GObject *object)
-{
-  DispatcherRequestData *request_data = (DispatcherRequestData *) user_data;
-
-  request_data->handle = empathy_contact_get_handle (contact);
-
-  dispatcher_request_channel (request_data);
-}
-
 void
 empathy_dispatcher_chat_with_contact (EmpathyContact *contact,
                                       EmpathyDispatcherRequestCb *callback,
@@ -1218,7 +1110,6 @@ empathy_dispatcher_chat_with_contact (EmpathyContact *contact,
 {
   EmpathyDispatcher *dispatcher;
   EmpathyDispatcherPriv *priv;
-  McAccount *account;
   TpConnection *connection;
   ConnectionData *connection_data;
   DispatcherRequestData *request_data;
@@ -1228,46 +1119,75 @@ empathy_dispatcher_chat_with_contact (EmpathyContact *contact,
   dispatcher = empathy_dispatcher_dup_singleton();
   priv = GET_PRIV (dispatcher);
 
-  account = empathy_contact_get_account (contact);
-  connection = g_hash_table_lookup (priv->accounts, account);
+  connection = empathy_contact_get_connection (contact);
   connection_data = g_hash_table_lookup (priv->connections, connection);
 
   /* The contact handle might not be known yet */
   request_data  = new_dispatcher_request_data (dispatcher, connection,
-    TP_IFACE_CHANNEL_TYPE_TEXT, TP_HANDLE_TYPE_CONTACT, 0, NULL,
-    contact, callback, user_data);
+    TP_IFACE_CHANNEL_TYPE_TEXT, TP_HANDLE_TYPE_CONTACT,
+    empathy_contact_get_handle (contact), NULL, contact, callback, user_data);
 
   connection_data->outstanding_requests = g_list_prepend
     (connection_data->outstanding_requests, request_data);
 
-  empathy_contact_call_when_ready (contact,
-    EMPATHY_CONTACT_READY_HANDLE, dispatcher_chat_with_contact_cb,
-    request_data, NULL, G_OBJECT (dispatcher));
+  dispatcher_request_channel (request_data);
 
   g_object_unref (dispatcher);
 }
 
+typedef struct
+{
+  EmpathyDispatcher *dispatcher;
+  EmpathyDispatcherRequestCb *callback;
+  gpointer user_data;
+} ChatWithContactIdData;
+
+static void
+dispatcher_chat_with_contact_id_cb (EmpathyTpContactFactory *factory,
+                                    EmpathyContact          *contact,
+                                    const GError            *error,
+                                    gpointer                 user_data,
+                                    GObject                 *weak_object)
+{
+  ChatWithContactIdData *data = user_data;
+
+  if (error)
+    {
+      /* FIXME: Should call data->callback with the error */
+      DEBUG ("Error: %s", error->message);
+    }
+  else
+    {
+      empathy_dispatcher_chat_with_contact (contact, data->callback, data->user_data);
+    }
+
+  g_object_unref (data->dispatcher);
+  g_slice_free (ChatWithContactIdData, data);
+}
+
 void
-empathy_dispatcher_chat_with_contact_id (McAccount *account,
+empathy_dispatcher_chat_with_contact_id (TpConnection *connection,
                                          const gchar *contact_id,
                                          EmpathyDispatcherRequestCb *callback,
                                          gpointer user_data)
 {
-  EmpathyDispatcher *dispatcher = empathy_dispatcher_dup_singleton ();
-  EmpathyContactFactory *factory;
-  EmpathyContact        *contact;
+  EmpathyDispatcher *dispatcher;
+  EmpathyTpContactFactory *factory;
+  ChatWithContactIdData *data;
 
-  g_return_if_fail (MC_IS_ACCOUNT (account));
+  g_return_if_fail (TP_IS_CONNECTION (connection));
   g_return_if_fail (!EMP_STR_EMPTY (contact_id));
 
-  factory = empathy_contact_factory_dup_singleton ();
-  contact = empathy_contact_factory_get_from_id (factory, account, contact_id);
-
-  empathy_dispatcher_chat_with_contact (contact, callback, user_data);
+  dispatcher = empathy_dispatcher_dup_singleton ();
+  factory = empathy_tp_contact_factory_dup_singleton (connection);
+  data = g_slice_new0 (ChatWithContactIdData);
+  data->dispatcher = dispatcher;
+  data->callback = callback;
+  data->user_data = user_data;
+  empathy_tp_contact_factory_get_from_id (factory, contact_id,
+      dispatcher_chat_with_contact_id_cb, data, NULL, NULL);
 
-  g_object_unref (contact);
   g_object_unref (factory);
-  g_object_unref (dispatcher);
 }
 
 static void
@@ -1304,7 +1224,7 @@ dispatcher_request_handles_cb (TpConnection *connection,
 }
 
 void
-empathy_dispatcher_join_muc (McAccount *account,
+empathy_dispatcher_join_muc (TpConnection *connection,
                              const gchar *roomname,
                              EmpathyDispatcherRequestCb *callback,
                              gpointer user_data)
@@ -1312,20 +1232,17 @@ empathy_dispatcher_join_muc (McAccount *account,
   EmpathyDispatcher *dispatcher;
   EmpathyDispatcherPriv *priv;
   DispatcherRequestData *request_data;
-  TpConnection *connection;
   ConnectionData *connection_data;
   const gchar *names[] = { roomname, NULL };
 
-  g_return_if_fail (MC_IS_ACCOUNT (account));
+  g_return_if_fail (TP_IS_CONNECTION (connection));
   g_return_if_fail (!EMP_STR_EMPTY (roomname));
 
   dispatcher = empathy_dispatcher_dup_singleton();
   priv = GET_PRIV (dispatcher);
 
-  connection = g_hash_table_lookup (priv->accounts, account);
   connection_data = g_hash_table_lookup (priv->connections, connection);
 
-
   /* Don't know the room handle yet */
   request_data  = new_dispatcher_request_data (dispatcher, connection,
     TP_IFACE_CHANNEL_TYPE_TEXT, TP_HANDLE_TYPE_ROOM, 0, NULL,
@@ -1359,7 +1276,7 @@ dispatcher_create_channel_cb (TpConnection *connect,
 
 void
 empathy_dispatcher_create_channel (EmpathyDispatcher *dispatcher,
-                                   McAccount *account,
+                                   TpConnection *connection,
                                    GHashTable *request,
                                    EmpathyDispatcherRequestCb *callback,
                                    gpointer user_data)
@@ -1371,15 +1288,11 @@ empathy_dispatcher_create_channel (EmpathyDispatcher *dispatcher,
   guint handle_type;
   guint handle;
   gboolean valid;
-  TpConnection *connection;
 
   g_return_if_fail (EMPATHY_IS_DISPATCHER (dispatcher));
-  g_return_if_fail (MC_IS_ACCOUNT (account));
+  g_return_if_fail (TP_IS_CONNECTION (connection));
   g_return_if_fail (request != NULL);
 
-  connection = g_hash_table_lookup (priv->accounts, account);
-  g_assert (connection != NULL);
-
   connection_data = g_hash_table_lookup (priv->connections, connection);
   g_assert (connection_data != NULL);
 
@@ -1405,56 +1318,6 @@ empathy_dispatcher_create_channel (EmpathyDispatcher *dispatcher,
     G_OBJECT (request_data->dispatcher));
 }
 
-static void
-dispatcher_create_channel_with_contact_cb (EmpathyContact *contact,
-                                           const GError *error,
-                                           gpointer user_data,
-                                           GObject *object)
-{
-  DispatcherRequestData *request_data = (DispatcherRequestData *) user_data;
-  GValue *target_handle;
-
-  g_assert (request_data->request);
-
-  if (error != NULL)
-    {
-      dispatcher_request_failed (request_data->dispatcher,
-        request_data, error);
-      return;
-    }
-
-  request_data->handle = empathy_contact_get_handle (contact);
-
-  target_handle = tp_g_value_slice_new (G_TYPE_UINT);
-  g_value_set_uint (target_handle, request_data->handle);
-  g_hash_table_insert (request_data->request,
-    TP_IFACE_CHANNEL ".TargetHandle", target_handle);
-
-  tp_cli_connection_interface_requests_call_create_channel (
-    request_data->connection, -1,
-    request_data->request, dispatcher_create_channel_cb, request_data, NULL,
-    G_OBJECT (request_data->dispatcher));
-}
-
-static void
-dispatcher_send_file_connection_ready_cb (TpConnection *connection,
-                                          const GError *error,
-                                          gpointer user_data)
-{
-  DispatcherRequestData *request_data = (DispatcherRequestData *) user_data;
-
-  if (error !=  NULL)
-    {
-      dispatcher_request_failed (request_data->dispatcher,
-          request_data, error);
-      return;
-    }
-
-  empathy_contact_call_when_ready (request_data->contact,
-    EMPATHY_CONTACT_READY_HANDLE, dispatcher_create_channel_with_contact_cb,
-    request_data, NULL, G_OBJECT (request_data->dispatcher));
-}
-
 void
 empathy_dispatcher_send_file_to_contact (EmpathyContact *contact,
                                          const gchar *filename,
@@ -1466,8 +1329,7 @@ empathy_dispatcher_send_file_to_contact (EmpathyContact *contact,
 {
   EmpathyDispatcher *dispatcher = empathy_dispatcher_dup_singleton();
   EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher);
-  McAccount *account = empathy_contact_get_account (contact);
-  TpConnection *connection = g_hash_table_lookup (priv->accounts, account);
+  TpConnection *connection = empathy_contact_get_connection (contact);
   ConnectionData *connection_data =
     g_hash_table_lookup (priv->connections, connection);
   DispatcherRequestData *request_data;
@@ -1489,6 +1351,11 @@ empathy_dispatcher_send_file_to_contact (EmpathyContact *contact,
   g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
   g_hash_table_insert (request, TP_IFACE_CHANNEL ".TargetHandleType", value);
 
+  /* org.freedesktop.Telepathy.Channel.TargetHandle */
+  value = tp_g_value_slice_new (G_TYPE_UINT);
+  g_value_set_uint (value, empathy_contact_get_handle (contact));
+  g_hash_table_insert (request, TP_IFACE_CHANNEL ".TargetHandle", value);
+
   /* org.freedesktop.Telepathy.Channel.Type.FileTransfer.ContentType */
   value = tp_g_value_slice_new (G_TYPE_STRING);
   g_value_set_string (value, content_type);
@@ -1513,46 +1380,40 @@ empathy_dispatcher_send_file_to_contact (EmpathyContact *contact,
   g_hash_table_insert (request,
     TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Date", value);
 
-
-  /* The contact handle might not be known yet */
-  request_data  = new_dispatcher_request_data (dispatcher, connection,
-    TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, TP_HANDLE_TYPE_CONTACT, 0, request,
-    contact, callback, user_data);
+  request_data = new_dispatcher_request_data (dispatcher, connection,
+    TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, TP_HANDLE_TYPE_CONTACT,
+    empathy_contact_get_handle (contact), request, contact, callback,
+    user_data);
   connection_data->outstanding_requests = g_list_prepend
     (connection_data->outstanding_requests, request_data);
 
-  tp_connection_call_when_ready (connection,
-      dispatcher_send_file_connection_ready_cb, (gpointer) request_data);
+  tp_cli_connection_interface_requests_call_create_channel (
+    request_data->connection, -1,
+    request_data->request, dispatcher_create_channel_cb, request_data, NULL,
+    G_OBJECT (request_data->dispatcher));
 
   g_object_unref (dispatcher);
 }
 
 GStrv
 empathy_dispatcher_find_channel_class (EmpathyDispatcher *dispatcher,
-                                       McAccount *account,
+                                       TpConnection *connection,
                                        const gchar *channel_type,
                                        guint handle_type)
 {
   EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher);
   ConnectionData *cd;
-  TpConnection *connection;
   int i;
   GPtrArray *classes;
 
   g_return_val_if_fail (channel_type != NULL, NULL);
   g_return_val_if_fail (handle_type != 0, NULL);
 
-  connection = g_hash_table_lookup (priv->accounts, account);
-
-  if (connection == NULL)
-    return NULL;
-
   cd = g_hash_table_lookup (priv->connections, connection);
 
   if (cd == NULL)
     return NULL;
 
-
   classes = cd->requestable_channels;
   if (classes == NULL)
     return NULL;
index 13ef06afddd2ff25a8fdb2bd7ad6c1f04365eb67..fb7c6fe35cef867c6567331ed409bed7b8048bbf 100644 (file)
@@ -62,15 +62,11 @@ typedef void (EmpathyDispatcherRequestCb) (
 GType empathy_dispatcher_get_type (void) G_GNUC_CONST;
 
 void empathy_dispatcher_create_channel (EmpathyDispatcher *dispatcher,
-  McAccount *account, GHashTable *request,
-  EmpathyDispatcherRequestCb *callback, gpointer user_data);
-
-/* Requesting 1 to 1 stream media channels */
-void empathy_dispatcher_call_with_contact (EmpathyContact *contact,
+  TpConnection *connection, GHashTable *request,
   EmpathyDispatcherRequestCb *callback, gpointer user_data);
 
 /* Requesting 1 to 1 text channels */
-void empathy_dispatcher_chat_with_contact_id (McAccount *account,
+void empathy_dispatcher_chat_with_contact_id (TpConnection *connection,
   const gchar *contact_id, EmpathyDispatcherRequestCb *callback,
   gpointer user_data);
 void  empathy_dispatcher_chat_with_contact (EmpathyContact *contact,
@@ -83,12 +79,12 @@ void empathy_dispatcher_send_file_to_contact (EmpathyContact *contact,
   gpointer user_data);
 
 /* Request a muc channel */
-void empathy_dispatcher_join_muc (McAccount *account,
+void empathy_dispatcher_join_muc (TpConnection *connection,
   const gchar *roomname, EmpathyDispatcherRequestCb *callback,
   gpointer user_data);
 
 GStrv empathy_dispatcher_find_channel_class (EmpathyDispatcher *dispatcher,
-  McAccount *account, const gchar *channel_type, guint handle_type);
+  TpConnection *connection, const gchar *channel_type, guint handle_type);
 
 /* Get the dispatcher singleton */
 EmpathyDispatcher *    empathy_dispatcher_dup_singleton (void);
index 37a76676f5c84e948cc25f5f7884c9ee41edb11c..b74b5e177dbb7fb2b41bf07e791c0ec245812448 100644 (file)
@@ -481,8 +481,9 @@ log_store_empathy_get_messages_for_file (EmpathyLogStore *self,
 
       t = empathy_time_parse (time);
 
-      sender = empathy_contact_new_full (account, sender_id, sender_name);
-      empathy_contact_set_is_user (sender, is_user);
+      sender = empathy_contact_new_for_log (account, sender_id, sender_name,
+                                           is_user);
+
       if (!EMP_STR_EMPTY (sender_avatar_token))
         empathy_contact_load_avatar_cache (sender,
             sender_avatar_token);
index 42bf7a063c02c75eeffc826cb32ce4cf9797a72c..a5c0003c56741182ad665d9292d61a811899fd9e 100644 (file)
@@ -27,7 +27,7 @@
 #include <telepathy-glib/interfaces.h>
 
 #include "empathy-tp-call.h"
-#include "empathy-contact-factory.h"
+#include "empathy-tp-contact-factory.h"
 #include "empathy-utils.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_TP
@@ -253,22 +253,27 @@ tp_call_request_streams_for_capabilities (EmpathyTpCall *call,
   g_array_free (stream_types, TRUE);
 }
 
-static EmpathyContact *
-tp_call_dup_contact_from_handle (EmpathyTpCall *call, TpHandle handle)
+static void
+tp_call_got_contact_cb (EmpathyTpContactFactory *factory,
+                        EmpathyContact          *contact,
+                        const GError            *error,
+                        gpointer                 user_data,
+                        GObject                 *call)
 {
   EmpathyTpCallPriv *priv = GET_PRIV (call);
-  EmpathyContactFactory *factory;
-  McAccount *account;
-  EmpathyContact *contact;
-
-  factory = empathy_contact_factory_dup_singleton ();
-  account = empathy_channel_get_account (priv->channel);
-  contact = empathy_contact_factory_get_from_handle (factory, account, handle);
 
-  g_object_unref (factory);
-  g_object_unref (account);
+  if (error)
+    {
+      DEBUG ("Error: %s", error->message);
+      return;
+    }
 
-  return contact;
+  priv->contact = g_object_ref (contact);
+  priv->is_incoming = TRUE;
+  priv->status = EMPATHY_TP_CALL_STATUS_PENDING;
+  g_object_notify (G_OBJECT (call), "is-incoming");
+  g_object_notify (G_OBJECT (call), "contact");
+  g_object_notify (G_OBJECT (call), "status");
 }
 
 static void
@@ -288,13 +293,15 @@ tp_call_update_status (EmpathyTpCall *call)
     {
       if (priv->contact == NULL && iter.element != self_handle)
         {
+          EmpathyTpContactFactory *factory;
+          TpConnection *connection;
+
           /* We found the remote contact */
-          priv->contact = tp_call_dup_contact_from_handle (call, iter.element);
-          priv->is_incoming = TRUE;
-          priv->status = EMPATHY_TP_CALL_STATUS_PENDING;
-          g_object_notify (G_OBJECT (call), "is-incoming");
-          g_object_notify (G_OBJECT (call), "contact");
-          g_object_notify (G_OBJECT (call), "status");
+          connection = tp_channel_borrow_connection (priv->channel);
+          factory = empathy_tp_contact_factory_dup_singleton (connection);
+          empathy_tp_contact_factory_get_from_handle (factory, iter.element,
+              tp_call_got_contact_cb, NULL, NULL, G_OBJECT (call));
+          g_object_unref (factory);
         }
 
       if (priv->status == EMPATHY_TP_CALL_STATUS_PENDING &&
@@ -309,20 +316,6 @@ tp_call_update_status (EmpathyTpCall *call)
   g_object_unref (call);
 }
 
-static void
-tp_call_members_changed_cb (TpChannel *channel,
-                            gchar *message,
-                            GArray *added,
-                            GArray *removed,
-                            GArray *local_pending,
-                            GArray *remote_pending,
-                            guint actor,
-                            guint reason,
-                            EmpathyTpCall *call)
-{
-  tp_call_update_status (call);
-}
-
 void
 empathy_tp_call_to (EmpathyTpCall *call, EmpathyContact *contact)
 {
@@ -392,8 +385,8 @@ tp_call_constructor (GType type,
 
   /* Update status when members changes */
   tp_call_update_status (call);
-  g_signal_connect (priv->channel, "group-members-changed",
-      G_CALLBACK (tp_call_members_changed_cb), call);
+  g_signal_connect_swapped (priv->channel, "group-members-changed",
+      G_CALLBACK (tp_call_update_status), call);
 
   return object;
 }
index 048f5b275fc62a8016767c63f7203d0bdd26e853..54e08d07139cebb04b921338a88dd5ab936349e5 100644 (file)
@@ -28,8 +28,7 @@
 #include <telepathy-glib/util.h>
 
 #include "empathy-tp-chat.h"
-#include "empathy-tp-group.h"
-#include "empathy-contact-factory.h"
+#include "empathy-tp-contact-factory.h"
 #include "empathy-contact-monitor.h"
 #include "empathy-contact-list.h"
 #include "empathy-marshal.h"
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpChat)
 typedef struct {
        gboolean               dispose_has_run;
-       EmpathyContactFactory *factory;
+       EmpathyTpContactFactory *factory;
        EmpathyContactMonitor *contact_monitor;
        EmpathyContact        *user;
        EmpathyContact        *remote_contact;
-       EmpathyTpGroup        *group;
-       McAccount             *account;
+       GList                 *members;
        TpChannel             *channel;
        gboolean               listing_pending_messages;
        /* Queue of messages not signalled yet */
@@ -57,7 +55,6 @@ typedef struct {
        gboolean               had_properties_list;
        GPtrArray             *properties;
        gboolean               ready;
-       guint                  members_count;
 } EmpathyTpChatPriv;
 
 typedef struct {
@@ -100,13 +97,8 @@ tp_chat_invalidated_cb (TpProxy       *proxy,
                        gchar         *message,
                        EmpathyTpChat *chat)
 {
-       EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
        DEBUG ("Channel invalidated: %s", message);
        g_signal_emit (chat, signals[DESTROY], 0);
-
-       g_object_unref (priv->channel);
-       priv->channel = NULL;
 }
 
 static void
@@ -120,108 +112,6 @@ tp_chat_async_cb (TpChannel *proxy,
        }
 }
 
-static void
-tp_chat_member_added_cb (EmpathyTpGroup *group,
-                        EmpathyContact *contact,
-                        EmpathyContact *actor,
-                        guint           reason,
-                        const gchar    *message,
-                        EmpathyTpChat  *chat)
-{
-       EmpathyTpChatPriv *priv = GET_PRIV (chat);
-       guint              handle_type = 0;
-
-       if (priv->channel == NULL)
-               return;
-
-       priv->members_count++;
-       g_signal_emit_by_name (chat, "members-changed",
-                              contact, actor, reason, message,
-                              TRUE);
-
-       g_object_get (priv->channel, "handle-type", &handle_type, NULL);
-       if (handle_type == TP_HANDLE_TYPE_ROOM) {
-               return;
-       }
-
-       if (priv->members_count > 2 && priv->remote_contact) {
-               /* We now have more than 2 members, this is not a p2p chat
-                * anymore. Remove the remote-contact as it makes no sense, the
-                * EmpathyContactList interface must be used now. */
-               g_object_unref (priv->remote_contact);
-               priv->remote_contact = NULL;
-               g_object_notify (G_OBJECT (chat), "remote-contact");
-       }
-       if (priv->members_count <= 2 && !priv->remote_contact &&
-           !empathy_contact_is_user (contact)) {
-               /* This is a p2p chat, if it's not ourself that means this is
-                * the remote contact with who we are chatting. This is to
-                * avoid forcing the usage of the EmpathyContactList interface
-                * for p2p chats. */
-               priv->remote_contact = g_object_ref (contact);
-               g_object_notify (G_OBJECT (chat), "remote-contact");
-       }
-}
-
-static void
-tp_chat_member_removed_cb (EmpathyTpGroup *group,
-                          EmpathyContact *contact,
-                          EmpathyContact *actor,
-                          guint           reason,
-                          const gchar    *message,
-                          EmpathyTpChat  *chat)
-{
-       EmpathyTpChatPriv *priv = GET_PRIV (chat);
-       guint              handle_type = 0;
-
-       if (priv->channel == NULL)
-               return;
-
-       priv->members_count--;
-       g_signal_emit_by_name (chat, "members-changed",
-                              contact, actor, reason, message,
-                              FALSE);
-
-       g_object_get (priv->channel, "handle-type", &handle_type, NULL);
-       if (handle_type == TP_HANDLE_TYPE_ROOM) {
-               return;
-       }
-
-       if (priv->members_count <= 2 && !priv->remote_contact) {
-               GList *members, *l;
-
-               /* We are not a MUC anymore, get the remote contact back */
-               members = empathy_tp_group_get_members (group);
-               for (l = members; l; l = l->next) {
-                       if (!empathy_contact_is_user (l->data)) {
-                               priv->remote_contact = g_object_ref (l->data);
-                               g_object_notify (G_OBJECT (chat), "remote-contact");
-                               break;
-                       }
-               }
-               g_list_foreach (members, (GFunc) g_object_unref, NULL);
-               g_list_free (members);
-       }
-}
-
-static void
-tp_chat_local_pending_cb  (EmpathyTpGroup *group,
-                          EmpathyContact *contact,
-                          EmpathyContact *actor,
-                          guint           reason,
-                          const gchar    *message,
-                          EmpathyTpChat  *chat)
-{
-       EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
-       if (priv->channel == NULL)
-               return;
-
-       g_signal_emit_by_name (chat, "pendings-changed",
-                              contact, actor, reason, message,
-                              TRUE);
-}
-
 static void
 tp_chat_add (EmpathyContactList *list,
             EmpathyContact     *contact,
@@ -268,8 +158,9 @@ tp_chat_get_members (EmpathyContactList *list)
 
        g_return_val_if_fail (EMPATHY_IS_TP_CHAT (list), NULL);
 
-       if (priv->group) {
-               members = empathy_tp_group_get_members (priv->group);
+       if (priv->members) {
+               members = g_list_copy (priv->members);
+               g_list_foreach (members, (GFunc) g_object_ref, NULL);
        } else {
                members = g_list_prepend (members, g_object_ref (priv->user));
                members = g_list_prepend (members, g_object_ref (priv->remote_contact));
@@ -294,119 +185,74 @@ tp_chat_get_monitor (EmpathyContactList *list)
        return priv->contact_monitor;
 }
 
-static EmpathyMessage *
-tp_chat_build_message (EmpathyTpChat *chat,
-                      guint          id,
-                      guint          type,
-                      guint          timestamp,
-                      guint          from_handle,
-                      const gchar   *message_body)
+static void
+tp_chat_emit_queued_messages (EmpathyTpChat *chat)
 {
-       EmpathyTpChatPriv *priv;
+       EmpathyTpChatPriv *priv = GET_PRIV (chat);
        EmpathyMessage    *message;
-       EmpathyContact    *sender;
 
-       priv = GET_PRIV (chat);
-
-       if (from_handle == 0) {
-               sender = g_object_ref (priv->user);
-       } else {
-               sender = empathy_contact_factory_get_from_handle (priv->factory,
-                                                                 priv->account,
-                                                                 from_handle);
-       }
-
-       message = empathy_message_new (message_body);
-       empathy_message_set_tptype (message, type);
-       empathy_message_set_sender (message, sender);
-       empathy_message_set_receiver (message, priv->user);
-       empathy_message_set_timestamp (message, timestamp);
-       empathy_message_set_id (message, id);
-
-       g_object_unref (sender);
-
-       return message;
-}
-
-static void
-tp_chat_sender_ready_notify_cb (EmpathyContact *contact,
-                               GParamSpec     *param_spec,
-                               EmpathyTpChat  *chat)
-{
-       EmpathyTpChatPriv   *priv = GET_PRIV (chat);
-       EmpathyMessage      *message;
-       EmpathyContactReady  ready;
-       EmpathyContact      *sender = NULL;
-       gboolean             removed = FALSE;
-
-       /* Emit all messages queued until we find a message with not
-        * ready sender (in case of a MUC we could have more than one sender).
-        * When leaving this loop, sender is the first not ready contact queued
-        * and removed tells if at least one message got removed
-        * from the queue. */
+       /* Check if we can now emit some queued messages */
        while ((message = g_queue_peek_head (priv->messages_queue)) != NULL) {
-               sender = empathy_message_get_sender (message);
-               ready = empathy_contact_get_ready (sender);
-
-               if ((ready & EMPATHY_CONTACT_READY_NAME) == 0 ||
-                   (ready & EMPATHY_CONTACT_READY_ID) == 0) {
+               if (empathy_message_get_sender (message) == NULL) {
                        break;
                }
 
                DEBUG ("Queued message ready");
-               message = g_queue_pop_head (priv->messages_queue);
+               g_queue_pop_head (priv->messages_queue);
                g_queue_push_tail (priv->pending_messages_queue, message);
                g_signal_emit (chat, signals[MESSAGE_RECEIVED], 0, message);
-               removed = TRUE;
        }
+}
 
-       if (removed) {
-               /* We removed at least one message from the queue, disconnect
-                * the ready signal from the previous contact */
-               g_signal_handlers_disconnect_by_func (contact,
-                                                     tp_chat_sender_ready_notify_cb,
-                                                     chat);
-
-               if (g_queue_get_length (priv->messages_queue) > 0) {
-                       /* We still have queued message, connect the ready
-                        * signal on the new first message sender. */
-                       g_signal_connect (sender, "notify::ready",
-                                         G_CALLBACK (tp_chat_sender_ready_notify_cb),
-                                         chat);
-               }
+static void
+tp_chat_got_sender_cb (EmpathyTpContactFactory *factory,
+                      EmpathyContact          *contact,
+                      const GError            *error,
+                      gpointer                 message,
+                      GObject                 *chat)
+{
+       EmpathyTpChatPriv *priv = GET_PRIV (chat);
+
+       if (error) {
+               DEBUG ("Error: %s", error->message);
+               /* Do not block the message queue, just drop this message */
+               g_queue_remove (priv->messages_queue, message);
+       } else {
+               empathy_message_set_sender (message, contact);
        }
+
+       tp_chat_emit_queued_messages (EMPATHY_TP_CHAT (chat));
 }
 
 static void
-tp_chat_emit_or_queue_message (EmpathyTpChat  *chat,
-                              EmpathyMessage *message)
+tp_chat_build_message (EmpathyTpChat *chat,
+                      guint          id,
+                      guint          type,
+                      guint          timestamp,
+                      guint          from_handle,
+                      const gchar   *message_body)
 {
-       EmpathyTpChatPriv   *priv = GET_PRIV (chat);
-       EmpathyContact      *sender;
-       EmpathyContactReady  ready;
+       EmpathyTpChatPriv *priv;
+       EmpathyMessage    *message;
 
-       if (g_queue_get_length (priv->messages_queue) > 0) {
-               DEBUG ("Message queue not empty");
-               g_queue_push_tail (priv->messages_queue, g_object_ref (message));
-               return;
-       }
+       priv = GET_PRIV (chat);
 
+       message = empathy_message_new (message_body);
+       empathy_message_set_tptype (message, type);
+       empathy_message_set_receiver (message, priv->user);
+       empathy_message_set_timestamp (message, timestamp);
+       empathy_message_set_id (message, id);
+       g_queue_push_tail (priv->messages_queue, message);
 
-       sender = empathy_message_get_sender (message);
-       ready = empathy_contact_get_ready (sender);
-       if ((ready & EMPATHY_CONTACT_READY_NAME) &&
-           (ready & EMPATHY_CONTACT_READY_ID)) {
-               DEBUG ("Message queue empty and sender ready");
-               g_queue_push_tail (priv->pending_messages_queue, g_object_ref (message));
-               g_signal_emit (chat, signals[MESSAGE_RECEIVED], 0, message);
-               return;
+       if (from_handle == 0) {
+               empathy_message_set_sender (message, priv->user);
+               tp_chat_emit_queued_messages (chat);
+       } else {
+               empathy_tp_contact_factory_get_from_handle (priv->factory,
+                       from_handle,
+                       tp_chat_got_sender_cb,
+                       message, NULL, G_OBJECT (chat));
        }
-
-       DEBUG ("Sender not ready");
-       g_queue_push_tail (priv->messages_queue, g_object_ref (message));
-       g_signal_connect (sender, "notify::ready",
-                         G_CALLBACK (tp_chat_sender_ready_notify_cb),
-                         chat);
 }
 
 static void
@@ -422,7 +268,6 @@ tp_chat_received_cb (TpChannel   *channel,
 {
        EmpathyTpChat *chat = EMPATHY_TP_CHAT (chat_);
        EmpathyTpChatPriv *priv = GET_PRIV (chat);
-       EmpathyMessage    *message;
 
        if (priv->channel == NULL)
                return;
@@ -447,15 +292,12 @@ tp_chat_received_cb (TpChannel   *channel,
                return;
        }
 
-       message = tp_chat_build_message (chat,
-                                        message_id,
-                                        message_type,
-                                        timestamp,
-                                        from_handle,
-                                        message_body);
-
-       tp_chat_emit_or_queue_message (chat, message);
-       g_object_unref (message);
+       tp_chat_build_message (chat,
+                              message_id,
+                              message_type,
+                              timestamp,
+                              from_handle,
+                              message_body);
 }
 
 static void
@@ -468,22 +310,18 @@ tp_chat_sent_cb (TpChannel   *channel,
 {
        EmpathyTpChat *chat = EMPATHY_TP_CHAT (chat_);
        EmpathyTpChatPriv *priv = GET_PRIV (chat);
-       EmpathyMessage *message;
 
        if (priv->channel == NULL)
                return;
 
        DEBUG ("Message sent: %s", message_body);
 
-       message = tp_chat_build_message (chat,
-                                        0,
-                                        message_type,
-                                        timestamp,
-                                        0,
-                                        message_body);
-
-       tp_chat_emit_or_queue_message (chat, message);
-       g_object_unref (message);
+       tp_chat_build_message (chat,
+                              0,
+                              message_type,
+                              timestamp,
+                              0,
+                              message_body);
 }
 
 static void
@@ -495,7 +333,6 @@ tp_chat_send_error_cb (TpChannel   *channel,
                       gpointer     user_data,
                       GObject     *chat)
 {
-       EmpathyMessage *message;
        EmpathyTpChatPriv *priv = GET_PRIV (chat);
 
        if (priv->channel == NULL)
@@ -503,15 +340,12 @@ tp_chat_send_error_cb (TpChannel   *channel,
 
        DEBUG ("Message sent error: %s (%d)", message_body, error_code);
 
-       message = tp_chat_build_message (EMPATHY_TP_CHAT (chat),
-                                        0,
-                                        message_type,
-                                        timestamp,
-                                        0,
-                                        message_body);
-
-       g_signal_emit (chat, signals[SEND_ERROR], 0, message, error_code);
-       g_object_unref (message);
+       tp_chat_build_message (EMPATHY_TP_CHAT (chat),
+                              0,
+                              message_type,
+                              timestamp,
+                              0,
+                              message_body);
 }
 
 static void
@@ -529,28 +363,45 @@ tp_chat_send_cb (TpChannel    *proxy,
        }
 }
 
+typedef struct {
+       EmpathyTpChat *chat;
+       TpChannelChatState state;
+} StateChangedData;
+
 static void
-tp_chat_state_changed_cb (TpChannel *channel,
-                         guint      handle,
-                         guint      state,
-                         gpointer   user_data,
-                         GObject   *chat)
+tp_chat_state_changed_got_contact_cb (EmpathyTpContactFactory *factory,
+                                     EmpathyContact          *contact,
+                                     const GError            *error,
+                                     gpointer                 user_data,
+                                     GObject                 *chat)
 {
-       EmpathyTpChatPriv *priv = GET_PRIV (chat);
-       EmpathyContact    *contact;
+       TpChannelChatState state;
 
-       if (priv->channel == NULL)
+       if (error) {
+               DEBUG ("Error: %s", error->message);
                return;
+       }
 
-       contact = empathy_contact_factory_get_from_handle (priv->factory,
-                                                          priv->account,
-                                                          handle);
-
+       state = GPOINTER_TO_UINT (user_data);
        DEBUG ("Chat state changed for %s (%d): %d",
-               empathy_contact_get_name (contact), handle, state);
+               empathy_contact_get_name (contact),
+               empathy_contact_get_handle (contact), state);
 
        g_signal_emit (chat, signals[CHAT_STATE_CHANGED], 0, contact, state);
-       g_object_unref (contact);
+}
+
+static void
+tp_chat_state_changed_cb (TpChannel *channel,
+                         TpHandle   handle,
+                         TpChannelChatState state,
+                         gpointer   user_data,
+                         GObject   *chat)
+{
+       EmpathyTpChatPriv *priv = GET_PRIV (chat);
+
+       empathy_tp_contact_factory_get_from_handle (priv->factory, handle,
+               tp_chat_state_changed_got_contact_cb, GUINT_TO_POINTER (state),
+               NULL, chat);
 }
 
 static void
@@ -576,7 +427,6 @@ tp_chat_list_pending_messages_cb (TpChannel       *channel,
        }
 
        for (i = 0; i < messages_list->len; i++) {
-               EmpathyMessage *message;
                GValueArray    *message_struct;
                const gchar    *message_body;
                guint           message_id;
@@ -608,15 +458,12 @@ tp_chat_list_pending_messages_cb (TpChannel       *channel,
                        continue;
                }
 
-               message = tp_chat_build_message (chat,
-                                                message_id,
-                                                message_type,
-                                                timestamp,
-                                                from_handle,
-                                                message_body);
-
-               tp_chat_emit_or_queue_message (chat, message);
-               g_object_unref (message);
+               tp_chat_build_message (chat,
+                                      message_id,
+                                      message_type,
+                                      timestamp,
+                                      from_handle,
+                                      message_body);
        }
 
        if (empty_non_text_content_ids != NULL) {
@@ -781,8 +628,6 @@ empathy_tp_chat_set_property (EmpathyTpChat *chat,
        TpChatProperty    *property;
        guint              i;
 
-       g_return_if_fail (priv->ready);
-
        for (i = 0; i < priv->properties->len; i++) {
                property = g_ptr_array_index (priv->properties, i);
                if (!tp_strdiff (property->name, name)) {
@@ -824,64 +669,90 @@ empathy_tp_chat_set_property (EmpathyTpChat *chat,
 }
 
 static void
-tp_chat_channel_ready_cb (EmpathyTpChat *chat)
+tp_chat_dispose (GObject *object)
 {
-       EmpathyTpChatPriv *priv = GET_PRIV (chat);
-       TpConnection      *connection;
-       guint              handle, handle_type;
+       EmpathyTpChat *self = EMPATHY_TP_CHAT (object);
+       EmpathyTpChatPriv *priv = GET_PRIV (self);
 
-       if (priv->channel == NULL)
+       if (priv->dispose_has_run)
                return;
 
-       DEBUG ("Channel ready");
-
-       g_object_get (priv->channel,
-                     "connection", &connection,
-                     "handle", &handle,
-                     "handle_type", &handle_type,
-                     NULL);
+       priv->dispose_has_run = TRUE;
 
-       if (handle_type == TP_HANDLE_TYPE_CONTACT && handle != 0) {
-               priv->remote_contact = empathy_contact_factory_get_from_handle (priv->factory,
-                                                                               priv->account,
-                                                                               handle);
-               g_object_notify (G_OBJECT (chat), "remote-contact");
+       if (priv->channel != NULL) {
+               g_signal_handlers_disconnect_by_func (priv->channel,
+                       tp_chat_invalidated_cb, self);
+               g_object_unref (priv->channel);
        }
+       priv->channel = NULL;
 
-       if (tp_proxy_has_interface_by_id (priv->channel,
-                                         TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP)) {
-               priv->group = empathy_tp_group_new (priv->channel);
-
-               g_signal_connect (priv->group, "member-added",
-                                 G_CALLBACK (tp_chat_member_added_cb),
-                                 chat);
-               g_signal_connect (priv->group, "member-removed",
-                                 G_CALLBACK (tp_chat_member_removed_cb),
-                                 chat);
-               g_signal_connect (priv->group, "local-pending",
-                                 G_CALLBACK (tp_chat_local_pending_cb),
-                                 chat);
-               empathy_run_until_ready (priv->group);
-       } else {
-               priv->members_count = 2;
+       if (priv->remote_contact != NULL)
+               g_object_unref (priv->remote_contact);
+       priv->remote_contact = NULL;
+
+       if (priv->factory != NULL)
+               g_object_unref (priv->factory);
+       priv->factory = NULL;
+
+       if (priv->user != NULL);
+               g_object_unref (priv->user);
+       priv->user = NULL;
+
+       if (priv->contact_monitor)
+               g_object_unref (priv->contact_monitor);
+       priv->contact_monitor = NULL;
+
+       g_queue_foreach (priv->messages_queue, (GFunc) g_object_unref, NULL);
+       g_queue_clear (priv->messages_queue);
+
+       g_queue_foreach (priv->pending_messages_queue,
+               (GFunc) g_object_unref, NULL);
+       g_queue_clear (priv->pending_messages_queue);
+
+       if (G_OBJECT_CLASS (empathy_tp_chat_parent_class)->dispose)
+               G_OBJECT_CLASS (empathy_tp_chat_parent_class)->dispose (object);
+}
+
+static void
+tp_chat_finalize (GObject *object)
+{
+       EmpathyTpChatPriv *priv = GET_PRIV (object);
+       guint              i;
+
+       DEBUG ("Finalize: %p", object);
+
+       if (priv->properties) {
+               for (i = 0; i < priv->properties->len; i++) {
+                       TpChatProperty *property;
+
+                       property = g_ptr_array_index (priv->properties, i);
+                       g_free (property->name);
+                       if (property->value) {
+                               tp_g_value_slice_free (property->value);
+                       }
+                       g_slice_free (TpChatProperty, property);
+               }
+               g_ptr_array_free (priv->properties, TRUE);
        }
-       
-       if (tp_proxy_has_interface_by_id (priv->channel,
-                                         TP_IFACE_QUARK_PROPERTIES_INTERFACE)) {
-               tp_cli_properties_interface_call_list_properties (priv->channel, -1,
-                                                                 tp_chat_list_properties_cb,
-                                                                 NULL, NULL,
-                                                                 G_OBJECT (chat));
-               tp_cli_properties_interface_connect_to_properties_changed (priv->channel,
-                                                                          tp_chat_properties_changed_cb,
-                                                                          NULL, NULL,
-                                                                          G_OBJECT (chat), NULL);
-               tp_cli_properties_interface_connect_to_property_flags_changed (priv->channel,
-                                                                              tp_chat_property_flags_changed_cb,
-                                                                              NULL, NULL,
-                                                                              G_OBJECT (chat), NULL);
+
+       g_queue_free (priv->messages_queue);
+       g_queue_free (priv->pending_messages_queue);
+
+       G_OBJECT_CLASS (empathy_tp_chat_parent_class)->finalize (object);
+}
+
+static void
+tp_chat_check_if_ready (EmpathyTpChat *chat)
+{
+       EmpathyTpChatPriv *priv = GET_PRIV (chat);
+
+       if (priv->ready || priv->user == NULL ||
+           (priv->members == NULL && priv->remote_contact == NULL)) {
+               return;
        }
 
+       DEBUG ("Ready!");
+
        priv->listing_pending_messages = TRUE;
        tp_cli_channel_type_text_call_list_pending_messages (priv->channel, -1,
                                                             FALSE,
@@ -909,101 +780,184 @@ tp_chat_channel_ready_cb (EmpathyTpChat *chat)
                                                                           tp_chat_state_changed_cb,
                                                                           NULL, NULL,
                                                                           G_OBJECT (chat), NULL);
-
        priv->ready = TRUE;
        g_object_notify (G_OBJECT (chat), "ready");
 }
 
 static void
-tp_chat_dispose (GObject *object)
+tp_chat_update_remote_contact (EmpathyTpChat *chat)
 {
-       EmpathyTpChat *self = EMPATHY_TP_CHAT (object);
-       EmpathyTpChatPriv *priv = GET_PRIV (self);
+       EmpathyTpChatPriv *priv = GET_PRIV (chat);
+       EmpathyContact *contact = NULL;
+       TpHandle self_handle;
+       TpHandleType handle_type;
+       GList *l;
 
-       if (priv->dispose_has_run)
+       /* If this is a named chatroom, never pretend it is a private chat */
+       tp_channel_get_handle (priv->channel, &handle_type);
+       if (handle_type == TP_HANDLE_TYPE_ROOM) {
                return;
+       }
 
-       priv->dispose_has_run = TRUE;
-
-       if (priv->channel != NULL)
-               {
-                       g_signal_handlers_disconnect_by_func (priv->channel,
-                               tp_chat_invalidated_cb, self);
-                       g_object_unref (priv->channel);
-                       priv->channel = NULL;
+       /* This is an MSN-like chat where anyone can join the chat at anytime.
+        * If there is only one non-self contact member, we are in a private
+        * chat and we set the "remote-contact" property to that contact. If
+        * there are more, set the "remote-contact" property to NULL and the
+        * UI will display a contact list. */
+       self_handle = tp_channel_group_get_self_handle (priv->channel);
+       for (l = priv->members; l; l = l->next) {
+               /* Skip self contact if member */
+               if (empathy_contact_get_handle (l->data) == self_handle) {
+                       continue;
                }
 
-       if (priv->remote_contact != NULL)
-               g_object_unref (priv->remote_contact);
+               /* We have more than one remote contact, break */
+               if (contact != NULL) {
+                       contact = NULL;
+                       break;
+               }
 
-       priv->remote_contact = NULL;
+               /* If we didn't find yet a remote contact, keep this one */
+               contact = l->data;
+       }
 
-       if (priv->group != NULL)
-               g_object_unref (priv->group);
-       priv->group = NULL;
+       if (priv->remote_contact == contact) {
+               return;
+       }
 
-       if (priv->factory != NULL)
-               g_object_unref (priv->factory);
-       priv->factory = NULL;
+       DEBUG ("Changing remote contact from %p to %p",
+               priv->remote_contact, contact);
 
-       if (priv->user != NULL);
-               g_object_unref (priv->user);
-       priv->user = NULL;
+       if (priv->remote_contact) {
+               g_object_unref (priv->remote_contact);
+       }
 
-       if (priv->account != NULL);
-               g_object_unref (priv->account);
-       priv->account = NULL;
+       priv->remote_contact = contact ? g_object_ref (contact) : NULL;
+       g_object_notify (G_OBJECT (chat), "remote-contact");
+}
 
-       if (priv->contact_monitor)
-               g_object_unref (priv->contact_monitor);
-       priv->contact_monitor = NULL;
+static void
+tp_chat_got_added_contacts_cb (EmpathyTpContactFactory *factory,
+                              guint                    n_contacts,
+                              EmpathyContact * const * contacts,
+                              guint                    n_failed,
+                              const TpHandle          *failed,
+                              const GError            *error,
+                              gpointer                 user_data,
+                              GObject                 *chat)
+{
+       EmpathyTpChatPriv *priv = GET_PRIV (chat);
+       guint i;
+       const TpIntSet *members;
+       TpHandle handle;
+       EmpathyContact *contact;
 
-       if (!g_queue_is_empty (priv->messages_queue)) {
-               EmpathyMessage *message;
-               EmpathyContact *contact;
+       if (error) {
+               DEBUG ("Error: %s", error->message);
+               return;
+       }
 
-               message = g_queue_peek_head (priv->messages_queue);
-               contact = empathy_message_get_sender (message);
-               g_signal_handlers_disconnect_by_func (contact,
-               tp_chat_sender_ready_notify_cb, object);
+       members = tp_channel_group_get_members (priv->channel);
+       for (i = 0; i < n_contacts; i++) {
+               contact = contacts[i];
+               handle = empathy_contact_get_handle (contact);
+
+               /* Make sure the contact is still member */
+               if (tp_intset_is_member (members, handle)) {
+                       priv->members = g_list_prepend (priv->members,
+                               g_object_ref (contact));
+                       g_signal_emit_by_name (chat, "members-changed",
+                                              contact, NULL, 0, NULL, FALSE);
+               }
        }
 
-       g_list_foreach (priv->messages_queue->head,
-               (GFunc) g_object_unref, NULL);
+       tp_chat_update_remote_contact (EMPATHY_TP_CHAT (chat));
+       tp_chat_check_if_ready (EMPATHY_TP_CHAT (chat));
+}
 
-       g_list_foreach (priv->pending_messages_queue->head,
-               (GFunc) g_object_unref, NULL);
+static void
+tp_chat_group_members_changed_cb (TpChannel     *self,
+                                 gchar         *message,
+                                 GArray        *added,
+                                 GArray        *removed,
+                                 GArray        *local_pending,
+                                 GArray        *remote_pending,
+                                 guint          actor,
+                                 guint          reason,
+                                 EmpathyTpChat *chat)
+{
+       EmpathyTpChatPriv *priv = GET_PRIV (chat);
+       EmpathyContact *contact;
+       TpHandle handle;
+       guint i;
+       GList *l;
 
-       if (G_OBJECT_CLASS (empathy_tp_chat_parent_class)->dispose)
-               G_OBJECT_CLASS (empathy_tp_chat_parent_class)->dispose (object);
+       /* Remove contacts that are not members anymore */
+       for (i = 0; i < removed->len; i++) {
+               for (l = priv->members; l; l = l->next) {
+                       contact = l->data;
+                       handle = empathy_contact_get_handle (contact);
+                       if (handle == g_array_index (removed, TpHandle, i)) {
+                               priv->members = g_list_delete_link (priv->members, l);
+                               g_signal_emit_by_name (chat, "members-changed",
+                                                      contact, NULL, reason,
+                                                      message, FALSE);
+                               g_object_unref (contact);
+                               break;
+                       }
+               }
+       }
+
+       /* Request added contacts */
+       if (added->len > 0) {
+               empathy_tp_contact_factory_get_from_handles (priv->factory,
+                       added->len, (TpHandle*) added->data,
+                       tp_chat_got_added_contacts_cb, NULL, NULL,
+                       G_OBJECT (chat));
+       }
+
+       tp_chat_update_remote_contact (chat);
 }
 
 static void
-tp_chat_finalize (GObject *object)
+tp_chat_got_remote_contact_cb (EmpathyTpContactFactory *factory,
+                              EmpathyContact          *contact,
+                              const GError            *error,
+                              gpointer                 user_data,
+                              GObject                 *chat)
 {
-       EmpathyTpChatPriv *priv = GET_PRIV (object);
-       guint              i;
+       EmpathyTpChatPriv *priv = GET_PRIV (chat);
 
-       DEBUG ("Finalize: %p", object);
+       if (error) {
+               DEBUG ("Error: %s", error->message);
+               empathy_tp_chat_close (EMPATHY_TP_CHAT (chat));
+               return;
+       }
 
-       if (priv->properties) {
-               for (i = 0; i < priv->properties->len; i++) {
-                       TpChatProperty *property;
+       priv->remote_contact = g_object_ref (contact);
+       g_object_notify (chat, "remote-contact");
 
-                       property = g_ptr_array_index (priv->properties, i);
-                       g_free (property->name);
-                       if (property->value) {
-                               tp_g_value_slice_free (property->value);
-                       }
-                       g_slice_free (TpChatProperty, property);
-               }
-               g_ptr_array_free (priv->properties, TRUE);
-       }
+       tp_chat_check_if_ready (EMPATHY_TP_CHAT (chat));
+}
 
-       g_queue_free (priv->messages_queue);
-       g_queue_free (priv->pending_messages_queue);
+static void
+tp_chat_got_self_contact_cb (EmpathyTpContactFactory *factory,
+                            EmpathyContact          *contact,
+                            const GError            *error,
+                            gpointer                 user_data,
+                            GObject                 *chat)
+{
+       EmpathyTpChatPriv *priv = GET_PRIV (chat);
 
-       G_OBJECT_CLASS (empathy_tp_chat_parent_class)->finalize (object);
+       if (error) {
+               DEBUG ("Error: %s", error->message);
+               empathy_tp_chat_close (EMPATHY_TP_CHAT (chat));
+               return;
+       }
+
+       priv->user = g_object_ref (contact);
+       empathy_contact_set_is_user (priv->user, TRUE);
+       tp_chat_check_if_ready (EMPATHY_TP_CHAT (chat));
 }
 
 static GObject *
@@ -1013,26 +967,67 @@ tp_chat_constructor (GType                  type,
 {
        GObject           *chat;
        EmpathyTpChatPriv *priv;
-       gboolean           channel_ready;
+       TpConnection      *connection;
+       TpHandle           handle;
 
        chat = G_OBJECT_CLASS (empathy_tp_chat_parent_class)->constructor (type, n_props, props);
 
        priv = GET_PRIV (chat);
-       priv->account = empathy_channel_get_account (priv->channel);
-       priv->factory = empathy_contact_factory_dup_singleton ();
-       priv->user = empathy_contact_factory_get_user (priv->factory, priv->account);
 
+       connection = tp_channel_borrow_connection (priv->channel);
+       priv->factory = empathy_tp_contact_factory_dup_singleton (connection);
        g_signal_connect (priv->channel, "invalidated",
                          G_CALLBACK (tp_chat_invalidated_cb),
                          chat);
 
-       g_object_get (priv->channel, "channel-ready", &channel_ready, NULL);
-       if (channel_ready) {
-               tp_chat_channel_ready_cb (EMPATHY_TP_CHAT (chat));
+       if (tp_proxy_has_interface_by_id (priv->channel,
+                                         TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP)) {
+               const TpIntSet *members;
+               GArray *handles;
+
+               /* Get self contact from the group's self handle */
+               handle = tp_channel_group_get_self_handle (priv->channel);
+               empathy_tp_contact_factory_get_from_handle (priv->factory,
+                       handle, tp_chat_got_self_contact_cb,
+                       NULL, NULL, chat);
+
+               /* Get initial member contacts */
+               members = tp_channel_group_get_members (priv->channel);
+               handles = tp_intset_to_array (members);         
+               empathy_tp_contact_factory_get_from_handles (priv->factory,
+                       handles->len, (TpHandle*) handles->data,
+                       tp_chat_got_added_contacts_cb, NULL, NULL, chat);
+
+               g_signal_connect (priv->channel, "group-members-changed",
+                       G_CALLBACK (tp_chat_group_members_changed_cb), chat);
        } else {
-               g_signal_connect_swapped (priv->channel, "notify::channel-ready",
-                                         G_CALLBACK (tp_chat_channel_ready_cb),
-                                         chat);
+               /* Get the self contact from the connection's self handle */
+               handle = tp_connection_get_self_handle (connection);
+               empathy_tp_contact_factory_get_from_handle (priv->factory,
+                       handle, tp_chat_got_self_contact_cb,
+                       NULL, NULL, chat);
+
+               /* Get the remote contact */
+               handle = tp_channel_get_handle (priv->channel, NULL);
+               empathy_tp_contact_factory_get_from_handle (priv->factory,
+                       handle, tp_chat_got_remote_contact_cb,
+                       NULL, NULL, chat);
+       }
+
+       if (tp_proxy_has_interface_by_id (priv->channel,
+                                         TP_IFACE_QUARK_PROPERTIES_INTERFACE)) {
+               tp_cli_properties_interface_call_list_properties (priv->channel, -1,
+                                                                 tp_chat_list_properties_cb,
+                                                                 NULL, NULL,
+                                                                 G_OBJECT (chat));
+               tp_cli_properties_interface_connect_to_properties_changed (priv->channel,
+                                                                          tp_chat_properties_changed_cb,
+                                                                          NULL, NULL,
+                                                                          G_OBJECT (chat), NULL);
+               tp_cli_properties_interface_connect_to_property_flags_changed (priv->channel,
+                                                                              tp_chat_property_flags_changed_cb,
+                                                                              NULL, NULL,
+                                                                              G_OBJECT (chat), NULL);
        }
 
        return chat;
@@ -1107,6 +1102,7 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass)
                                                              "The remote contact if there is no group iface on the channel",
                                                              EMPATHY_TYPE_CONTACT,
                                                              G_PARAM_READABLE));
+
        g_object_class_install_property (object_class,
                                         PROP_READY,
                                         g_param_spec_boolean ("ready",
@@ -1203,17 +1199,9 @@ empathy_tp_chat_close (EmpathyTpChat *chat) {
        EmpathyTpChatPriv *priv = GET_PRIV (chat);
 
        /* If there are still messages left, it'll come back..
-          We loose the ordering of sent messages though */
-       g_signal_handlers_disconnect_by_func (priv->channel,
-               tp_chat_invalidated_cb, chat);
-
+        * We loose the ordering of sent messages though */
        tp_cli_channel_call_close (priv->channel, -1, tp_chat_async_cb,
                "closing channel", NULL, NULL);
-
-       g_object_unref (priv->channel);
-       priv->channel = NULL;
-
-       g_signal_emit (chat, signals[DESTROY], 0);
 }
 
 const gchar *
@@ -1222,7 +1210,6 @@ empathy_tp_chat_get_id (EmpathyTpChat *chat)
        EmpathyTpChatPriv *priv = GET_PRIV (chat);
 
        g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), NULL);
-       g_return_val_if_fail (priv->ready, NULL);
 
        return tp_channel_get_identifier (priv->channel);
 }
@@ -1233,28 +1220,29 @@ empathy_tp_chat_get_remote_contact (EmpathyTpChat *chat)
        EmpathyTpChatPriv *priv = GET_PRIV (chat);
 
        g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), NULL);
+       g_return_val_if_fail (priv->ready, NULL);
 
        return priv->remote_contact;
 }
 
-McAccount *
-empathy_tp_chat_get_account (EmpathyTpChat *chat)
+TpChannel *
+empathy_tp_chat_get_channel (EmpathyTpChat *chat)
 {
        EmpathyTpChatPriv *priv = GET_PRIV (chat);
 
-       g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), FALSE);
+       g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), NULL);
 
-       return priv->account;
+       return priv->channel;
 }
 
-TpChannel *
-empathy_tp_chat_get_channel (EmpathyTpChat *chat)
+TpConnection *
+empathy_tp_chat_get_connection (EmpathyTpChat *chat)
 {
        EmpathyTpChatPriv *priv = GET_PRIV (chat);
 
        g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), NULL);
 
-       return priv->channel;
+       return tp_channel_borrow_connection (priv->channel);
 }
 
 gboolean
@@ -1267,16 +1255,6 @@ empathy_tp_chat_is_ready (EmpathyTpChat *chat)
        return priv->ready;
 }
 
-guint
-empathy_tp_chat_get_members_count (EmpathyTpChat *chat)
-{
-       EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), 0);
-
-       return priv->members_count;
-}
-
 void
 empathy_tp_chat_send (EmpathyTpChat *chat,
                      EmpathyMessage *message)
@@ -1326,6 +1304,9 @@ empathy_tp_chat_get_pending_messages (EmpathyTpChat *chat)
 {
        EmpathyTpChatPriv *priv = GET_PRIV (chat);
 
+       g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), NULL);
+       g_return_val_if_fail (priv->ready, NULL);
+
        return priv->pending_messages_queue->head;
 }
 
@@ -1346,6 +1327,9 @@ empathy_tp_chat_acknowledge_message (EmpathyTpChat *chat,
        GList *m;
        guint id;
 
+       g_return_if_fail (EMPATHY_IS_TP_CHAT (chat));
+       g_return_if_fail (priv->ready);
+
        if (empathy_message_get_sender (message) == priv->user)
                goto out;
 
@@ -1373,6 +1357,9 @@ empathy_tp_chat_acknowledge_messages (EmpathyTpChat *chat,
        guint length;
        GArray *message_ids;
 
+       g_return_if_fail (EMPATHY_IS_TP_CHAT (chat));
+       g_return_if_fail (priv->ready);
+
        length = g_list_length ((GList *)messages);
 
        if (length == 0)
@@ -1402,3 +1389,4 @@ empathy_tp_chat_acknowledge_messages (EmpathyTpChat *chat,
        g_array_free (message_ids, TRUE);
        g_list_free (msgs);
 }
+
index 353052923fe6b3034b16a5105adeb4c74ca7e552..fadc5f636ea06db8cb7f14d844d159df686ac6f1 100644 (file)
@@ -57,10 +57,9 @@ EmpathyTpChat *empathy_tp_chat_new                  (TpChannel          *channel
 void           empathy_tp_chat_close                (EmpathyTpChat      *chat);
 const gchar *  empathy_tp_chat_get_id               (EmpathyTpChat      *chat);
 EmpathyContact*empathy_tp_chat_get_remote_contact   (EmpathyTpChat      *chat);
-McAccount *    empathy_tp_chat_get_account          (EmpathyTpChat      *chat);
 TpChannel *    empathy_tp_chat_get_channel          (EmpathyTpChat      *chat);
+TpConnection * empathy_tp_chat_get_connection       (EmpathyTpChat      *chat);
 gboolean       empathy_tp_chat_is_ready             (EmpathyTpChat      *chat);
-guint          empathy_tp_chat_get_members_count    (EmpathyTpChat      *chat);
 void           empathy_tp_chat_send                 (EmpathyTpChat      *chat,
                                                     EmpathyMessage     *message);
 void           empathy_tp_chat_set_state            (EmpathyTpChat      *chat,
index f72cc77d19c38b0b263180fb08bb0f6601515323..7735b0f1a19344d16da0573ccc33ca31779e8301 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2009 Collabora Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
 #include <string.h>
 
 #include <telepathy-glib/util.h>
-#include <telepathy-glib/connection.h>
 #include <telepathy-glib/gtypes.h>
-#include <libmissioncontrol/mission-control.h>
 
 #include <extensions/extensions.h>
 
 #include "empathy-tp-contact-factory.h"
 #include "empathy-utils.h"
-#include "empathy-account-manager.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_TP | EMPATHY_DEBUG_CONTACT
 #include "empathy-debug.h"
 
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpContactFactory)
 typedef struct {
-       EmpathyAccountManager *account_manager;
-       McAccount      *account;
        TpConnection   *connection;
-       gboolean        ready;
-
        GList          *contacts;
-       EmpathyContact *user;
 
        gchar         **avatar_mime_types;
        guint           avatar_min_width;
@@ -53,15 +45,14 @@ typedef struct {
        guint           avatar_max_width;
        guint           avatar_max_height;
        guint           avatar_max_size;
-  gboolean        can_request_ft;
+       gboolean        can_request_ft;
 } EmpathyTpContactFactoryPriv;
 
 G_DEFINE_TYPE (EmpathyTpContactFactory, empathy_tp_contact_factory, G_TYPE_OBJECT);
 
 enum {
        PROP_0,
-       PROP_ACCOUNT,
-       PROP_READY,
+       PROP_CONNECTION,
 
        PROP_MIME_TYPES,
        PROP_MIN_WIDTH,
@@ -71,6 +62,11 @@ enum {
        PROP_MAX_SIZE
 };
 
+static TpContactFeature contact_features[] = {
+       TP_CONTACT_FEATURE_ALIAS,
+       TP_CONTACT_FEATURE_PRESENCE,
+};
+
 static EmpathyContact *
 tp_contact_factory_find_by_handle (EmpathyTpContactFactory *tp_factory,
                                   guint                    handle)
@@ -88,14 +84,14 @@ tp_contact_factory_find_by_handle (EmpathyTpContactFactory *tp_factory,
 }
 
 static EmpathyContact *
-tp_contact_factory_find_by_id (EmpathyTpContactFactory *tp_factory,
-                              const gchar             *id)
+tp_contact_factory_find_by_tp_contact (EmpathyTpContactFactory *tp_factory,
+                                      TpContact               *tp_contact)
 {
        EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
        GList                       *l;
 
        for (l = priv->contacts; l; l = l->next) {
-               if (!tp_strdiff (empathy_contact_get_id (l->data), id)) {
+               if (empathy_contact_get_tp_contact (l->data) == tp_contact) {
                        return l->data;
                }
        }
@@ -114,104 +110,6 @@ tp_contact_factory_weak_notify (gpointer data,
        priv->contacts = g_list_remove (priv->contacts, where_the_object_was);
 }
 
-static void
-tp_contact_factory_presences_table_foreach (const gchar    *state_str,
-                                           GHashTable     *presences_table,
-                                           EmpathyContact *contact)
-{
-       const GValue *message;
-       const gchar  *message_str = NULL;
-
-       empathy_contact_set_presence (contact,
-                                     empathy_presence_from_str (state_str));
-       
-       message = g_hash_table_lookup (presences_table, "message");
-       if (message) {
-               message_str = g_value_get_string (message);
-       }
-
-       if (!EMP_STR_EMPTY (message_str)) {
-               empathy_contact_set_presence_message (contact, message_str);
-       } else {
-               empathy_contact_set_presence_message (contact, NULL);
-       }
-}
-
-static void
-tp_contact_factory_parse_presence_foreach (guint                    handle,
-                                          GValueArray             *presence_struct,
-                                          EmpathyTpContactFactory *tp_factory)
-{
-       GHashTable      *presences_table;
-       EmpathyContact  *contact;
-
-       contact = tp_contact_factory_find_by_handle (tp_factory, handle);
-       if (!contact) {
-               return;
-       }
-
-       presences_table = g_value_get_boxed (g_value_array_get_nth (presence_struct, 1));
-
-       g_hash_table_foreach (presences_table,
-                             (GHFunc) tp_contact_factory_presences_table_foreach,
-                             contact);
-
-       DEBUG ("Changing presence for contact %s (%d) to '%s' (%d)",
-               empathy_contact_get_id (contact),
-               handle,
-               empathy_contact_get_presence_message (contact),
-               empathy_contact_get_presence (contact));
-}
-
-static void
-tp_contact_factory_get_presence_cb (TpConnection *connection,
-                                   GHashTable   *handle_table,
-                                   const GError *error,
-                                   gpointer      user_data,
-                                   GObject      *tp_factory)
-{
-       if (error) {
-               DEBUG ("Error getting presence: %s", error->message);
-               if (error->domain == TP_DBUS_ERRORS &&
-                   error->code == TP_DBUS_ERROR_NO_INTERFACE) {
-                       guint *handles = user_data;
-
-                       /* We have no presence iface, set default presence
-                        * to available */
-                       while (*handles != 0) {
-                               EmpathyContact *contact;
-
-                               contact = tp_contact_factory_find_by_handle (
-                                       (EmpathyTpContactFactory*) tp_factory,
-                                       *handles);
-                               if (contact) {
-                                       empathy_contact_set_presence (contact,
-                                                                     MC_PRESENCE_AVAILABLE);
-                               }
-
-                               handles++;
-                       }
-               }
-
-               return;
-       }
-
-       g_hash_table_foreach (handle_table,
-                             (GHFunc) tp_contact_factory_parse_presence_foreach,
-                             EMPATHY_TP_CONTACT_FACTORY (tp_factory));
-}
-
-static void
-tp_contact_factory_presence_update_cb (TpConnection *connection,
-                                      GHashTable   *handle_table,
-                                      gpointer      user_data,
-                                      GObject      *tp_factory)
-{
-       g_hash_table_foreach (handle_table,
-                             (GHFunc) tp_contact_factory_parse_presence_foreach,
-                             EMPATHY_TP_CONTACT_FACTORY (tp_factory));
-}
-
 static void
 tp_contact_factory_set_aliases_cb (TpConnection *connection,
                                   const GError *error,
@@ -219,92 +117,7 @@ tp_contact_factory_set_aliases_cb (TpConnection *connection,
                                   GObject      *tp_factory)
 {
        if (error) {
-               DEBUG ("Error setting alias: %s", error->message);
-       }
-}
-
-static void
-tp_contact_factory_request_aliases_cb (TpConnection *connection,
-                                      const gchar  **contact_names,
-                                      const GError  *error,
-                                      gpointer       user_data,
-                                      GObject       *tp_factory)
-{
-       guint        *handles = user_data;
-       guint         i = 0;
-       const gchar **name;
-
-       if (error) {
-               DEBUG ("Error requesting aliases: %s", error->message);
-
-               /* If we failed to get alias set it to NULL, like that if
-                * someone is waiting for the name to be ready it won't wait
-                * infinitely */
-               while (*handles != 0) {
-                       EmpathyContact *contact;
-
-                       contact = tp_contact_factory_find_by_handle (
-                               (EmpathyTpContactFactory*) tp_factory,
-                               *handles);
-                       if (contact) {
-                               empathy_contact_set_name (contact, NULL);
-                       }
-
-                       handles++;
-               }
-               return;
-       }
-
-       for (name = contact_names; *name; name++) {
-               EmpathyContact *contact;
-
-               contact = tp_contact_factory_find_by_handle (EMPATHY_TP_CONTACT_FACTORY (tp_factory),
-                                                            handles[i]);
-               if (!contact) {
-                       continue;
-               }
-
-               DEBUG ("Renaming contact %s (%d) to %s (request cb)",
-                       empathy_contact_get_id (contact),
-                       empathy_contact_get_handle (contact),
-                       *name);
-
-               empathy_contact_set_name (contact, *name);
-
-               i++;
-       }
-}
-
-static void
-tp_contact_factory_aliases_changed_cb (TpConnection    *connection,
-                                      const GPtrArray *renamed_handlers,
-                                      gpointer         user_data,
-                                      GObject         *weak_object)
-{
-       EmpathyTpContactFactory *tp_factory = EMPATHY_TP_CONTACT_FACTORY (weak_object);
-       guint                    i;
-
-       for (i = 0; renamed_handlers->len > i; i++) {
-               guint           handle;
-               const gchar    *alias;
-               GValueArray    *renamed_struct;
-               EmpathyContact *contact;
-
-               renamed_struct = g_ptr_array_index (renamed_handlers, i);
-               handle = g_value_get_uint (g_value_array_get_nth (renamed_struct, 0));
-               alias = g_value_get_string (g_value_array_get_nth (renamed_struct, 1));
-               contact = tp_contact_factory_find_by_handle (tp_factory, handle);
-
-               if (!contact) {
-                       /* We don't know this contact, skip */
-                       continue;
-               }
-
-               DEBUG ("Renaming contact %s (%d) to %s (changed cb)",
-                       empathy_contact_get_id (contact),
-                       handle, alias);
-
-               empathy_contact_set_name (contact, alias);
+               DEBUG ("Error: %s", error->message);
        }
 }
 
@@ -316,7 +129,7 @@ tp_contact_factory_set_avatar_cb (TpConnection *connection,
                                  GObject      *tp_factory)
 {
        if (error) {
-               DEBUG ("Error setting avatar: %s", error->message);
+               DEBUG ("Error: %s", error->message);
        }
 }
 
@@ -327,7 +140,7 @@ tp_contact_factory_clear_avatar_cb (TpConnection *connection,
                                    GObject      *tp_factory)
 {
        if (error) {
-               DEBUG ("Error clearing avatar: %s", error->message);
+               DEBUG ("Error: %s", error->message);
        }
 }
 
@@ -366,7 +179,7 @@ tp_contact_factory_request_avatars_cb (TpConnection *connection,
                                       GObject      *tp_factory)
 {
        if (error) {
-               DEBUG ("Error requesting avatars: %s", error->message);
+               DEBUG ("Error: %s", error->message);
        }
 }
 
@@ -426,20 +239,19 @@ tp_contact_factory_avatar_tokens_foreach (gpointer key,
 }
 
 static void
-tp_contact_factory_get_known_avatar_tokens_cb (TpConnection *connection,
-                                              GHashTable   *tokens,
-                                              const GError *error,
-                                              gpointer      user_data,
-                                              GObject      *tp_factory)
+tp_contact_factory_got_known_avatar_tokens (EmpathyTpContactFactory *tp_factory,
+                                           GHashTable              *tokens,
+                                           const GError            *error)
 {
+       EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
        TokensData data;
 
        if (error) {
-               DEBUG ("Error getting known avatars tokens: %s", error->message);
+               DEBUG ("Error: %s", error->message);
                return;
        }
 
-       data.tp_factory = EMPATHY_TP_CONTACT_FACTORY (tp_factory);
+       data.tp_factory = tp_factory;
        data.handles = g_array_new (FALSE, FALSE, sizeof (guint));
        g_hash_table_foreach (tokens,
                              tp_contact_factory_avatar_tokens_foreach,
@@ -450,15 +262,16 @@ tp_contact_factory_get_known_avatar_tokens_cb (TpConnection *connection,
 
        /* Request needed avatars */
        if (data.handles->len > 0) {
-               tp_cli_connection_interface_avatars_call_request_avatars (connection,
+               tp_cli_connection_interface_avatars_call_request_avatars (priv->connection,
                                                                          -1,
                                                                          data.handles,
                                                                          tp_contact_factory_request_avatars_cb,
                                                                          NULL, NULL,
-                                                                         tp_factory);
+                                                                         G_OBJECT (tp_factory));
        }
 
        g_array_free (data.handles, TRUE);
+       g_hash_table_destroy (tokens);
 }
 
 static void
@@ -528,17 +341,14 @@ tp_contact_factory_update_capabilities (EmpathyTpContactFactory *tp_factory,
 }
 
 static void
-tp_contact_factory_get_capabilities_cb (TpConnection    *connection,
-                                       const GPtrArray *capabilities,
-                                       const GError    *error,
-                                       gpointer         user_data,
-                                       GObject         *weak_object)
+tp_contact_factory_got_capabilities (EmpathyTpContactFactory *tp_factory,
+                                    GPtrArray *capabilities,
+                                    const GError    *error)
 {
-       EmpathyTpContactFactory *tp_factory = EMPATHY_TP_CONTACT_FACTORY (weak_object);
-       guint                    i;
+       guint i;
 
        if (error) {
-               DEBUG ("Error getting capabilities: %s", error->message);
+               DEBUG ("Error: %s", error->message);
                /* FIXME Should set the capabilities of the contacts for which this request
                 * originated to NONE */
                return;
@@ -562,7 +372,11 @@ tp_contact_factory_get_capabilities_cb (TpConnection    *connection,
                                                        channel_type,
                                                        generic,
                                                        specific);
+
+               g_value_array_free (values);
        }
+
+       g_ptr_array_free (capabilities, TRUE);
 }
 
 static void
@@ -595,231 +409,6 @@ tp_contact_factory_capabilities_changed_cb (TpConnection    *connection,
        }
 }
 
-static void
-tp_contact_factory_request_everything (EmpathyTpContactFactory *tp_factory,
-                                      const GArray            *handles)
-{
-       EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
-       guint                       *dup_handles;
-
-       g_return_if_fail (priv->ready);
-
-       dup_handles = g_malloc0 ((handles->len + 1) * sizeof (guint));
-       g_memmove (dup_handles, handles->data, handles->len * sizeof (guint));
-       tp_cli_connection_interface_presence_call_get_presence (priv->connection,
-                                                               -1,
-                                                               handles,
-                                                               tp_contact_factory_get_presence_cb,
-                                                               dup_handles, g_free,
-                                                               G_OBJECT (tp_factory));
-
-       /* FIXME: Sometimes the dbus call timesout because CM takes
-        * too much time to request all aliases from the server,
-        * that's why we increase the timeout here. See fd.o bug #14795 */
-       dup_handles = g_malloc0 ((handles->len + 1) * sizeof (guint));
-       g_memmove (dup_handles, handles->data, handles->len * sizeof (guint));
-       tp_cli_connection_interface_aliasing_call_request_aliases (priv->connection,
-                                                                  5*60*1000,
-                                                                  handles,
-                                                                  tp_contact_factory_request_aliases_cb,
-                                                                  dup_handles, g_free,
-                                                                  G_OBJECT (tp_factory));
-
-       tp_cli_connection_interface_avatars_call_get_known_avatar_tokens (priv->connection,
-                                                                         -1,
-                                                                         handles,
-                                                                         tp_contact_factory_get_known_avatar_tokens_cb,
-                                                                         NULL, NULL,
-                                                                         G_OBJECT (tp_factory));
-
-       tp_cli_connection_interface_capabilities_call_get_capabilities (priv->connection,
-                                                                       -1,
-                                                                       handles,
-                                                                       tp_contact_factory_get_capabilities_cb,
-                                                                       NULL, NULL,
-                                                                       G_OBJECT (tp_factory));
-}
-
-static void
-tp_contact_factory_list_free (gpointer data)
-{
-       GList *l = data;
-
-       g_list_foreach (l, (GFunc) g_object_unref, NULL);
-       g_list_free (l);
-}
-
-static void
-tp_contact_factory_request_handles_cb (TpConnection *connection,
-                                      const GArray *handles,
-                                      const GError *error,
-                                      gpointer      user_data,
-                                      GObject      *tp_factory)
-{
-       GList *contacts = user_data;
-       GList *l;
-       guint  i = 0;
-
-       if (error) {
-               DEBUG ("Failed to request handles: %s", error->message);
-               return;
-       }
-
-       for (l = contacts; l; l = l->next) {
-               guint handle;
-
-               handle = g_array_index (handles, guint, i);
-               empathy_contact_set_handle (l->data, handle);
-
-               i++;
-       }
-
-       tp_contact_factory_request_everything (EMPATHY_TP_CONTACT_FACTORY (tp_factory),
-                                              handles);
-}
-
-static void
-tp_contact_factory_inspect_handles_cb (TpConnection  *connection,
-                                      const gchar  **ids,
-                                      const GError  *error,
-                                      gpointer       user_data,
-                                      GObject       *tp_factory)
-{
-       const gchar **id;
-       GList        *contacts = user_data;
-       GList        *l;
-
-       if (error) {
-               DEBUG ("Failed to inspect handles: %s", error->message);
-               return;
-       }
-
-       id = ids;
-       for (l = contacts; l; l = l->next) {
-               empathy_contact_set_id (l->data, *id);
-               id++;
-       }
-}
-
-static void
-tp_contact_factory_disconnect_contact_foreach (gpointer data,
-                                              gpointer user_data)
-{
-       EmpathyContact *contact = data;
-       
-       empathy_contact_set_presence (contact, MC_PRESENCE_UNSET);
-       empathy_contact_set_handle (contact, 0);
-}
-
-static void
-tp_contact_factory_connection_invalidated_cb (EmpathyTpContactFactory *tp_factory)
-{
-       EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
-
-       DEBUG ("Connection invalidated");
-
-       g_object_unref (priv->connection);
-       priv->connection = NULL;
-       priv->ready = FALSE;
-       g_object_notify (G_OBJECT (tp_factory), "ready");
-
-
-       g_list_foreach (priv->contacts,
-                       tp_contact_factory_disconnect_contact_foreach,
-                       tp_factory);
-}
-
-static void
-tp_contact_factory_ready (EmpathyTpContactFactory *tp_factory)
-{
-       EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
-       GList                       *l;
-       GArray                      *handle_needed;
-       GArray                      *id_needed;
-       GList                       *handle_needed_contacts = NULL;
-       GList                       *id_needed_contacts = NULL;
-
-       DEBUG ("Connection ready");
-
-       priv->ready = TRUE;
-       g_object_notify (G_OBJECT (tp_factory), "ready");
-
-       /* Connect signals */
-       tp_cli_connection_interface_aliasing_connect_to_aliases_changed (priv->connection,
-                                                                        tp_contact_factory_aliases_changed_cb,
-                                                                        NULL, NULL,
-                                                                        G_OBJECT (tp_factory),
-                                                                        NULL);
-       tp_cli_connection_interface_avatars_connect_to_avatar_updated (priv->connection,
-                                                                      tp_contact_factory_avatar_updated_cb,
-                                                                      NULL, NULL,
-                                                                      G_OBJECT (tp_factory),
-                                                                      NULL);
-       tp_cli_connection_interface_avatars_connect_to_avatar_retrieved (priv->connection,
-                                                                        tp_contact_factory_avatar_retrieved_cb,
-                                                                        NULL, NULL,
-                                                                        G_OBJECT (tp_factory),
-                                                                        NULL);
-       tp_cli_connection_interface_presence_connect_to_presence_update (priv->connection,
-                                                                        tp_contact_factory_presence_update_cb,
-                                                                        NULL, NULL,
-                                                                        G_OBJECT (tp_factory),
-                                                                        NULL);
-       tp_cli_connection_interface_capabilities_connect_to_capabilities_changed (priv->connection,
-                                                                                 tp_contact_factory_capabilities_changed_cb,
-                                                                                 NULL, NULL,
-                                                                                 G_OBJECT (tp_factory),
-                                                                                 NULL);
-
-       /* Request needed info for all existing contacts */
-       handle_needed = g_array_new (TRUE, FALSE, sizeof (gchar*));
-       id_needed = g_array_new (FALSE, FALSE, sizeof (guint));
-       for (l = priv->contacts; l; l = l->next) {
-               EmpathyContact *contact;
-               guint           handle;
-               const gchar    *id;
-
-               contact = l->data;
-               handle = empathy_contact_get_handle (contact);
-               id = empathy_contact_get_id (contact);
-               if (handle == 0) {
-                       g_assert (!EMP_STR_EMPTY (id));
-                       g_array_append_val (handle_needed, id);
-                       handle_needed_contacts = g_list_prepend (handle_needed_contacts,
-                                                                g_object_ref (contact));
-               }
-               if (EMP_STR_EMPTY (id)) {
-                       g_array_append_val (id_needed, handle);
-                       id_needed_contacts = g_list_prepend (id_needed_contacts,
-                                                            g_object_ref (contact));
-               }
-       }
-       handle_needed_contacts = g_list_reverse (handle_needed_contacts);
-       id_needed_contacts = g_list_reverse (id_needed_contacts);
-
-       tp_cli_connection_call_request_handles (priv->connection,
-                                               -1,
-                                               TP_HANDLE_TYPE_CONTACT,
-                                               (const gchar**) handle_needed->data,
-                                               tp_contact_factory_request_handles_cb,
-                                               handle_needed_contacts, tp_contact_factory_list_free,
-                                               G_OBJECT (tp_factory));
-
-       tp_cli_connection_call_inspect_handles (priv->connection,
-                                               -1,
-                                               TP_HANDLE_TYPE_CONTACT,
-                                               id_needed,
-                                               tp_contact_factory_inspect_handles_cb,
-                                               id_needed_contacts, tp_contact_factory_list_free,
-                                               G_OBJECT (tp_factory));
-
-       tp_contact_factory_request_everything ((EmpathyTpContactFactory*) tp_factory,
-                                              id_needed);
-
-       g_array_free (handle_needed, TRUE);
-       g_array_free (id_needed, TRUE);
-}
-
 static void
 get_requestable_channel_classes_cb (TpProxy *connection,
                                    const GValue *value,
@@ -834,7 +423,6 @@ get_requestable_channel_classes_cb (TpProxy *connection,
 
        if (error != NULL) {
                DEBUG ("Error: %s", error->message);
-               tp_contact_factory_ready (self);
                return;
        }
 
@@ -877,8 +465,6 @@ get_requestable_channel_classes_cb (TpProxy *connection,
                }
                break;
        }
-
-       tp_contact_factory_ready (self);
 }
 
 static void
@@ -909,303 +495,377 @@ tp_contact_factory_got_avatar_requirements_cb (TpConnection *proxy,
                priv->avatar_max_height = max_height;
                priv->avatar_max_size = max_size;
        }
-
-       /* Can we request file transfer channels? */
-       tp_cli_dbus_properties_call_get (priv->connection, -1,
-               TP_IFACE_CONNECTION_INTERFACE_REQUESTS,
-               "RequestableChannelClasses",
-               get_requestable_channel_classes_cb, NULL, NULL,
-               G_OBJECT (tp_factory));
 }
 
 static void
-tp_contact_factory_got_self_handle_cb (TpConnection *proxy,
-                                      guint         handle,
-                                      const GError *error,
-                                      gpointer      user_data,
-                                      GObject      *tp_factory)
+tp_contact_factory_add_contact (EmpathyTpContactFactory *tp_factory,
+                               EmpathyContact          *contact)
 {
        EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
+       TpHandle self_handle;
+       TpHandle handle;
+       GArray handles = {(gchar*) &handle, 1};
+       GHashTable *tokens;
+       GPtrArray *capabilities;
+       GError *error = NULL;
+
+       /* Keep a weak ref to that contact */
+       g_object_weak_ref (G_OBJECT (contact),
+                          tp_contact_factory_weak_notify,
+                          tp_factory);
+       priv->contacts = g_list_prepend (priv->contacts, contact);
 
-       if (error) {
-               DEBUG ("Failed to get self handles: %s", error->message);
-               return;
+       /* The contact keeps a ref to its factory */
+       g_object_set_data_full (G_OBJECT (contact), "empathy-factory",
+                               g_object_ref (tp_factory),
+                               g_object_unref);
+
+       /* Set the FT capability */
+       if (priv->can_request_ft) {
+               EmpathyCapabilities caps;
+
+               caps = empathy_contact_get_capabilities (contact);
+               caps |= EMPATHY_CAPABILITIES_FT;
+
+               empathy_contact_set_capabilities (contact, caps);
        }
 
-       empathy_contact_set_handle (priv->user, handle);
+       /* Set is-user property. Note that it could still be the handle is
+        * different from the connection's self handle, in the case the handle
+        * comes from a group interface. */
+       self_handle = tp_connection_get_self_handle (priv->connection);
+       handle = empathy_contact_get_handle (contact);
+       empathy_contact_set_is_user (contact, self_handle == handle);
+
+       /* FIXME: This should be done by TpContact */
+       tp_cli_connection_interface_avatars_run_get_known_avatar_tokens (priv->connection,
+                                                                        -1,
+                                                                        &handles,
+                                                                        &tokens,
+                                                                        &error,
+                                                                        NULL);
+       tp_contact_factory_got_known_avatar_tokens (tp_factory, tokens, error);
+       g_clear_error (&error);
+
+       tp_cli_connection_interface_capabilities_run_get_capabilities (priv->connection,
+                                                                       -1,
+                                                                       &handles,
+                                                                       &capabilities,
+                                                                       &error,
+                                                                       NULL);
+       tp_contact_factory_got_capabilities (tp_factory, capabilities, error);
+       g_clear_error (&error);
 
-       /* Get avatar requirements for this connection */
-       tp_cli_connection_interface_avatars_call_get_avatar_requirements (
-               priv->connection,
-               -1,
-               tp_contact_factory_got_avatar_requirements_cb,
-               NULL, NULL,
-               tp_factory);
+       DEBUG ("Contact added: %s (%d)",
+               empathy_contact_get_id (contact),
+               empathy_contact_get_handle (contact));
 }
 
-static void
-tp_contact_factory_connection_ready_cb (EmpathyTpContactFactory *tp_factory)
-{
-       EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
+typedef union {
+       EmpathyTpContactFactoryContactsByIdCb ids_cb;
+       EmpathyTpContactFactoryContactsByHandleCb handles_cb;
+       EmpathyTpContactFactoryContactCb contact_cb;
+} GetContactsCb;
 
-       /* Get our own handle */
-       tp_cli_connection_call_get_self_handle (priv->connection,
-                                               -1,
-                                               tp_contact_factory_got_self_handle_cb,
-                                               NULL, NULL,
-                                               G_OBJECT (tp_factory));
-}
+typedef struct {
+       EmpathyTpContactFactory *tp_factory;
+       GetContactsCb callback;
+       gpointer user_data;
+       GDestroyNotify destroy;
+} GetContactsData;
 
 static void
-tp_contact_factory_status_updated (EmpathyTpContactFactory *tp_factory)
+get_contacts_data_free (gpointer user_data)
 {
-       EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
-       gboolean                     connection_ready;
-       MissionControl              *mc;
+       GetContactsData *data = user_data;
 
-       if (priv->connection) {
-               /* We already have our connection object */
-               return;
+       if (data->destroy) {
+               data->destroy (data->user_data);
        }
+       g_object_unref (data->tp_factory);
 
-       mc = empathy_mission_control_dup_singleton ();
-       priv->connection = mission_control_get_tpconnection (mc, priv->account, NULL);
-       if (!priv->connection) {
-               return;
-       }
+       g_slice_free (GetContactsData, data);
+}
 
-       /* We got a new connection, wait for it to be ready */
-       g_signal_connect_swapped (priv->connection, "invalidated",
-                                 G_CALLBACK (tp_contact_factory_connection_invalidated_cb),
-                                 tp_factory);
+static EmpathyContact *
+dup_contact_for_tp_contact (EmpathyTpContactFactory *tp_factory,
+                           TpContact               *tp_contact)
+{
+       EmpathyContact *contact;
+
+       contact = tp_contact_factory_find_by_tp_contact (tp_factory,
+                                                        tp_contact);
 
-       g_object_get (priv->connection, "connection-ready", &connection_ready, NULL);
-       if (connection_ready) {
-               tp_contact_factory_connection_ready_cb (tp_factory);
+       if (contact != NULL) {
+               g_object_ref (contact);
        } else {
-               g_signal_connect_swapped (priv->connection, "notify::connection-ready",
-                                         G_CALLBACK (tp_contact_factory_connection_ready_cb),
-                                         tp_factory);
+               contact = empathy_contact_new (tp_contact);
+               tp_contact_factory_add_contact (tp_factory, contact);
        }
 
-       g_object_unref (mc);
+       return contact;
 }
 
-static void
-tp_contact_factory_account_connection_cb (EmpathyAccountManager *account_manager,
-                                         McAccount *account,
-                                         TpConnectionStatusReason reason,
-                                         TpConnectionStatus current,
-                                         TpConnectionStatus previous,
-                                         EmpathyTpContactFactory  *tp_factory)
+static EmpathyContact **
+contacts_array_new (EmpathyTpContactFactory *tp_factory,
+                   guint                    n_contacts,
+                   TpContact * const *      contacts)
 {
-       EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
+       EmpathyContact **ret;
+       guint            i;
 
-       if (account && empathy_account_equal (account, priv->account)) {
-               tp_contact_factory_status_updated (tp_factory);
+       ret = g_new0 (EmpathyContact *, n_contacts);
+       for (i = 0; i < n_contacts; i++) {
+               ret[i] = dup_contact_for_tp_contact (tp_factory, contacts[i]);
        }
+
+       return ret;
 }
 
 static void
-tp_contact_factory_add_contact (EmpathyTpContactFactory *tp_factory,
-                               EmpathyContact          *contact)
+contacts_array_free (guint            n_contacts,
+                    EmpathyContact **contacts)
 {
-       EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
-
-       g_object_weak_ref (G_OBJECT (contact),
-                          tp_contact_factory_weak_notify,
-                          tp_factory);
-       priv->contacts = g_list_prepend (priv->contacts, contact);
+       guint i;
 
-       DEBUG ("Contact added: %s (%d)",
-               empathy_contact_get_id (contact),
-               empathy_contact_get_handle (contact));
+       for (i = 0; i < n_contacts; i++) {
+               g_object_unref (contacts[i]);
+       }
+       g_free (contacts);
 }
 
 static void
-tp_contact_factory_hold_handles_cb (TpConnection *connection,
-                                   const GError *error,
-                                   gpointer      userdata,
-                                   GObject      *tp_factory)
+get_contacts_by_id_cb (TpConnection *connection,
+                      guint n_contacts,
+                      TpContact * const *contacts,
+                      const gchar * const *requested_ids,
+                      GHashTable *failed_id_errors,
+                      const GError *error,
+                      gpointer user_data,
+                      GObject *weak_object)
 {
-       if (error) {
-               DEBUG ("Failed to hold handles: %s", error->message);
+       GetContactsData *data = user_data;
+       EmpathyContact **empathy_contacts;
+
+       empathy_contacts = contacts_array_new (data->tp_factory,
+                                              n_contacts, contacts);
+       if (data->callback.ids_cb) {
+               data->callback.ids_cb (data->tp_factory,
+                                      n_contacts, empathy_contacts,
+                                      requested_ids,
+                                      failed_id_errors,
+                                      error,
+                                      data->user_data, weak_object);
        }
+
+       contacts_array_free (n_contacts, empathy_contacts);
 }
 
-EmpathyContact *
-empathy_tp_contact_factory_get_user (EmpathyTpContactFactory *tp_factory)
+void
+empathy_tp_contact_factory_get_from_ids (EmpathyTpContactFactory *tp_factory,
+                                        guint                    n_ids,
+                                        const gchar * const     *ids,
+                                        EmpathyTpContactFactoryContactsByIdCb callback,
+                                        gpointer                 user_data,
+                                        GDestroyNotify           destroy,
+                                        GObject                 *weak_object)
 {
        EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
+       GetContactsData *data;
 
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory), NULL);
-
-       return g_object_ref (priv->user);
+       g_return_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory));
+       g_return_if_fail (ids != NULL);
+
+       data = g_slice_new (GetContactsData);
+       data->callback.ids_cb = callback;
+       data->user_data = user_data;
+       data->destroy = destroy;
+       data->tp_factory = g_object_ref (tp_factory);
+       tp_connection_get_contacts_by_id (priv->connection,
+                                         n_ids, ids,
+                                         G_N_ELEMENTS (contact_features),
+                                         contact_features,
+                                         get_contacts_by_id_cb,
+                                         data,
+                                         (GDestroyNotify) get_contacts_data_free,
+                                         weak_object);
 }
 
 static void
-contact_created (EmpathyTpContactFactory *self,
-                 EmpathyContact *contact)
+get_contact_by_id_cb (TpConnection *connection,
+                     guint n_contacts,
+                     TpContact * const *contacts,
+                     const gchar * const *requested_ids,
+                     GHashTable *failed_id_errors,
+                     const GError *error,
+                     gpointer user_data,
+                     GObject *weak_object)
 {
-  EmpathyTpContactFactoryPriv *priv = GET_PRIV (self);
-
-  if (priv->can_request_ft)
-    {
-      /* Set the FT capability */
-      /* FIXME: We should use the futur ContactCapabilities interface */
-      EmpathyCapabilities caps;
-
-      caps = empathy_contact_get_capabilities (contact);
-      caps |= EMPATHY_CAPABILITIES_FT;
+       GetContactsData *data = user_data;
+       EmpathyContact  *contact = NULL;
 
-      empathy_contact_set_capabilities (contact, caps);
-    }
+       if (n_contacts == 1) {
+               contact = dup_contact_for_tp_contact (data->tp_factory,
+                                                     contacts[0]);
+       }
+       else if (error == NULL) {
+               GHashTableIter iter;
+               gpointer       value;
+
+               g_hash_table_iter_init (&iter, failed_id_errors);
+               while (g_hash_table_iter_next (&iter, NULL, &value)) {
+                       if (value) {
+                               error = value;
+                               break;
+                       }
+               }
+       }
 
-  tp_contact_factory_add_contact (self, contact);
+       if (data->callback.contact_cb) {
+               data->callback.contact_cb (data->tp_factory,
+                                          contact,
+                                          error,
+                                          data->user_data, weak_object);
+       }
 }
 
-EmpathyContact *
+void
 empathy_tp_contact_factory_get_from_id (EmpathyTpContactFactory *tp_factory,
-                                       const gchar             *id)
+                                       const gchar             *id,
+                                       EmpathyTpContactFactoryContactCb callback,
+                                       gpointer                 user_data,
+                                       GDestroyNotify           destroy,
+                                       GObject                 *weak_object)
 {
        EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
-       EmpathyContact              *contact;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory), NULL);
-       g_return_val_if_fail (id != NULL, NULL);
-
-       /* Check if the contact already exists */
-       contact = tp_contact_factory_find_by_id (tp_factory, id);
-       if (contact) {
-               return g_object_ref (contact);
-       }
-
-       /* Create new contact */
-       contact = g_object_new (EMPATHY_TYPE_CONTACT,
-                               "account", priv->account,
-                               "id", id,
-                               NULL);
-       contact_created (tp_factory, contact);
-
-       if (priv->ready) {
-               const gchar *contact_ids[] = {id, NULL};
-               GList       *contacts;
-               
-               contacts = g_list_prepend (NULL, g_object_ref (contact));
-               tp_cli_connection_call_request_handles (priv->connection,
-                                                       -1,
-                                                       TP_HANDLE_TYPE_CONTACT,
-                                                       contact_ids,
-                                                       tp_contact_factory_request_handles_cb,
-                                                       contacts, tp_contact_factory_list_free,
-                                                       G_OBJECT (tp_factory));
-       }
+       GetContactsData *data;
 
-       return contact;
+       g_return_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory));
+       g_return_if_fail (id != NULL);
+
+       data = g_slice_new (GetContactsData);
+       data->callback.contact_cb = callback;
+       data->user_data = user_data;
+       data->destroy = destroy;
+       data->tp_factory = g_object_ref (tp_factory);
+       tp_connection_get_contacts_by_id (priv->connection,
+                                         1, &id,
+                                         G_N_ELEMENTS (contact_features),
+                                         contact_features,
+                                         get_contact_by_id_cb,
+                                         data,
+                                         (GDestroyNotify) get_contacts_data_free,
+                                         weak_object);
 }
 
-EmpathyContact *
-empathy_tp_contact_factory_get_from_handle (EmpathyTpContactFactory *tp_factory,
-                                           guint                    handle)
+static void
+get_contacts_by_handle_cb (TpConnection *connection,
+                          guint n_contacts,
+                          TpContact * const *contacts,
+                          guint n_failed,
+                          const TpHandle *failed,
+                          const GError *error,
+                          gpointer user_data,
+                          GObject *weak_object)
 {
-       EmpathyContact *contact;
-       GArray         *handles;
-       GList          *contacts;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory), NULL);
-
-       handles = g_array_new (FALSE, FALSE, sizeof (guint));
-       g_array_append_val (handles, handle);
-
-       contacts = empathy_tp_contact_factory_get_from_handles (tp_factory, handles);
-       g_array_free (handles, TRUE);
-
-       contact = contacts ? contacts->data : NULL;
-       g_list_free (contacts);
+       GetContactsData *data = user_data;
+       EmpathyContact **empathy_contacts;
+
+       empathy_contacts = contacts_array_new (data->tp_factory,
+                                              n_contacts, contacts);
+       if (data->callback.handles_cb) {
+               data->callback.handles_cb (data->tp_factory,
+                                          n_contacts, empathy_contacts,
+                                          n_failed, failed,
+                                          error,
+                                          data->user_data, weak_object);
+       }
 
-       return contact;
+       contacts_array_free (n_contacts, empathy_contacts);
 }
 
-GList *
+void
 empathy_tp_contact_factory_get_from_handles (EmpathyTpContactFactory *tp_factory,
-                                            const GArray            *handles)
+                                            guint n_handles,
+                                            const TpHandle *handles,
+                                            EmpathyTpContactFactoryContactsByHandleCb callback,
+                                            gpointer                 user_data,
+                                            GDestroyNotify           destroy,
+                                            GObject                 *weak_object)
 {
        EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
-       GList                       *contacts = NULL;
-       GArray                      *new_handles;
-       GList                       *new_contacts = NULL;
-       guint                        i;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory), NULL);
-       g_return_val_if_fail (handles != NULL, NULL);
+       GetContactsData *data;
 
-       /* Search all contacts we already have */
-       new_handles = g_array_new (FALSE, FALSE, sizeof (guint));
-       for (i = 0; i < handles->len; i++) {
-               EmpathyContact *contact;
-               guint           handle;
+       g_return_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory));
+       g_return_if_fail (handles != NULL);
+
+       data = g_slice_new (GetContactsData);
+       data->callback.handles_cb = callback;
+       data->user_data = user_data;
+       data->destroy = destroy;
+       data->tp_factory = g_object_ref (tp_factory);
+       tp_connection_get_contacts_by_handle (priv->connection,
+                                             n_handles, handles,
+                                             G_N_ELEMENTS (contact_features),
+                                             contact_features,
+                                             get_contacts_by_handle_cb,
+                                             data,
+                                             (GDestroyNotify) get_contacts_data_free,
+                                             weak_object);
+}
 
-               handle = g_array_index (handles, guint, i);
-               if (handle == 0) {
-                       continue;
-               }
+static void
+get_contact_by_handle_cb (TpConnection *connection,
+                         guint n_contacts,
+                         TpContact * const *contacts,
+                         guint n_failed,
+                         const TpHandle *failed,
+                         const GError *error,
+                         gpointer user_data,
+                         GObject *weak_object)
+{
+       GetContactsData *data = user_data;
+       EmpathyContact  *contact = NULL;
 
-               contact = tp_contact_factory_find_by_handle (tp_factory, handle);
-               if (contact) {
-                       contacts = g_list_prepend (contacts, g_object_ref (contact));
-               } else {
-                       g_array_append_val (new_handles, handle);
-               }
+       if (n_contacts == 1) {
+               contact = dup_contact_for_tp_contact (data->tp_factory,
+                                                     contacts[0]);
        }
 
-       if (new_handles->len == 0) {
-               g_array_free (new_handles, TRUE);
-               return contacts;
+       if (data->callback.contact_cb) {
+               data->callback.contact_cb (data->tp_factory,
+                                          contact,
+                                          error,
+                                          data->user_data, weak_object);
        }
+}
 
-       /* Create new contacts */
-       for (i = 0; i < new_handles->len; i++) {
-               EmpathyContact *contact;
-               guint           handle;
-
-               handle = g_array_index (new_handles, guint, i);
-
-               contact = g_object_new (EMPATHY_TYPE_CONTACT,
-                                       "account", priv->account,
-                                       "handle", handle,
-                                       NULL);
-               contact_created (tp_factory, contact);
-               contacts = g_list_prepend (contacts, contact);
-               new_contacts = g_list_prepend (new_contacts, g_object_ref (contact));
-       }
-       new_contacts = g_list_reverse (new_contacts);
-
-       if (priv->ready) {
-               /* Get the IDs of all new handles */
-               tp_cli_connection_call_inspect_handles (priv->connection,
-                                                       -1,
-                                                       TP_HANDLE_TYPE_CONTACT,
-                                                       new_handles,
-                                                       tp_contact_factory_inspect_handles_cb,
-                                                       new_contacts, tp_contact_factory_list_free,
-                                                       G_OBJECT (tp_factory));
-
-               /* Hold all new handles. */
-               /* FIXME: Should be unholded when removed from the factory */
-               tp_cli_connection_call_hold_handles (priv->connection,
-                                                    -1,
-                                                    TP_HANDLE_TYPE_CONTACT,
-                                                    new_handles,
-                                                    tp_contact_factory_hold_handles_cb,
-                                                    NULL, NULL,
-                                                    G_OBJECT (tp_factory));
-
-               tp_contact_factory_request_everything (tp_factory, new_handles);
-       }
+void
+empathy_tp_contact_factory_get_from_handle (EmpathyTpContactFactory *tp_factory,
+                                           TpHandle                 handle,
+                                           EmpathyTpContactFactoryContactCb callback,
+                                           gpointer                 user_data,
+                                           GDestroyNotify           destroy,
+                                           GObject                 *weak_object)
+{
+       EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
+       GetContactsData *data;
 
-       g_array_free (new_handles, TRUE);
+       g_return_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory));
 
-       return contacts;
+       data = g_slice_new (GetContactsData);
+       data->callback.contact_cb = callback;
+       data->user_data = user_data;
+       data->destroy = destroy;
+       data->tp_factory = g_object_ref (tp_factory);
+       tp_connection_get_contacts_by_handle (priv->connection,
+                                             1, &handle,
+                                             G_N_ELEMENTS (contact_features),
+                                             contact_features,
+                                             get_contact_by_handle_cb,
+                                             data,
+                                             (GDestroyNotify) get_contacts_data_free,
+                                             weak_object);
 }
 
 void
@@ -1219,9 +879,6 @@ empathy_tp_contact_factory_set_alias (EmpathyTpContactFactory *tp_factory,
 
        g_return_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory));
        g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-       g_return_if_fail (priv->ready);
-       g_return_if_fail (empathy_account_equal (empathy_contact_get_account (contact),
-                                                priv->account));
 
        handle = empathy_contact_get_handle (contact);
 
@@ -1257,7 +914,6 @@ empathy_tp_contact_factory_set_avatar (EmpathyTpContactFactory *tp_factory,
        EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
 
        g_return_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory));
-       g_return_if_fail (priv->ready);
 
        if (data && size > 0 && size < G_MAXUINT) {
                GArray avatar;
@@ -1265,8 +921,8 @@ empathy_tp_contact_factory_set_avatar (EmpathyTpContactFactory *tp_factory,
                avatar.data = (gchar*) data;
                avatar.len = size;
 
-               DEBUG ("Setting avatar on account %s",
-                       mc_account_get_unique_name (priv->account));
+               DEBUG ("Setting avatar on connection %s",
+                       tp_proxy_get_object_path (TP_PROXY (priv->connection)));
 
                tp_cli_connection_interface_avatars_call_set_avatar (priv->connection,
                                                                     -1,
@@ -1276,8 +932,8 @@ empathy_tp_contact_factory_set_avatar (EmpathyTpContactFactory *tp_factory,
                                                                     NULL, NULL,
                                                                     G_OBJECT (tp_factory));
        } else {
-               DEBUG ("Clearing avatar on account %s",
-                       mc_account_get_unique_name (priv->account));
+               DEBUG ("Clearing avatar on connection %s",
+                       tp_proxy_get_object_path (TP_PROXY (priv->connection)));
 
                tp_cli_connection_interface_avatars_call_clear_avatar (priv->connection,
                                                                       -1,
@@ -1287,16 +943,6 @@ empathy_tp_contact_factory_set_avatar (EmpathyTpContactFactory *tp_factory,
        }
 }
 
-gboolean
-empathy_tp_contact_factory_is_ready (EmpathyTpContactFactory *tp_factory)
-{
-       EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory);
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory), FALSE);
-
-       return priv->ready;
-}
-
 static void
 tp_contact_factory_get_property (GObject    *object,
                                 guint       param_id,
@@ -1306,11 +952,8 @@ tp_contact_factory_get_property (GObject    *object,
        EmpathyTpContactFactoryPriv *priv = GET_PRIV (object);
 
        switch (param_id) {
-       case PROP_ACCOUNT:
-               g_value_set_object (value, priv->account);
-               break;
-       case PROP_READY:
-               g_value_set_boolean (value, priv->ready);
+       case PROP_CONNECTION:
+               g_value_set_object (value, priv->connection);
                break;
        case PROP_MIME_TYPES:
                g_value_set_boxed (value, priv->avatar_mime_types);
@@ -1345,8 +988,8 @@ tp_contact_factory_set_property (GObject      *object,
        EmpathyTpContactFactoryPriv *priv = GET_PRIV (object);
 
        switch (param_id) {
-       case PROP_ACCOUNT:
-               priv->account = g_object_ref (g_value_get_object (value));
+       case PROP_CONNECTION:
+               priv->connection = g_value_dup_object (value);
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -1360,12 +1003,7 @@ tp_contact_factory_finalize (GObject *object)
        EmpathyTpContactFactoryPriv *priv = GET_PRIV (object);
        GList                       *l;
 
-       DEBUG ("Finalized: %p (%s)", object,
-               mc_account_get_normalized_name (priv->account));
-
-       g_signal_handlers_disconnect_by_func (priv->account_manager,
-                                             tp_contact_factory_account_connection_cb,
-                                             object);
+       DEBUG ("Finalized: %p", object);
 
        for (l = priv->contacts; l; l = l->next) {
                g_object_weak_unref (G_OBJECT (l->data),
@@ -1374,16 +1012,8 @@ tp_contact_factory_finalize (GObject *object)
        }
 
        g_list_free (priv->contacts);
-       g_object_unref (priv->account_manager);
-       g_object_unref (priv->account);
-       g_object_unref (priv->user);
-
-       if (priv->connection) {
-               g_signal_handlers_disconnect_by_func (priv->connection,
-                                                     tp_contact_factory_connection_invalidated_cb,
-                                                     object);
-               g_object_unref (priv->connection);
-       }
+
+       g_object_unref (priv->connection);
 
        g_strfreev (priv->avatar_mime_types);
 
@@ -1401,11 +1031,35 @@ tp_contact_factory_constructor (GType                  type,
        tp_factory = G_OBJECT_CLASS (empathy_tp_contact_factory_parent_class)->constructor (type, n_props, props);
        priv = GET_PRIV (tp_factory);
 
-       priv->ready = FALSE;
-       priv->user = empathy_contact_new (priv->account);
-       empathy_contact_set_is_user (priv->user, TRUE);
-       tp_contact_factory_add_contact ((EmpathyTpContactFactory*) tp_factory, priv->user);
-       tp_contact_factory_status_updated (EMPATHY_TP_CONTACT_FACTORY (tp_factory));
+       /* FIXME: This should be moved to TpContact */
+       tp_cli_connection_interface_avatars_connect_to_avatar_updated (priv->connection,
+                                                                      tp_contact_factory_avatar_updated_cb,
+                                                                      NULL, NULL,
+                                                                      tp_factory,
+                                                                      NULL);
+       tp_cli_connection_interface_avatars_connect_to_avatar_retrieved (priv->connection,
+                                                                        tp_contact_factory_avatar_retrieved_cb,
+                                                                        NULL, NULL,
+                                                                        tp_factory,
+                                                                        NULL);
+       tp_cli_connection_interface_capabilities_connect_to_capabilities_changed (priv->connection,
+                                                                                 tp_contact_factory_capabilities_changed_cb,
+                                                                                 NULL, NULL,
+                                                                                 tp_factory,
+                                                                                 NULL);
+
+
+       /* FIXME: This should be moved to TpConnection */
+       tp_cli_connection_interface_avatars_call_get_avatar_requirements (priv->connection,
+                                                                         -1,
+                                                                         tp_contact_factory_got_avatar_requirements_cb,
+                                                                         NULL, NULL,
+                                                                         tp_factory);
+       tp_cli_dbus_properties_call_get (priv->connection, -1,
+               TP_IFACE_CONNECTION_INTERFACE_REQUESTS,
+               "RequestableChannelClasses",
+               get_requestable_channel_classes_cb, NULL, NULL,
+               G_OBJECT (tp_factory));
 
        return tp_factory;
 }
@@ -1421,29 +1075,20 @@ empathy_tp_contact_factory_class_init (EmpathyTpContactFactoryClass *klass)
        object_class->set_property = tp_contact_factory_set_property;
 
        g_object_class_install_property (object_class,
-                                        PROP_ACCOUNT,
-                                        g_param_spec_object ("account",
-                                                             "Factory's Account",
-                                                             "The account associated with the factory",
-                                                             MC_TYPE_ACCOUNT,
+                                        PROP_CONNECTION,
+                                        g_param_spec_object ("connection",
+                                                             "Factory's Connection",
+                                                             "The connection associated with the factory",
+                                                             TP_TYPE_CONNECTION,
                                                              G_PARAM_READWRITE |
                                                              G_PARAM_CONSTRUCT_ONLY |
                                                              G_PARAM_STATIC_STRINGS));
-       g_object_class_install_property (object_class,
-                                        PROP_READY,
-                                        g_param_spec_boolean ("ready",
-                                                              "Whether the factory is ready",
-                                                              "TRUE once the factory is ready to be used",
-                                                              FALSE,
-                                                              G_PARAM_READABLE |
-                                                              G_PARAM_STATIC_STRINGS));
        g_object_class_install_property (object_class,
                                         PROP_MIME_TYPES,
                                         g_param_spec_boxed ("avatar-mime-types",
                                                             "Supported MIME types for avatars",
                                                             "Types of images that may be set as "
-                                                            "avatars on this connection.  Only valid "
-                                                            "once 'ready' becomes TRUE.",
+                                                            "avatars on this connection.",
                                                             G_TYPE_STRV,
                                                             G_PARAM_READABLE |
                                                             G_PARAM_STATIC_STRINGS));
@@ -1451,8 +1096,7 @@ empathy_tp_contact_factory_class_init (EmpathyTpContactFactoryClass *klass)
                                         PROP_MIN_WIDTH,
                                         g_param_spec_uint ("avatar-min-width",
                                                            "Minimum width for avatars",
-                                                           "Minimum width of avatar that may be set. "
-                                                           "Only valid once 'ready' becomes TRUE.",
+                                                           "Minimum width of avatar that may be set.",
                                                            0,
                                                            G_MAXUINT,
                                                            0,
@@ -1462,8 +1106,7 @@ empathy_tp_contact_factory_class_init (EmpathyTpContactFactoryClass *klass)
                                         PROP_MIN_HEIGHT,
                                         g_param_spec_uint ("avatar-min-height",
                                                            "Minimum height for avatars",
-                                                           "Minimum height of avatar that may be set. "
-                                                           "Only valid once 'ready' becomes TRUE.",
+                                                           "Minimum height of avatar that may be set.",
                                                            0,
                                                            G_MAXUINT,
                                                            0,
@@ -1474,8 +1117,7 @@ empathy_tp_contact_factory_class_init (EmpathyTpContactFactoryClass *klass)
                                         g_param_spec_uint ("avatar-max-width",
                                                            "Maximum width for avatars",
                                                            "Maximum width of avatar that may be set "
-                                                           "or 0 if there is no maximum. "
-                                                           "Only valid once 'ready' becomes TRUE.",
+                                                           "or 0 if there is no maximum.",
                                                            0,
                                                            G_MAXUINT,
                                                            0,
@@ -1486,8 +1128,7 @@ empathy_tp_contact_factory_class_init (EmpathyTpContactFactoryClass *klass)
                                         g_param_spec_uint ("avatar-max-height",
                                                            "Maximum height for avatars",
                                                            "Maximum height of avatar that may be set "
-                                                           "or 0 if there is no maximum. "
-                                                           "Only valid once 'ready' becomes TRUE.",
+                                                           "or 0 if there is no maximum.",
                                                            0,
                                                            G_MAXUINT,
                                                            0,
@@ -1498,8 +1139,7 @@ empathy_tp_contact_factory_class_init (EmpathyTpContactFactoryClass *klass)
                                         g_param_spec_uint ("avatar-max-size",
                                                            "Maximum size for avatars in bytes",
                                                            "Maximum file size of avatar that may be "
-                                                           "set or 0 if there is no maximum. "
-                                                           "Only valid once 'ready' becomes TRUE.",
+                                                           "set or 0 if there is no maximum.",
                                                            0,
                                                            G_MAXUINT,
                                                            0,
@@ -1517,20 +1157,68 @@ empathy_tp_contact_factory_init (EmpathyTpContactFactory *tp_factory)
                EMPATHY_TYPE_TP_CONTACT_FACTORY, EmpathyTpContactFactoryPriv);
 
        tp_factory->priv = priv;
-       priv->account_manager = empathy_account_manager_dup_singleton ();
+       priv->can_request_ft = FALSE;
+}
 
-       g_signal_connect (priv->account_manager, "account-connection-changed",
-                         G_CALLBACK (tp_contact_factory_account_connection_cb),
-                         tp_factory);
+static GHashTable *factories = NULL;
 
-       priv->can_request_ft = FALSE;
+static void
+tp_contact_factory_connection_invalidated_cb (TpProxy *connection,
+                                             guint    domain,
+                                             gint     code,
+                                             gchar   *message,
+                                             gpointer user_data)
+{
+       DEBUG ("Message: %s", message);
+       g_hash_table_remove (factories, connection);
+}
+
+static void
+tp_contact_factory_connection_weak_notify_cb (gpointer connection,
+                                             GObject *where_the_object_was)
+{
+       g_hash_table_remove (factories, connection);
+}
+
+static void
+tp_contact_factory_remove_connection (gpointer connection)
+{
+       g_signal_handlers_disconnect_by_func (connection,
+               tp_contact_factory_connection_invalidated_cb, NULL);
+       g_object_unref (connection);
 }
 
 EmpathyTpContactFactory *
-empathy_tp_contact_factory_new (McAccount *account)
+empathy_tp_contact_factory_dup_singleton (TpConnection *connection)
 {
-       return g_object_new (EMPATHY_TYPE_TP_CONTACT_FACTORY,
-                            "account", account,
-                            NULL);
+       EmpathyTpContactFactory *tp_factory;
+
+       g_return_val_if_fail (TP_IS_CONNECTION (connection), NULL);
+
+       if (factories == NULL) {
+               factories = g_hash_table_new_full (empathy_proxy_hash,
+                                                  empathy_proxy_equal,
+                                                  tp_contact_factory_remove_connection,
+                                                  NULL);
+       }
+
+       tp_factory = g_hash_table_lookup (factories, connection);
+       if (tp_factory == NULL) {
+               tp_factory = g_object_new (EMPATHY_TYPE_TP_CONTACT_FACTORY,
+                                          "connection", connection,
+                                          NULL);
+               g_hash_table_insert (factories, g_object_ref (connection),
+                                    tp_factory);
+               g_object_weak_ref (G_OBJECT (tp_factory),
+                                  tp_contact_factory_connection_weak_notify_cb,
+                                  connection);
+               g_signal_connect (connection, "invalidated",
+                                 G_CALLBACK (tp_contact_factory_connection_invalidated_cb),
+                                 NULL);
+       } else {
+               g_object_ref (tp_factory);
+       }
+
+       return tp_factory;
 }
 
index 92e7c2980b4d60a057c51cb02ab2a614cfec629a..91ff2f9e7209a5677ebed6c40e880045d2376eb8 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2009 Collabora Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -24,7 +24,7 @@
 
 #include <glib.h>
 
-#include <libmissioncontrol/mc-account.h>
+#include <telepathy-glib/connection.h>
 
 #include "empathy-contact.h"
 
@@ -49,15 +49,58 @@ struct _EmpathyTpContactFactoryClass {
        GObjectClass parent_class;
 };
 
+typedef void (*EmpathyTpContactFactoryContactsByIdCb) (EmpathyTpContactFactory *factory,
+                                                      guint                    n_contacts,
+                                                      EmpathyContact * const * contacts,
+                                                      const gchar * const *    requested_ids,
+                                                      GHashTable              *failed_id_errors,
+                                                      const GError            *error,
+                                                      gpointer                 user_data,
+                                                      GObject                 *weak_object);
+
+typedef void (*EmpathyTpContactFactoryContactsByHandleCb) (EmpathyTpContactFactory *factory,
+                                                          guint                    n_contacts,
+                                                          EmpathyContact * const * contacts,
+                                                           guint                    n_failed,
+                                                           const TpHandle          *failed,
+                                                           const GError            *error,
+                                                          gpointer                 user_data,
+                                                          GObject                 *weak_object);
+
+typedef void (*EmpathyTpContactFactoryContactCb) (EmpathyTpContactFactory *factory,
+                                                 EmpathyContact          *contact,
+                                                 const GError            *error,
+                                                 gpointer                 user_data,
+                                                 GObject                 *weak_object);
+
 GType                    empathy_tp_contact_factory_get_type         (void) G_GNUC_CONST;
-EmpathyTpContactFactory *empathy_tp_contact_factory_new              (McAccount *account);
-EmpathyContact *         empathy_tp_contact_factory_get_user         (EmpathyTpContactFactory *tp_factory);
-EmpathyContact *         empathy_tp_contact_factory_get_from_id      (EmpathyTpContactFactory *tp_factory,
-                                                                     const gchar             *id);
-EmpathyContact *         empathy_tp_contact_factory_get_from_handle  (EmpathyTpContactFactory *tp_factory,
-                                                                     guint                    handle);
-GList *                  empathy_tp_contact_factory_get_from_handles (EmpathyTpContactFactory *tp_factory,
-                                                                     const GArray            *handles);
+EmpathyTpContactFactory *empathy_tp_contact_factory_dup_singleton    (TpConnection *connection);
+void                     empathy_tp_contact_factory_get_from_ids     (EmpathyTpContactFactory *tp_factory,
+                                                                     guint                    n_ids,
+                                                                     const gchar * const     *ids,
+                                                                     EmpathyTpContactFactoryContactsByIdCb callback,
+                                                                     gpointer                 user_data,
+                                                                     GDestroyNotify           destroy,
+                                                                     GObject                 *weak_object);
+void                     empathy_tp_contact_factory_get_from_handles (EmpathyTpContactFactory *tp_factory,
+                                                                     guint                    n_handles,
+                                                                     const TpHandle          *handles,
+                                                                     EmpathyTpContactFactoryContactsByHandleCb callback,
+                                                                     gpointer                 user_data,
+                                                                     GDestroyNotify           destroy,
+                                                                     GObject                 *weak_object);
+void                     empathy_tp_contact_factory_get_from_id      (EmpathyTpContactFactory *tp_factory,
+                                                                     const gchar             *id,
+                                                                     EmpathyTpContactFactoryContactCb callback,
+                                                                     gpointer                 user_data,
+                                                                     GDestroyNotify           destroy,
+                                                                     GObject                 *weak_object);
+void                     empathy_tp_contact_factory_get_from_handle  (EmpathyTpContactFactory *tp_factory,
+                                                                     TpHandle                 handle,
+                                                                     EmpathyTpContactFactoryContactCb callback,
+                                                                     gpointer                 user_data,
+                                                                     GDestroyNotify           destroy,
+                                                                     GObject                 *weak_object);
 void                     empathy_tp_contact_factory_set_alias        (EmpathyTpContactFactory *tp_factory,
                                                                      EmpathyContact          *contact,
                                                                      const gchar             *alias);
@@ -65,7 +108,6 @@ void                     empathy_tp_contact_factory_set_avatar       (EmpathyTpC
                                                                      const gchar             *data,
                                                                      gsize                    size,
                                                                      const gchar             *mime_type);
-gboolean                 empathy_tp_contact_factory_is_ready         (EmpathyTpContactFactory *tp_factory);
 
 G_END_DECLS
 
index d4b99e4c4f1d91582d8ef411aa988e58a20679de..dd160224c90a28a28a949e6191d5b99f6315a4a5 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2007 Xavier Claessens <xclaesse@gmail.com>
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2009 Collabora Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -31,8 +31,8 @@
 #include <telepathy-glib/dbus.h>
 
 #include "empathy-tp-contact-list.h"
+#include "empathy-tp-contact-factory.h"
 #include "empathy-contact-list.h"
-#include "empathy-tp-group.h"
 #include "empathy-utils.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_TP | EMPATHY_DEBUG_CONTACT
 
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpContactList)
 typedef struct {
-       McAccount      *account;
+       EmpathyTpContactFactory *factory;
        TpConnection   *connection;
        const gchar    *protocol_group;
-       gboolean        ready;
 
-       EmpathyTpGroup *publish;
-       EmpathyTpGroup *subscribe;
-       GList          *members;
-       GList          *pendings;
-
-       GList          *groups;
-       GHashTable     *contacts_groups;
+       TpChannel      *publish;
+       TpChannel      *subscribe;
+       GHashTable     *members; /* handle -> EmpathyContact */
+       GHashTable     *pendings; /* handle -> EmpathyContact */
+       GHashTable     *groups; /* group name -> TpChannel */
+       GHashTable     *add_to_group; /* group name -> GArray of handles */
 } EmpathyTpContactListPriv;
 
 typedef enum {
@@ -62,377 +60,536 @@ typedef enum {
 
 static void tp_contact_list_iface_init         (EmpathyContactListIface   *iface);
 
-enum {
-       DESTROY,
-       LAST_SIGNAL
-};
-
 enum {
        PROP_0,
-       PROP_ACCOUNT,
+       PROP_CONNECTION,
 };
 
-static guint signals[LAST_SIGNAL];
-
 G_DEFINE_TYPE_WITH_CODE (EmpathyTpContactList, empathy_tp_contact_list, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CONTACT_LIST,
                                                tp_contact_list_iface_init));
 
 static void
-tp_contact_list_group_destroy_cb (EmpathyTpGroup       *group,
-                                 EmpathyTpContactList *list)
+tp_contact_list_group_invalidated_cb (TpChannel *channel,
+                                     guint      domain,
+                                     gint       code,
+                                     gchar     *message,
+                                     EmpathyTpContactList *list)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       const TpIntSet *members;
+       TpIntSetIter iter;
+       const gchar *group_name;
+
+       group_name = tp_channel_get_identifier (channel);
+       DEBUG ("Group %s invalidated. Message: %s", group_name, message);
+
+       /* Signal that all members are not in that group anymore */
+       members = tp_channel_group_get_members (channel);
+       tp_intset_iter_init (&iter, members);
+       while (tp_intset_iter_next (&iter)) {
+               EmpathyContact *contact;
+
+               contact = g_hash_table_lookup (priv->members,
+                                              GUINT_TO_POINTER (iter.element));
+               if (contact == NULL) {
+                       continue;
+               }
 
-       DEBUG ("Group destroyed: %s", empathy_tp_group_get_name (group));
+               DEBUG ("Contact %s (%d) removed from group %s",
+                       empathy_contact_get_id (contact), iter.element,
+                       group_name);
+               g_signal_emit_by_name (list, "groups-changed", contact,
+                                      group_name,
+                                      FALSE);
+       }
 
-       priv->groups = g_list_remove (priv->groups, group);
-       g_object_unref (group);
+       g_hash_table_remove (priv->groups, group_name);
 }
 
 static void
-tp_contact_list_group_member_added_cb (EmpathyTpGroup       *group,
-                                      EmpathyContact       *contact,
-                                      EmpathyContact       *actor,
-                                      guint                 reason,
-                                      const gchar          *message,
-                                      EmpathyTpContactList *list)
+tp_contact_list_group_ready_cb (TpChannel *channel,
+                               const GError *error,
+                               gpointer list)
 {
-       EmpathyTpContactListPriv  *priv = GET_PRIV (list);
-       const gchar               *group_name;
-       GList                    **groups;
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       const gchar *group_name;
 
-       if (!g_list_find (priv->members, contact)) {
+       if (error) {
+               DEBUG ("Error: %s", error->message);
+               g_object_unref (channel);
                return;
        }
+       
+       group_name = tp_channel_get_identifier (channel);
+       g_hash_table_insert (priv->groups, (gpointer) group_name, channel);
+       DEBUG ("Group %s added", group_name);
 
-       groups = g_hash_table_lookup (priv->contacts_groups, contact);
-       if (!groups) {
-               groups = g_slice_new0 (GList*);
-               g_hash_table_insert (priv->contacts_groups,
-                                    g_object_ref (contact),
-                                    groups);
-       }
+       g_signal_connect (channel, "invalidated",
+                         G_CALLBACK (tp_contact_list_group_invalidated_cb),
+                         list);
 
-       group_name = empathy_tp_group_get_name (group);
-       if (!g_list_find_custom (*groups, group_name, (GCompareFunc) strcmp)) {
-               DEBUG ("Contact %s (%d) added to group %s",
-                       empathy_contact_get_id (contact),
-                       empathy_contact_get_handle (contact),
-                       group_name);
-               *groups = g_list_prepend (*groups, g_strdup (group_name));
-               g_signal_emit_by_name (list, "groups-changed", contact,
-                                      group_name,
-                                      TRUE);
+       if (priv->add_to_group) {
+               GArray *handles;
+
+               handles = g_hash_table_lookup (priv->add_to_group, group_name);
+               if (handles) {
+                       DEBUG ("Adding initial members to group %s", group_name);
+                       tp_cli_channel_interface_group_call_add_members (channel,
+                               -1, handles, NULL, NULL, NULL, NULL, NULL);
+                       g_hash_table_remove (priv->add_to_group, group_name);
+               }
        }
 }
 
 static void
-tp_contact_list_group_member_removed_cb (EmpathyTpGroup       *group,
-                                        EmpathyContact       *contact,
-                                        EmpathyContact       *actor,
-                                        guint                 reason,
-                                        const gchar          *message,
-                                        EmpathyTpContactList *list)
+tp_contact_list_group_members_changed_cb (TpChannel     *channel,
+                                         gchar         *message,
+                                         GArray        *added,
+                                         GArray        *removed,
+                                         GArray        *local_pending,
+                                         GArray        *remote_pending,
+                                         guint          actor,
+                                         guint          reason,
+                                         EmpathyTpContactList *list)
 {
        EmpathyTpContactListPriv  *priv = GET_PRIV (list);
-       const gchar               *group_name;
-       GList                    **groups, *l;
+       const gchar *group_name;
+       gint i;
 
-       if (!g_list_find (priv->members, contact)) {
-               return;
-       }
+       group_name = tp_channel_get_identifier (channel);
 
-       groups = g_hash_table_lookup (priv->contacts_groups, contact);
-       if (!groups) {
-               return;
-       }
+       for (i = 0; i < added->len; i++) {
+               EmpathyContact *contact;
+               TpHandle handle;
+
+               handle = g_array_index (added, TpHandle, i);
+               contact = g_hash_table_lookup (priv->members,
+                                              GUINT_TO_POINTER (handle));
+               if (contact == NULL) {
+                       continue;
+               }
+
+               DEBUG ("Contact %s (%d) added to group %s",
+                       empathy_contact_get_id (contact), handle, group_name);
+               g_signal_emit_by_name (list, "groups-changed", contact,
+                                      group_name,
+                                      TRUE);
+       }       
+
+       for (i = 0; i < removed->len; i++) {
+               EmpathyContact *contact;
+               TpHandle handle;
+
+               handle = g_array_index (removed, TpHandle, i);
+               contact = g_hash_table_lookup (priv->members,
+                                              GUINT_TO_POINTER (handle));
+               if (contact == NULL) {
+                       continue;
+               }
 
-       group_name = empathy_tp_group_get_name (group);
-       if ((l = g_list_find_custom (*groups, group_name, (GCompareFunc) strcmp))) {
                DEBUG ("Contact %s (%d) removed from group %s",
-                       empathy_contact_get_id (contact),
-                       empathy_contact_get_handle (contact),
-                       group_name);
-               g_free (l->data);
-               *groups = g_list_delete_link (*groups, l);
+                       empathy_contact_get_id (contact), handle, group_name);
+
                g_signal_emit_by_name (list, "groups-changed", contact,
                                       group_name,
                                       FALSE);
-       }
+       }       
 }
 
-static EmpathyTpGroup *
-tp_contact_list_find_group (EmpathyTpContactList *list,
-                           const gchar          *group)
+static void
+tp_contact_list_group_add_channel (EmpathyTpContactList *list,
+                                  const gchar          *object_path,
+                                  const gchar          *channel_type,
+                                  TpHandleType          handle_type,
+                                  guint                 handle)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       GList                    *l;
+       TpChannel                *channel;
 
-       for (l = priv->groups; l; l = l->next) {
-               if (!tp_strdiff (group, empathy_tp_group_get_name (l->data))) {
-                       return l->data;
-               }
+       /* Only accept server-side contact groups */
+       if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_CONTACT_LIST) ||
+           handle_type != TP_HANDLE_TYPE_GROUP) {
+               return;
+       }
+
+       channel = tp_channel_new (priv->connection,
+                                 object_path, channel_type,
+                                 handle_type, handle, NULL);
+
+       /* TpChannel emits initial set of members just before being ready */
+       g_signal_connect (channel, "group-members-changed",
+                         G_CALLBACK (tp_contact_list_group_members_changed_cb),
+                         list);
+
+       /* Give the ref to the callback */
+       tp_channel_call_when_ready (channel,
+                                   tp_contact_list_group_ready_cb,
+                                   list);
+}
+
+static void
+tp_contact_list_group_request_channel_cb (TpConnection *connection,
+                                         const gchar  *object_path,
+                                         const GError *error,
+                                         gpointer      user_data,
+                                         GObject      *list)
+{
+       /* The new channel will be handled in NewChannel cb. Here we only
+        * handle the error if RequestChannel failed */
+       if (error) {
+               DEBUG ("Error: %s", error->message);
+               return;
        }
-       return NULL;
 }
 
-static TpContactListType
-tp_contact_list_get_type (EmpathyTpContactList *list,
-                         EmpathyTpGroup       *group)
+static void
+tp_contact_list_group_request_handles_cb (TpConnection *connection,
+                                         const GArray *handles,
+                                         const GError *error,
+                                         gpointer      user_data,
+                                         GObject      *list)
 {
-       const gchar *name;
+       TpHandle channel_handle;
 
-       name = empathy_tp_group_get_name (group);
-       if (!tp_strdiff (name, "subscribe")) {
-               return TP_CONTACT_LIST_TYPE_SUBSCRIBE;
-       } else if (!tp_strdiff (name, "publish")) {
-               return TP_CONTACT_LIST_TYPE_PUBLISH;
+       if (error) {
+               DEBUG ("Error: %s", error->message);
+               return;
        }
 
-       return TP_CONTACT_LIST_TYPE_UNKNOWN;
+       channel_handle = g_array_index (handles, TpHandle, 0);
+       tp_cli_connection_call_request_channel (connection, -1,
+                                               TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
+                                               TP_HANDLE_TYPE_GROUP,
+                                               channel_handle,
+                                               TRUE,
+                                               tp_contact_list_group_request_channel_cb,
+                                               NULL, NULL,
+                                               list);
 }
 
+/* This function takes ownership of handles array */
 static void
-tp_contact_list_add_member (EmpathyTpContactList *list,
-                           EmpathyContact       *contact,
-                           EmpathyContact       *actor,
-                           guint                 reason,
-                           const gchar          *message)
+tp_contact_list_group_add (EmpathyTpContactList *list,
+                          const gchar          *group_name,
+                          GArray               *handles)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       GList                    *l;
+       TpChannel                *channel;
+       const gchar              *names[] = {group_name, NULL};
+
+       /* Search the channel for that group name */
+       channel = g_hash_table_lookup (priv->groups, group_name);
+       if (channel) {
+               tp_cli_channel_interface_group_call_add_members (channel, -1,
+                       handles, NULL, NULL, NULL, NULL, NULL);
+               g_array_free (handles, TRUE);
+               return;
+       }
 
-       /* Add to the list and emit signal */
-       priv->members = g_list_prepend (priv->members, g_object_ref (contact));
-       g_signal_emit_by_name (list, "members-changed",
-                              contact, actor, reason, message,
-                              TRUE);
+       /* That group does not exist yet, we have to:
+        * 1) Request an handle for the group name
+        * 2) Request a channel
+        * 3) When NewChannel is emitted, add handles in members
+        */
+       g_hash_table_insert (priv->add_to_group,
+                            g_strdup (group_name),
+                            handles);
+       tp_cli_connection_call_request_handles (priv->connection, -1,
+                                               TP_HANDLE_TYPE_GROUP, names,
+                                               tp_contact_list_group_request_handles_cb,
+                                               NULL, NULL,
+                                               G_OBJECT (list));
+}
+
+static void
+tp_contact_list_got_added_members_cb (EmpathyTpContactFactory *factory,
+                                     guint                    n_contacts,
+                                     EmpathyContact * const * contacts,
+                                     guint                    n_failed,
+                                     const TpHandle          *failed,
+                                     const GError            *error,
+                                     gpointer                 user_data,
+                                     GObject                 *list)
+{
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       guint i;
 
-       /* This contact is now member, implicitly accept pending. */
-       if (g_list_find (priv->pendings, contact)) {
-               empathy_tp_group_add_member (priv->publish, contact, "");
+       if (error) {
+               DEBUG ("Error: %s", error->message);
+               return;
        }
 
-       /* Update groups of the contact */
-       for (l = priv->groups; l; l = l->next) {
-               if (empathy_tp_group_is_member (l->data, contact)) {
-                       tp_contact_list_group_member_added_cb (l->data, contact,
-                                                              NULL, 0, NULL, 
-                                                              list);
+       for (i = 0; i < n_contacts; i++) {
+               EmpathyContact *contact = contacts[i];
+               TpHandle handle;
+
+               handle = empathy_contact_get_handle (contact);
+               if (g_hash_table_lookup (priv->members, GUINT_TO_POINTER (handle)))
+                       continue;
+
+               /* Add to the list and emit signal */
+               g_hash_table_insert (priv->members, GUINT_TO_POINTER (handle),
+                                    g_object_ref (contact));
+               g_signal_emit_by_name (list, "members-changed", contact,
+                                      0, 0, NULL, TRUE);
+
+               /* This contact is now member, implicitly accept pending. */
+               if (g_hash_table_lookup (priv->pendings, GUINT_TO_POINTER (handle))) {
+                       GArray handles = {(gchar*) &handle, 1};
+
+                       tp_cli_channel_interface_group_call_add_members (priv->publish,
+                               -1, &handles, NULL, NULL, NULL, NULL, NULL);
                }
        }
 }
 
 static void
-tp_contact_list_added_cb (EmpathyTpGroup       *group,
-                         EmpathyContact       *contact,
-                         EmpathyContact       *actor,
-                         guint                 reason,
-                         const gchar          *message,
-                         EmpathyTpContactList *list)
+tp_contact_list_got_local_pending_cb (EmpathyTpContactFactory *factory,
+                                     guint                    n_contacts,
+                                     EmpathyContact * const * contacts,
+                                     guint                    n_failed,
+                                     const TpHandle          *failed,
+                                     const GError            *error,
+                                     gpointer                 user_data,
+                                     GObject                 *list)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       TpContactListType         list_type;
-
-       list_type = tp_contact_list_get_type (list, group);
-       DEBUG ("Contact %s (%d) added to list type %d",
-               empathy_contact_get_id (contact),
-               empathy_contact_get_handle (contact),
-               list_type);
-
-       /* We now get the presence of that contact, add it to members */
-       if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE &&
-           !g_list_find (priv->members, contact)) {
-               tp_contact_list_add_member (list, contact, actor, reason, message);
+       guint i;
+
+       if (error) {
+               DEBUG ("Error: %s", error->message);
+               return;
        }
 
-       /* We now send our presence to that contact, remove it from pendings */
-       if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH &&
-           g_list_find (priv->pendings, contact)) {
-               g_signal_emit_by_name (list, "pendings-changed",
-                                      contact, actor, reason, message,
-                                      FALSE);
-               priv->pendings = g_list_remove (priv->pendings, contact);
-               g_object_unref (contact);
+       for (i = 0; i < n_contacts; i++) {
+               EmpathyContact *contact = contacts[i];
+               TpHandle handle;
+               const gchar *message;
+               TpChannelGroupChangeReason reason;
+
+               handle = empathy_contact_get_handle (contact);
+               if (g_hash_table_lookup (priv->members, GUINT_TO_POINTER (handle))) {
+                       GArray handles = {(gchar*) &handle, 1};
+
+                       /* This contact is already member, auto accept. */
+                       tp_cli_channel_interface_group_call_add_members (priv->publish,
+                               -1, &handles, NULL, NULL, NULL, NULL, NULL);
+               }
+               else if (tp_channel_group_get_local_pending_info (priv->publish,
+                                                                 handle,
+                                                                 NULL,
+                                                                 &reason,
+                                                                 &message)) {
+                       /* Add contact to pendings */
+                       g_hash_table_insert (priv->pendings, GUINT_TO_POINTER (handle),
+                                            g_object_ref (contact));
+                       g_signal_emit_by_name (list, "pendings-changed", contact,
+                                              contact, reason, message, TRUE);
+               }
        }
 }
 
 static void
-tp_contact_list_removed_cb (EmpathyTpGroup       *group,
-                           EmpathyContact       *contact,
-                           EmpathyContact       *actor,
-                           guint                 reason,
-                           const gchar          *message,
-                           EmpathyTpContactList *list)
+tp_contact_list_remove_handle (EmpathyTpContactList *list,
+                              GHashTable *table,
+                              TpHandle handle)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       TpContactListType         list_type;
-
-       list_type = tp_contact_list_get_type (list, group);
-       DEBUG ("Contact %s (%d) removed from list type %d",
-               empathy_contact_get_id (contact),
-               empathy_contact_get_handle (contact),
-               list_type);
-
-       /* This contact refuses to send us his presence, remove from members. */
-       if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE &&
-           g_list_find (priv->members, contact)) {
-               g_signal_emit_by_name (list, "members-changed",
-                                      contact, actor, reason, message,
-                                      FALSE);
-               priv->members = g_list_remove (priv->members, contact);
-               g_object_unref (contact);
-       }
+       EmpathyContact *contact;
+       const gchar *signal;
+
+       if (table == priv->pendings)
+               signal = "pendings-changed";
+       else if (table == priv->members)
+               signal = "members-changed";
+       else
+               return;
 
-       /* We refuse to send our presence to that contact, remove from pendings */
-       if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH &&
-           g_list_find (priv->pendings, contact)) {
-               g_signal_emit_by_name (list, "pendings-changed",
-                                      contact, actor, reason, message,
+       contact = g_hash_table_lookup (table, GUINT_TO_POINTER (handle));
+       if (contact) {
+               g_object_ref (contact);
+               g_hash_table_remove (table, GUINT_TO_POINTER (handle));
+               g_signal_emit_by_name (list, signal, contact, 0, 0, NULL,
                                       FALSE);
-               priv->pendings = g_list_remove (priv->pendings, contact);
                g_object_unref (contact);
        }
 }
 
 static void
-tp_contact_list_pending_cb (EmpathyTpGroup       *group,
-                           EmpathyContact       *contact,
-                           EmpathyContact       *actor,
-                           guint                 reason,
-                           const gchar          *message,
-                           EmpathyTpContactList *list)
+tp_contact_list_publish_group_members_changed_cb (TpChannel     *channel,
+                                                 gchar         *message,
+                                                 GArray        *added,
+                                                 GArray        *removed,
+                                                 GArray        *local_pending,
+                                                 GArray        *remote_pending,
+                                                 TpHandle       actor,
+                                                 TpChannelGroupChangeReason reason,
+                                                 EmpathyTpContactList *list)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       TpContactListType         list_type;
+       guint i;
 
-       list_type = tp_contact_list_get_type (list, group);
-       DEBUG ("Contact %s (%d) pending in list type %d",
-               empathy_contact_get_id (contact),
-               empathy_contact_get_handle (contact),
-               list_type);
+       /* We now send our presence to those contacts, remove them from pendings */
+       for (i = 0; i < added->len; i++) {
+               tp_contact_list_remove_handle (list, priv->pendings,
+                       g_array_index (added, TpHandle, i));
+       }
 
-       /* We want this contact in our contact list but we don't get its 
-        * presence yet. Add to members anyway. */
-       if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE &&
-           !g_list_find (priv->members, contact)) {
-               tp_contact_list_add_member (list, contact, actor, reason, message);
+       /* We refuse to send our presence to those contacts, remove from pendings */
+       for (i = 0; i < removed->len; i++) {
+               tp_contact_list_remove_handle (list, priv->pendings,
+                       g_array_index (added, TpHandle, i));
        }
 
-       /* This contact wants our presence, auto accept if he is member,
-        * otherwise he is pending. */
-       if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH &&
-           !g_list_find (priv->pendings, contact)) {
-               if (g_list_find (priv->members, contact)) {
-                       empathy_tp_group_add_member (priv->publish, contact, "");
-               } else {
-                       priv->pendings = g_list_prepend (priv->pendings,
-                                                        g_object_ref (contact));
-                       g_signal_emit_by_name (list, "pendings-changed",
-                                              contact, actor, reason, message,
-                                              TRUE);
-               }
+       /* Those contacts want our presence, auto accept those that are already
+        * member, otherwise add in pendings. */
+       if (local_pending->len > 0) {
+               empathy_tp_contact_factory_get_from_handles (priv->factory,
+                       local_pending->len, (TpHandle*) local_pending->data,
+                       tp_contact_list_got_local_pending_cb, NULL, NULL,
+                       G_OBJECT (list));
        }
 }
 
 static void
-tp_contact_list_invalidated_cb (TpConnection         *connection,
-                               guint                 domain,
-                               gint                  code,
-                               gchar                *message,
-                               EmpathyTpContactList *list)
+tp_contact_list_publish_request_channel_cb (TpConnection *connection,
+                                           const gchar  *object_path,
+                                           const GError *error,
+                                           gpointer      user_data,
+                                           GObject      *list)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       GList                    *l;
 
-       DEBUG ("Connection invalidated");
-
-       /* Remove all contacts */
-       for (l = priv->members; l; l = l->next) {
-               g_signal_emit_by_name (list, "members-changed", l->data,
-                                      NULL, 0, NULL,
-                                      FALSE);
-               g_object_unref (l->data);
-       }
-       for (l = priv->pendings; l; l = l->next) {
-               g_signal_emit_by_name (list, "pendings-changed", l->data,
-                                      NULL, 0, NULL,
-                                      FALSE);
-               g_object_unref (l->data);
+       if (error) {
+               DEBUG ("Error: %s", error->message);
+               return;
        }
-       g_list_free (priv->members);
-       g_list_free (priv->pendings);
-       priv->members = NULL;
-       priv->pendings = NULL;
 
-       /* Tell the world to not use us anymore */
-       g_signal_emit (list, signals[DESTROY], 0);
+       priv->publish = tp_channel_new (connection, object_path,
+                                       TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
+                                       TP_HANDLE_TYPE_LIST,
+                                       GPOINTER_TO_UINT (user_data),
+                                       NULL);
+
+       /* TpChannel emits initial set of members just before being ready */
+       g_signal_connect (priv->publish, "group-members-changed",
+                         G_CALLBACK (tp_contact_list_publish_group_members_changed_cb),
+                         list);
 }
 
 static void
-tp_contact_list_group_list_free (GList **groups)
+tp_contact_list_publish_request_handle_cb (TpConnection *connection,
+                                          const GArray *handles,
+                                          const GError *error,
+                                          gpointer      user_data,
+                                          GObject      *list)
 {
-       g_list_foreach (*groups, (GFunc) g_free, NULL);
-       g_list_free (*groups);
-       g_slice_free (GList*, groups);
+       TpHandle handle;
+
+       if (error) {
+               DEBUG ("Error: %s", error->message);
+               return;
+       }
+
+       handle = g_array_index (handles, TpHandle, 0);
+       tp_cli_connection_call_request_channel (connection, -1,
+                                               TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
+                                               TP_HANDLE_TYPE_LIST,
+                                               handle,
+                                               TRUE,
+                                               tp_contact_list_publish_request_channel_cb,
+                                               GUINT_TO_POINTER (handle), NULL,
+                                               list);
 }
 
 static void
-tp_contact_list_add_channel (EmpathyTpContactList *list,
-                            const gchar          *object_path,
-                            const gchar          *channel_type,
-                            TpHandleType          handle_type,
-                            guint                 handle)
+tp_contact_list_subscribe_group_members_changed_cb (TpChannel     *channel,
+                                                   gchar         *message,
+                                                   GArray        *added,
+                                                   GArray        *removed,
+                                                   GArray        *local_pending,
+                                                   GArray        *remote_pending,
+                                                   guint          actor,
+                                                   guint          reason,
+                                                   EmpathyTpContactList *list)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       TpChannel                *channel;
-       EmpathyTpGroup           *group;
-       const gchar              *group_name;
-       GList                    *contacts, *l;
+       guint i;
+
+       /* We now get the presence of those contacts, add them to members */
+       if (added->len > 0) {
+               empathy_tp_contact_factory_get_from_handles (priv->factory,
+                       added->len, (TpHandle*) added->data,
+                       tp_contact_list_got_added_members_cb, NULL, NULL,
+                       G_OBJECT (list));
+       }
 
-       if (strcmp (channel_type, TP_IFACE_CHANNEL_TYPE_CONTACT_LIST) != 0 ||
-           handle_type != TP_HANDLE_TYPE_GROUP) {
-               return;
+       /* Those contacts refuse to send us their presence, remove from members. */
+       for (i = 0; i < removed->len; i++) {
+               tp_contact_list_remove_handle (list, priv->members,
+                       g_array_index (added, TpHandle, i));
        }
 
-       channel = tp_channel_new (priv->connection,
-                                 object_path, channel_type,
-                                 handle_type, handle, NULL);
+       /* We want those contacts in our contact list but we don't get their 
+        * presence yet. Add to members anyway. */
+       if (remote_pending->len > 0) {
+               empathy_tp_contact_factory_get_from_handles (priv->factory,
+                       remote_pending->len, (TpHandle*) remote_pending->data,
+                       tp_contact_list_got_added_members_cb, NULL, NULL,
+                       G_OBJECT (list));
+       }
+}
 
-       group = empathy_tp_group_new (channel);
-       empathy_run_until_ready (group);
-       g_object_unref (channel);
+static void
+tp_contact_list_subscribe_request_channel_cb (TpConnection *connection,
+                                             const gchar  *object_path,
+                                             const GError *error,
+                                             gpointer      user_data,
+                                             GObject      *list)
+{
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
 
-       /* Check if already exists */
-       group_name = empathy_tp_group_get_name (group);
-       if (tp_contact_list_find_group (list, group_name)) {
-               g_object_unref (group);
+       if (error) {
+               DEBUG ("Error: %s", error->message);
                return;
        }
 
-       /* Add the group */
-       DEBUG ("New server-side group: %s", group_name);
-       priv->groups = g_list_prepend (priv->groups, group);
-       g_signal_connect (group, "member-added",
-                         G_CALLBACK (tp_contact_list_group_member_added_cb),
-                         list);
-       g_signal_connect (group, "member-removed",
-                         G_CALLBACK (tp_contact_list_group_member_removed_cb),
-                         list);
-       g_signal_connect (group, "destroy",
-                         G_CALLBACK (tp_contact_list_group_destroy_cb),
+       priv->subscribe = tp_channel_new (connection, object_path,
+                                         TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
+                                         TP_HANDLE_TYPE_LIST,
+                                         GPOINTER_TO_UINT (user_data),
+                                         NULL);
+
+       /* TpChannel emits initial set of members just before being ready */
+       g_signal_connect (priv->subscribe, "group-members-changed",
+                         G_CALLBACK (tp_contact_list_subscribe_group_members_changed_cb),
                          list);
+}
 
-       /* Get initial members */
-       contacts = empathy_tp_group_get_members (group);
-       for (l = contacts; l; l = l->next) {
-               tp_contact_list_group_member_added_cb (group, l->data,
-                                                      NULL, 0, NULL,
-                                                      list);
-               g_object_unref (l->data);
+static void
+tp_contact_list_subscribe_request_handle_cb (TpConnection *connection,
+                                            const GArray *handles,
+                                            const GError *error,
+                                            gpointer      user_data,
+                                            GObject      *list)
+{
+       TpHandle handle;
+
+       if (error) {
+               DEBUG ("Error: %s", error->message);
+               return;
        }
-       g_list_free (contacts);
+
+       handle = g_array_index (handles, TpHandle, 0);
+       tp_cli_connection_call_request_channel (connection, -1,
+                                               TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
+                                               TP_HANDLE_TYPE_LIST,
+                                               handle,
+                                               TRUE,
+                                               tp_contact_list_subscribe_request_channel_cb,
+                                               GUINT_TO_POINTER (handle), NULL,
+                                               list);
 }
 
 static void
@@ -445,13 +602,9 @@ tp_contact_list_new_channel_cb (TpConnection *proxy,
                                gpointer      user_data,
                                GObject      *list)
 {
-       EmpathyTpContactListPriv *priv = GET_PRIV (list);
-
-       if (!suppress_handler && priv->ready) {
-               tp_contact_list_add_channel (EMPATHY_TP_CONTACT_LIST (list),
-                                            object_path, channel_type,
-                                            handle_type, handle);
-       }
+       tp_contact_list_group_add_channel (EMPATHY_TP_CONTACT_LIST (list),
+                                          object_path, channel_type,
+                                          handle_type, handle);
 }
 
 static void
@@ -461,8 +614,7 @@ tp_contact_list_list_channels_cb (TpConnection    *connection,
                                  gpointer         user_data,
                                  GObject         *list)
 {
-       EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       guint                     i;
+       guint i;
 
        if (error) {
                DEBUG ("Error: %s", error->message);
@@ -482,151 +634,10 @@ tp_contact_list_list_channels_cb (TpConnection    *connection,
                handle_type = g_value_get_uint (g_value_array_get_nth (chan_struct, 2));
                handle = g_value_get_uint (g_value_array_get_nth (chan_struct, 3));
 
-               tp_contact_list_add_channel (EMPATHY_TP_CONTACT_LIST (list),
-                                            object_path, channel_type,
-                                            handle_type, handle);
-       }
-
-       priv->ready = TRUE;
-}
-
-static void
-tp_contact_list_request_channel_cb (TpConnection *connection,
-                                   const gchar  *object_path,
-                                   const GError *error,
-                                   gpointer      user_data,
-                                   GObject      *weak_object)
-{
-       EmpathyTpContactList     *list = EMPATHY_TP_CONTACT_LIST (weak_object);
-       EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       EmpathyTpGroup           *group;
-       TpChannel                *channel;
-       TpContactListType         list_type;
-       GList                    *contacts, *l;
-
-       if (error) {
-               DEBUG ("Error: %s", error->message);
-               return;
-       }
-
-       channel = tp_channel_new (connection, object_path,
-                                 TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
-                                 TP_HANDLE_TYPE_LIST,
-                                 GPOINTER_TO_UINT (user_data),
-                                 NULL);
-       group = empathy_tp_group_new (channel);
-       empathy_run_until_ready (group);
-
-       list_type = tp_contact_list_get_type (list, group);
-       if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH && !priv->publish) {
-               DEBUG ("Got publish list");
-               priv->publish = group;
-
-               /* Publish is the list of contacts to who we send our
-                * presence. Makes no sense to be in remote-pending */
-               g_signal_connect (group, "local-pending",
-                                 G_CALLBACK (tp_contact_list_pending_cb),
-                                 list);
-
-               contacts = empathy_tp_group_get_local_pendings (group);
-               for (l = contacts; l; l = l->next) {
-                       EmpathyPendingInfo *info = l->data;
-                               tp_contact_list_pending_cb (group,
-                                                   info->member,
-                                                   info->actor,
-                                                   0,
-                                                   info->message,
-                                                   list);
-                       empathy_pending_info_free (info);
-               }
-               g_list_free (contacts);
-       }
-       else if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE && !priv->subscribe) {
-               DEBUG ("Got subscribe list");
-               priv->subscribe = group;
-
-               /* Subscribe is the list of contacts from who we
-                * receive presence. Makes no sense to be in
-                * local-pending */
-               g_signal_connect (group, "remote-pending",
-                                 G_CALLBACK (tp_contact_list_pending_cb),
-                                 list);
-
-               contacts = empathy_tp_group_get_remote_pendings (group);
-               for (l = contacts; l; l = l->next) {
-                       tp_contact_list_pending_cb (group,
-                                                   l->data,
-                                                   NULL, 0,
-                                                   NULL, list);
-                       g_object_unref (l->data);
-               }
-               g_list_free (contacts);
-       } else {
-               DEBUG ("Type of contact list channel unknown or aleady "
-                       "have that list: %s",
-                       empathy_tp_group_get_name (group));
-               g_object_unref (group);
-               return;
+               tp_contact_list_group_add_channel (EMPATHY_TP_CONTACT_LIST (list),
+                                                  object_path, channel_type,
+                                                  handle_type, handle);
        }
-
-       /* For all list types when need to get members */
-       g_signal_connect (group, "member-added",
-                         G_CALLBACK (tp_contact_list_added_cb),
-                         list);
-       g_signal_connect (group, "member-removed",
-                         G_CALLBACK (tp_contact_list_removed_cb),
-                         list);
-
-       contacts = empathy_tp_group_get_members (group);
-       for (l = contacts; l; l = l->next) {
-               tp_contact_list_added_cb (group,
-                                         l->data,
-                                         NULL, 0, NULL,
-                                         list);
-               g_object_unref (l->data);
-       }
-       g_list_free (contacts);
-}
-
-static void
-tp_contact_list_request_handle_cb (TpConnection *connection,
-                                  const GArray *handles,
-                                  const GError *error,
-                                  gpointer      user_data,
-                                  GObject      *list)
-{
-       guint handle;
-
-       if (error) {
-               DEBUG ("Error: %s", error->message);
-               return;
-       }
-
-       handle = g_array_index (handles, guint, 0);
-       tp_cli_connection_call_request_channel (connection, -1,
-                                               TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
-                                               TP_HANDLE_TYPE_LIST,
-                                               handle,
-                                               TRUE,
-                                               tp_contact_list_request_channel_cb,
-                                               GUINT_TO_POINTER (handle), NULL,
-                                               list);
-}
-
-static void
-tp_contact_list_request_list (EmpathyTpContactList *list,
-                             const gchar          *type)
-{
-       EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       const gchar *names[] = {type, NULL};
-
-       tp_cli_connection_call_request_handles (priv->connection,
-                                               -1,
-                                               TP_HANDLE_TYPE_LIST,
-                                               names,
-                                               tp_contact_list_request_handle_cb,
-                                               NULL, NULL,
-                                               G_OBJECT (list));
 }
 
 static void
@@ -634,6 +645,8 @@ tp_contact_list_finalize (GObject *object)
 {
        EmpathyTpContactListPriv *priv;
        EmpathyTpContactList     *list;
+       GHashTableIter            iter;
+       gpointer                  channel;
 
        list = EMPATHY_TP_CONTACT_LIST (object);
        priv = GET_PRIV (list);
@@ -646,49 +659,55 @@ tp_contact_list_finalize (GObject *object)
        if (priv->publish) {
                g_object_unref (priv->publish);
        }
-       if (priv->account) {
-               g_object_unref (priv->account);
-       }
+
        if (priv->connection) {
-               g_signal_handlers_disconnect_by_func (priv->connection,
-                                                     tp_contact_list_invalidated_cb,
-                                                     object);
                g_object_unref (priv->connection);
        }
 
-       g_hash_table_destroy (priv->contacts_groups);
-       g_list_foreach (priv->groups, (GFunc) g_object_unref, NULL);
-       g_list_free (priv->groups);
-       g_list_foreach (priv->members, (GFunc) g_object_unref, NULL);
-       g_list_free (priv->members);
-       g_list_foreach (priv->pendings, (GFunc) g_object_unref, NULL);
-       g_list_free (priv->pendings);
+       if (priv->factory) {
+               g_object_unref (priv->factory);
+       }
+
+       g_hash_table_iter_init (&iter, priv->groups);
+       while (g_hash_table_iter_next (&iter, NULL, &channel)) {
+               g_signal_handlers_disconnect_by_func (channel,
+                       tp_contact_list_group_invalidated_cb, list);
+       }
+
+       g_hash_table_destroy (priv->groups);
+       g_hash_table_destroy (priv->members);
+       g_hash_table_destroy (priv->pendings);
+       g_hash_table_destroy (priv->add_to_group);
 
        G_OBJECT_CLASS (empathy_tp_contact_list_parent_class)->finalize (object);
 }
 
 static void
-tp_contact_list_connection_ready (TpConnection *connection,
-                                 const GError *error,
-                                 gpointer      list)
+tp_contact_list_constructed (GObject *list)
 {
-       EmpathyTpContactListPriv *priv = GET_PRIV (list);
 
-       if (error) {
-               tp_contact_list_invalidated_cb (connection,
-                                               error->domain,
-                                               error->code,
-                                               error->message,
-                                               EMPATHY_TP_CONTACT_LIST (list));
-               return;
-       }
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       gchar                    *protocol_name = NULL;
+       const gchar              *names[] = {NULL, NULL};
 
-       g_signal_connect (priv->connection, "invalidated",
-                         G_CALLBACK (tp_contact_list_invalidated_cb),
-                         list);
+       priv->factory = empathy_tp_contact_factory_dup_singleton (priv->connection);
 
-       tp_contact_list_request_list (list, "publish");
-       tp_contact_list_request_list (list, "subscribe");
+       names[0] = "publish";
+       tp_cli_connection_call_request_handles (priv->connection,
+                                               -1,
+                                               TP_HANDLE_TYPE_LIST,
+                                               names,
+                                               tp_contact_list_publish_request_handle_cb,
+                                               NULL, NULL,
+                                               G_OBJECT (list));
+       names[0] = "subscribe";
+       tp_cli_connection_call_request_handles (priv->connection,
+                                               -1,
+                                               TP_HANDLE_TYPE_LIST,
+                                               names,
+                                               tp_contact_list_subscribe_request_handle_cb,
+                                               NULL, NULL,
+                                               G_OBJECT (list));
 
        tp_cli_connection_call_list_channels (priv->connection, -1,
                                              tp_contact_list_list_channels_cb,
@@ -699,39 +718,15 @@ tp_contact_list_connection_ready (TpConnection *connection,
                                                  tp_contact_list_new_channel_cb,
                                                  NULL, NULL,
                                                  list, NULL);
-}
-
-static void
-tp_contact_list_constructed (GObject *list)
-{
-
-       EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       MissionControl           *mc;
-       guint                     status;
-       McProfile                *profile;
-       const gchar              *protocol_name;
-
-       /* Get the connection. status==0 means CONNECTED */
-       mc = empathy_mission_control_dup_singleton ();
-       status = mission_control_get_connection_status (mc, priv->account, NULL);
-       g_return_if_fail (status == 0);
-       priv->connection = mission_control_get_tpconnection (mc, priv->account, NULL);
-       g_return_if_fail (priv->connection != NULL);
-       g_object_unref (mc);
-
-       tp_connection_call_when_ready (priv->connection,
-                                      tp_contact_list_connection_ready,
-                                      list);
 
        /* Check for protocols that does not support contact groups. We can
         * put all contacts into a special group in that case.
         * FIXME: Default group should be an information in the profile */
-       profile = mc_account_get_profile (priv->account);
-       protocol_name = mc_profile_get_protocol_name (profile);
-       if (strcmp (protocol_name, "local-xmpp") == 0) {
+       tp_connection_parse_object_path (priv->connection, &protocol_name, NULL);
+       if (!tp_strdiff (protocol_name, "local-xmpp")) {
                priv->protocol_group = _("People nearby");
        }
-       g_object_unref (profile);
+       g_free (protocol_name);
 }
 
 static void
@@ -743,8 +738,8 @@ tp_contact_list_get_property (GObject    *object,
        EmpathyTpContactListPriv *priv = GET_PRIV (object);
 
        switch (param_id) {
-       case PROP_ACCOUNT:
-               g_value_set_object (value, priv->account);
+       case PROP_CONNECTION:
+               g_value_set_object (value, priv->connection);
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -761,8 +756,8 @@ tp_contact_list_set_property (GObject      *object,
        EmpathyTpContactListPriv *priv = GET_PRIV (object);
 
        switch (param_id) {
-       case PROP_ACCOUNT:
-               priv->account = g_object_ref (g_value_get_object (value));
+       case PROP_CONNECTION:
+               priv->connection = g_value_dup_object (value);
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -781,27 +776,23 @@ empathy_tp_contact_list_class_init (EmpathyTpContactListClass *klass)
        object_class->set_property = tp_contact_list_set_property;
 
        g_object_class_install_property (object_class,
-                                        PROP_ACCOUNT,
-                                        g_param_spec_object ("account",
-                                                             "The Account",
-                                                             "The account associated with the contact list",
-                                                             MC_TYPE_ACCOUNT,
+                                        PROP_CONNECTION,
+                                        g_param_spec_object ("connection",
+                                                             "The Connection",
+                                                             "The connection associated with the contact list",
+                                                             TP_TYPE_CONNECTION,
                                                              G_PARAM_READWRITE |
                                                              G_PARAM_CONSTRUCT_ONLY));
 
-       signals[DESTROY] =
-               g_signal_new ("destroy",
-                             G_TYPE_FROM_CLASS (klass),
-                             G_SIGNAL_RUN_LAST,
-                             0,
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__VOID,
-                             G_TYPE_NONE,
-                             0);
-
        g_type_class_add_private (object_class, sizeof (EmpathyTpContactListPriv));
 }
 
+static void
+tp_contact_list_array_free (gpointer handles)
+{
+       g_array_free (handles, TRUE);
+}
+
 static void
 empathy_tp_contact_list_init (EmpathyTpContactList *list)
 {
@@ -809,22 +800,39 @@ empathy_tp_contact_list_init (EmpathyTpContactList *list)
                EMPATHY_TYPE_TP_CONTACT_LIST, EmpathyTpContactListPriv);
 
        list->priv = priv;
-       priv->contacts_groups = g_hash_table_new_full (g_direct_hash,
-                                                      g_direct_equal,
-                                                      (GDestroyNotify) g_object_unref,
-                                                      (GDestroyNotify) tp_contact_list_group_list_free);
+
+       /* Map group's name to group's TpChannel. The group name string is owned
+        * by the TpChannel object */
+       priv->groups = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                             NULL,
+                                             (GDestroyNotify) g_object_unref);
+
+       /* Map contact's handle to EmpathyContact object */
+       priv->members = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+                                              NULL,
+                                              (GDestroyNotify) g_object_unref);
+
+       /* Map contact's handle to EmpathyContact object */
+       priv->pendings = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+                                               NULL,
+                                               (GDestroyNotify) g_object_unref);
+
+       /* Map group's name to GArray of handle */
+       priv->add_to_group = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                   g_free,
+                                                   tp_contact_list_array_free);
 }
 
 EmpathyTpContactList *
-empathy_tp_contact_list_new (McAccount *account)
+empathy_tp_contact_list_new (TpConnection *connection)
 {
        return g_object_new (EMPATHY_TYPE_TP_CONTACT_LIST,
-                            "account", account,
+                            "connection", connection,
                             NULL);
 }
 
-McAccount *
-empathy_tp_contact_list_get_account (EmpathyTpContactList *list)
+TpConnection *
+empathy_tp_contact_list_get_connection (EmpathyTpContactList *list)
 {
        EmpathyTpContactListPriv *priv;
 
@@ -832,7 +840,7 @@ empathy_tp_contact_list_get_account (EmpathyTpContactList *list)
 
        priv = GET_PRIV (list);
 
-       return priv->account;
+       return priv->connection;
 }
 
 static void
@@ -841,15 +849,18 @@ tp_contact_list_add (EmpathyContactList *list,
                     const gchar        *message)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       TpHandle handle;
+       GArray handles = {(gchar *) &handle, 1};
 
-       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
-
+       handle = empathy_contact_get_handle (contact);
        if (priv->subscribe) {
-               empathy_tp_group_add_member (priv->subscribe, contact, message);
+               tp_cli_channel_interface_group_call_add_members (priv->subscribe,
+                       -1, &handles, message, NULL, NULL, NULL, NULL);
        }
-
-       if (priv->publish && g_list_find (priv->pendings, contact)) {
-               empathy_tp_group_add_member (priv->publish, contact, message);          
+       if (priv->publish &&
+           g_hash_table_lookup (priv->pendings, GUINT_TO_POINTER (handle))) {
+               tp_cli_channel_interface_group_call_add_members (priv->publish,
+                       -1, &handles, message, NULL, NULL, NULL, NULL);
        }
 }
 
@@ -859,14 +870,17 @@ tp_contact_list_remove (EmpathyContactList *list,
                        const gchar        *message)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       TpHandle handle;
+       GArray handles = {(gchar *) &handle, 1};
 
-       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
-
+       handle = empathy_contact_get_handle (contact);
        if (priv->subscribe) {
-               empathy_tp_group_remove_member (priv->subscribe, contact, message);
+               tp_cli_channel_interface_group_call_remove_members (priv->subscribe,
+                       -1, &handles, message, NULL, NULL, NULL, NULL);
        }
        if (priv->publish) {
-               empathy_tp_group_remove_member (priv->publish, contact, message);               
+               tp_cli_channel_interface_group_call_remove_members (priv->publish,
+                       -1, &handles, message, NULL, NULL, NULL, NULL);
        }
 }
 
@@ -874,44 +888,40 @@ static GList *
 tp_contact_list_get_members (EmpathyContactList *list)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       GList *ret;
 
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
-       g_list_foreach (priv->members, (GFunc) g_object_ref, NULL);
-       return g_list_copy (priv->members);
+       ret = g_hash_table_get_values (priv->members);
+       g_list_foreach (ret, (GFunc) g_object_ref, NULL);
+       return ret;
 }
 
 static GList *
 tp_contact_list_get_pendings (EmpathyContactList *list)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       GList *ret;
 
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
-       g_list_foreach (priv->pendings, (GFunc) g_object_ref, NULL);
-       return g_list_copy (priv->pendings);
+       ret = g_hash_table_get_values (priv->pendings);
+       g_list_foreach (ret, (GFunc) g_object_ref, NULL);
+       return ret;
 }
 
 static GList *
 tp_contact_list_get_all_groups (EmpathyContactList *list)
 {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       GList                    *groups = NULL, *l;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
+       GList                    *ret, *l;
 
-       if (priv->protocol_group) {
-               groups = g_list_prepend (groups, g_strdup (priv->protocol_group));
+       ret = g_hash_table_get_keys (priv->groups);
+       for (l = ret; l; l = l->next) {
+               l->data = g_strdup (l->data);
        }
 
-       for (l = priv->groups; l; l = l->next) {
-               const gchar *name;
-
-               name = empathy_tp_group_get_name (l->data);
-               groups = g_list_prepend (groups, g_strdup (name));
+       if (priv->protocol_group) {
+               ret = g_list_prepend (ret, g_strdup (priv->protocol_group));
        }
 
-       return groups;
+       return ret;
 }
 
 static GList *
@@ -919,174 +929,119 @@ tp_contact_list_get_groups (EmpathyContactList *list,
                            EmpathyContact     *contact)
 {
        EmpathyTpContactListPriv  *priv = GET_PRIV (list);
-       GList                    **groups;
-       GList                     *ret = NULL, *l;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
+       GList                     *ret = NULL;
+       GHashTableIter             iter;
+       gpointer                   group_name;
+       gpointer                   channel;
+       TpHandle                   handle;
+
+       handle = empathy_contact_get_handle (contact);
+       g_hash_table_iter_init (&iter, priv->groups);
+       while (g_hash_table_iter_next (&iter, &group_name, &channel)) {
+               const TpIntSet *members;
+
+               members = tp_channel_group_get_members (channel);
+               if (tp_intset_is_member (members, handle)) {
+                       ret = g_list_prepend (ret, g_strdup (group_name));
+               }
+       }
 
        if (priv->protocol_group) {
                ret = g_list_prepend (ret, g_strdup (priv->protocol_group));
        }
 
-       groups = g_hash_table_lookup (priv->contacts_groups, contact);
-       if (!groups) {
-               return ret;
-       }
-
-       for (l = *groups; l; l = l->next) {
-               ret = g_list_prepend (ret, g_strdup (l->data));
-       }
-
-
        return ret;
 }
 
-static EmpathyTpGroup *
-tp_contact_list_get_group (EmpathyTpContactList *list,
-                          const gchar          *group)
-{
-       EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       EmpathyTpGroup           *tp_group;
-       gchar                    *object_path;
-       guint                     handle;
-       GArray                   *handles;
-       const char               *names[2] = {group, NULL};
-       GError                   *error = NULL;
-
-       tp_group = tp_contact_list_find_group (list, group);
-       if (tp_group) {
-               return tp_group;
-       }
-
-       DEBUG ("creating new group: %s", group);
-
-       if (!tp_cli_connection_run_request_handles (priv->connection, -1,
-                                                   TP_HANDLE_TYPE_GROUP,
-                                                   names,
-                                                   &handles,
-                                                   &error, NULL)) {
-               DEBUG ("Failed to RequestHandles: %s",
-                       error ? error->message : "No error given");
-               g_clear_error (&error);
-               return NULL;
-       }
-       handle = g_array_index (handles, guint, 0);
-       g_array_free (handles, TRUE);
-
-       if (!tp_cli_connection_run_request_channel (priv->connection, -1,
-                                                   TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
-                                                   TP_HANDLE_TYPE_GROUP,
-                                                   handle,
-                                                   TRUE,
-                                                   &object_path,
-                                                   &error, NULL)) {
-               DEBUG ("Failed to RequestChannel: %s",
-                       error ? error->message : "No error given");
-               g_clear_error (&error);
-               return NULL;
-       }
-
-       tp_contact_list_add_channel (EMPATHY_TP_CONTACT_LIST (list),
-                                    object_path,
-                                    TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
-                                    TP_HANDLE_TYPE_GROUP, handle);
-
-       g_free (object_path);
-
-       return tp_contact_list_find_group (list, group);
-}
-
 static void
 tp_contact_list_add_to_group (EmpathyContactList *list,
                              EmpathyContact     *contact,
-                             const gchar        *group)
+                             const gchar        *group_name)
 {
-       EmpathyTpGroup *tp_group;
-
-       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
-
-       tp_group = tp_contact_list_get_group (EMPATHY_TP_CONTACT_LIST (list),
-                                             group);
-
-       if (tp_group) {
-               empathy_tp_group_add_member (tp_group, contact, "");
-       }
+       TpHandle handle;
+       GArray *handles;
+
+       handle = empathy_contact_get_handle (contact);
+       handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 1);
+       g_array_append_val (handles, handle);
+       tp_contact_list_group_add (EMPATHY_TP_CONTACT_LIST (list),
+                                  group_name, handles);
 }
 
 static void
 tp_contact_list_remove_from_group (EmpathyContactList *list,
                                   EmpathyContact     *contact,
-                                  const gchar        *group)
+                                  const gchar        *group_name)
 {
-       EmpathyTpGroup *tp_group;
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       TpChannel                *channel;
+       TpHandle                  handle;
+       GArray                    handles = {(gchar *) &handle, 1};
 
-       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
+       channel = g_hash_table_lookup (priv->groups, group_name);
+       if (channel == NULL) {
+               return;
+       }
 
-       tp_group = tp_contact_list_find_group (EMPATHY_TP_CONTACT_LIST (list),
-                                              group);
+       handle = empathy_contact_get_handle (contact);
+       DEBUG ("remove contact %s (%d) from group %s",
+               empathy_contact_get_id (contact), handle, group_name);
 
-       if (tp_group) {
-               empathy_tp_group_remove_member (tp_group, contact, "");
-       }
+       tp_cli_channel_interface_group_call_remove_members (channel, -1,
+               &handles, NULL, NULL, NULL, NULL, NULL);
 }
 
 static void
 tp_contact_list_rename_group (EmpathyContactList *list,
-                             const gchar        *old_group,
-                             const gchar        *new_group)
+                             const gchar        *old_group_name,
+                             const gchar        *new_group_name)
 {
-       EmpathyTpGroup *tp_group;
-       GList          *members;
-
-       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       TpChannel                *channel;
+       const TpIntSet           *members;
+       GArray                   *handles;
 
-       tp_group = tp_contact_list_find_group (EMPATHY_TP_CONTACT_LIST (list),
-                                              old_group);
-       if (!tp_group) {
+       channel = g_hash_table_lookup (priv->groups, old_group_name);
+       if (channel == NULL) {
                return;
        }
 
-       DEBUG ("rename group %s to %s", old_group, new_group);
-
-       /* Remove all members from the old group */
-       members = empathy_tp_group_get_members (tp_group);
-       empathy_tp_group_remove_members (tp_group, members, "");
-       empathy_tp_group_close (tp_group);
+       DEBUG ("rename group %s to %s", old_group_name, new_group_name);
 
-       /* Add all members to the new group */
-       tp_group = tp_contact_list_get_group (EMPATHY_TP_CONTACT_LIST (list),
-                                             new_group);
-       empathy_tp_group_add_members (tp_group, members, "");
+       /* Remove all members and close the old channel */
+       members = tp_channel_group_get_members (channel);
+       handles = tp_intset_to_array (members);
+       tp_cli_channel_interface_group_call_remove_members (channel, -1,
+               handles, NULL, NULL, NULL, NULL, NULL);
+       tp_cli_channel_call_close (channel, -1, NULL, NULL, NULL, NULL);
 
-       g_list_foreach (members, (GFunc) g_object_unref, NULL);
-       g_list_free (members);
+       tp_contact_list_group_add (EMPATHY_TP_CONTACT_LIST (list),
+                                  new_group_name, handles);
 }
 
 static void
 tp_contact_list_remove_group (EmpathyContactList *list,
-                             const gchar *group)
+                             const gchar *group_name)
 {
-       EmpathyTpGroup *tp_group;
-       GList          *members;
-
-       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       TpChannel                *channel;
+       const TpIntSet           *members;
+       GArray                   *handles;
 
-       tp_group = tp_contact_list_find_group (EMPATHY_TP_CONTACT_LIST (list),
-                                              group);
-       
-       if (!tp_group) {
+       channel = g_hash_table_lookup (priv->groups, group_name);
+       if (channel == NULL) {
                return;
        }
 
-       DEBUG ("remove group %s", group);
+       DEBUG ("remove group %s", group_name);
 
-       /* Remove all members of the group */
-       members = empathy_tp_group_get_members (tp_group);
-       empathy_tp_group_remove_members (tp_group, members, "");
-       empathy_tp_group_close (tp_group);
-
-       g_list_foreach (members, (GFunc) g_object_unref, NULL);
-       g_list_free (members);
+       /* Remove all members and close the channel */
+       members = tp_channel_group_get_members (channel);
+       handles = tp_intset_to_array (members);
+       tp_cli_channel_interface_group_call_remove_members (channel, -1,
+               handles, NULL, NULL, NULL, NULL, NULL);
+       tp_cli_channel_call_close (channel, -1, NULL, NULL, NULL, NULL);
+       g_array_free (handles, TRUE);
 }
 
 static void
@@ -1117,6 +1072,34 @@ empathy_tp_contact_list_can_add (EmpathyTpContactList *list)
        if (priv->subscribe == NULL)
                return FALSE;
 
-       flags = empathy_tp_group_get_flags (priv->subscribe);
+       flags = tp_channel_group_get_flags (priv->subscribe);
        return (flags & TP_CHANNEL_GROUP_FLAG_CAN_ADD) != 0;
 }
+
+void
+empathy_tp_contact_list_remove_all (EmpathyTpContactList *list)
+{
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       GHashTableIter            iter;
+       gpointer                  contact;
+
+       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
+
+       /* Remove all contacts */
+       g_hash_table_iter_init (&iter, priv->members);
+       while (g_hash_table_iter_next (&iter, NULL, &contact)) {
+               g_signal_emit_by_name (list, "members-changed", contact,
+                                      NULL, 0, NULL,
+                                      FALSE);
+       }
+       g_hash_table_remove_all (priv->members);
+
+       g_hash_table_iter_init (&iter, priv->pendings);
+       while (g_hash_table_iter_next (&iter, NULL, &contact)) {
+               g_signal_emit_by_name (list, "pendings-changed", contact,
+                                      NULL, 0, NULL,
+                                      FALSE);
+       }
+       g_hash_table_remove_all (priv->pendings);
+}
+
index e8edcfacee8d21f9d63d744dd9984b2271688542..c6cf6cb4abe3c4f44a155469ea5ab27a57361a35 100644 (file)
@@ -24,7 +24,7 @@
 #define __EMPATHY_TP_CONTACT_LIST_H__
 
 #include <glib.h>
-#include <libmissioncontrol/mc-account.h>
+#include <telepathy-glib/connection.h>
 
 
 G_BEGIN_DECLS
@@ -49,9 +49,10 @@ struct _EmpathyTpContactListClass {
 };
 
 GType                  empathy_tp_contact_list_get_type    (void) G_GNUC_CONST;
-EmpathyTpContactList * empathy_tp_contact_list_new         (McAccount            *account);
-McAccount *            empathy_tp_contact_list_get_account (EmpathyTpContactList *list);
+EmpathyTpContactList * empathy_tp_contact_list_new         (TpConnection         *connection);
+TpConnection *         empathy_tp_contact_list_get_connection (EmpathyTpContactList *list);
 gboolean               empathy_tp_contact_list_can_add     (EmpathyTpContactList *list);
+void                   empathy_tp_contact_list_remove_all  (EmpathyTpContactList *list);
 
 G_END_DECLS
 
index 1f6bedfb2ac850ac7ba0b42c9e9b2d7fde4299c7..6796f5a0bf82e044ba12799de1c15d7f1f1c63e9 100644 (file)
@@ -39,7 +39,7 @@
 #include <telepathy-glib/util.h>
 
 #include "empathy-tp-file.h"
-#include "empathy-contact-factory.h"
+#include "empathy-tp-contact-factory.h"
 #include "empathy-marshal.h"
 #include "empathy-time.h"
 #include "empathy-utils.h"
@@ -277,9 +277,10 @@ copy_stream (GInputStream *in,
 /* EmpathyTpFile object */
 
 struct _EmpathyTpFilePriv {
-  EmpathyContactFactory *factory;
+  EmpathyTpContactFactory *factory;
   MissionControl *mc;
   TpChannel *channel;
+  gboolean ready;
 
   EmpathyContact *contact;
   GInputStream *in_stream;
@@ -307,6 +308,7 @@ enum {
   PROP_CHANNEL,
   PROP_STATE,
   PROP_INCOMING,
+  PROP_READY,
   PROP_FILENAME,
   PROP_SIZE,
   PROP_CONTENT_TYPE,
@@ -493,81 +495,154 @@ tp_file_transferred_bytes_changed_cb (TpChannel *channel,
   g_object_notify (G_OBJECT (tp_file), "transferred-bytes");
 }
 
-static GObject *
-tp_file_constructor (GType type,
-                     guint n_props,
-                     GObjectConstructParam *props)
+static void
+tp_file_check_if_ready (EmpathyTpFile *tp_file)
 {
-  GObject *file_obj;
-  EmpathyTpFile *tp_file;
-  TpHandle handle;
-  GHashTable *properties;
-  McAccount *account;
-  GValue *requested;
-
-  file_obj = G_OBJECT_CLASS (empathy_tp_file_parent_class)->constructor (type,
-      n_props, props);
-
-  tp_file = EMPATHY_TP_FILE (file_obj);
-
-  tp_file->priv->factory = empathy_contact_factory_dup_singleton ();
-  tp_file->priv->mc = empathy_mission_control_dup_singleton ();
-
-  g_signal_connect (tp_file->priv->channel, "invalidated",
-    G_CALLBACK (tp_file_invalidated_cb), tp_file);
+  if (tp_file->priv->ready || tp_file->priv->contact == NULL ||
+      tp_file->priv->state == 0)
+    return;
 
-  tp_cli_channel_type_file_transfer_connect_to_file_transfer_state_changed (
-      tp_file->priv->channel, tp_file_state_changed_cb, NULL, NULL,
-      G_OBJECT (tp_file), NULL);
+  tp_file->priv->ready = TRUE;
+  g_object_notify (G_OBJECT (tp_file), "ready");
+}
 
-  tp_cli_channel_type_file_transfer_connect_to_transferred_bytes_changed (
-      tp_file->priv->channel, tp_file_transferred_bytes_changed_cb,
-      NULL, NULL, G_OBJECT (tp_file), NULL);
+static void
+tp_file_got_contact_cb (EmpathyTpContactFactory *factory,
+                        EmpathyContact *contact,
+                        const GError *error,
+                        gpointer user_data,
+                        GObject *weak_object)
+{
+  EmpathyTpFile *tp_file = EMPATHY_TP_FILE (weak_object);
 
-  account = empathy_channel_get_account (tp_file->priv->channel);
+  if (error)
+    {
+      DEBUG ("Error: %s", error->message);
+      empathy_tp_file_close (tp_file);
+      return;
+    }
 
-  handle = tp_channel_get_handle (tp_file->priv->channel, NULL);
-  tp_file->priv->contact = empathy_contact_factory_get_from_handle (
-      tp_file->priv->factory, account, (guint) handle);
+  tp_file->priv->contact = g_object_ref (contact);
+  tp_file_check_if_ready (tp_file);
+}
 
-  tp_cli_dbus_properties_run_get_all (tp_file->priv->channel,
-      -1, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, &properties, NULL, NULL);
+static void
+tp_file_get_all_cb (TpProxy *proxy,
+                    GHashTable *properties,
+                    const GError *error,
+                    gpointer user_data,
+                    GObject *file_obj)
+{
+  EmpathyTpFile *tp_file = EMPATHY_TP_FILE (file_obj);
 
-  tp_cli_dbus_properties_run_get (tp_file->priv->channel,
-      -1, TP_IFACE_CHANNEL, "Requested", &requested, NULL, NULL);
+  if (error)
+    {
+      DEBUG ("Error: %s", error->message);
+      tp_cli_channel_call_close (tp_file->priv->channel, -1, NULL, NULL, NULL,
+          NULL);
+      return;
+    }
 
   tp_file->priv->size = g_value_get_uint64 (
       g_hash_table_lookup (properties, "Size"));
+  g_object_notify (file_obj, "size");
 
   tp_file->priv->state = g_value_get_uint (
       g_hash_table_lookup (properties, "State"));
-
-  tp_file->priv->state_change_reason =
-      TP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE;
+  g_object_notify (file_obj, "state");
 
   tp_file->priv->transferred_bytes = g_value_get_uint64 (
       g_hash_table_lookup (properties, "TransferredBytes"));
+  g_object_notify (file_obj, "transferred-bytes");
 
   tp_file->priv->filename = g_value_dup_string (
       g_hash_table_lookup (properties, "Filename"));
+  g_object_notify (file_obj, "filename");
 
   tp_file->priv->content_hash = g_value_dup_string (
       g_hash_table_lookup (properties, "ContentHash"));
+  g_object_notify (file_obj, "content-hash");
 
   tp_file->priv->content_hash_type = g_value_get_uint (
       g_hash_table_lookup (properties, "ContentHashType"));
+  g_object_notify (file_obj, "content-hash-type");
 
   tp_file->priv->content_type = g_value_dup_string (
       g_hash_table_lookup (properties, "ContentType"));
+  g_object_notify (file_obj, "content-type");
 
   tp_file->priv->description = g_value_dup_string (
       g_hash_table_lookup (properties, "Description"));
 
+  tp_file_check_if_ready (tp_file);
+}
+
+static void
+tp_file_get_requested_cb (TpProxy *proxy,
+                          const GValue *requested,
+                          const GError *error,
+                          gpointer user_data,
+                          GObject *weak_object)
+{
+  EmpathyTpFile *tp_file = EMPATHY_TP_FILE (weak_object);
+
+  if (error)
+    {
+      DEBUG ("Error: %s", error->message);
+      tp_cli_channel_call_close (tp_file->priv->channel, -1, NULL, NULL, NULL,
+          NULL);
+      return;
+    }
+
   tp_file->priv->incoming = !g_value_get_boolean (requested);
+  g_object_notify (G_OBJECT (tp_file), "incoming");
+
+  tp_file_check_if_ready (tp_file);
+}
+
+static GObject *
+tp_file_constructor (GType type,
+                     guint n_props,
+                     GObjectConstructParam *props)
+{
+  GObject *file_obj;
+  EmpathyTpFile *tp_file;
+  TpHandle handle;
+  TpConnection *connection;
+
+  file_obj = G_OBJECT_CLASS (empathy_tp_file_parent_class)->constructor (type,
+      n_props, props);
+
+  tp_file = EMPATHY_TP_FILE (file_obj);
+
+  connection = tp_channel_borrow_connection (tp_file->priv->channel);
+  tp_file->priv->factory = empathy_tp_contact_factory_dup_singleton (connection);
+  tp_file->priv->mc = empathy_mission_control_dup_singleton ();
+  tp_file->priv->state_change_reason =
+      TP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE;
+
+  g_signal_connect (tp_file->priv->channel, "invalidated",
+    G_CALLBACK (tp_file_invalidated_cb), tp_file);
+
+  tp_cli_channel_type_file_transfer_connect_to_file_transfer_state_changed (
+      tp_file->priv->channel, tp_file_state_changed_cb, NULL, NULL,
+      G_OBJECT (tp_file), NULL);
+
+  tp_cli_channel_type_file_transfer_connect_to_transferred_bytes_changed (
+      tp_file->priv->channel, tp_file_transferred_bytes_changed_cb,
+      NULL, NULL, G_OBJECT (tp_file), NULL);
 
-  g_hash_table_destroy (properties);
-  g_object_unref (account);
-  g_value_unset (requested);
+  tp_cli_dbus_properties_call_get (tp_file->priv->channel, -1,
+      TP_IFACE_CHANNEL, "Requested",
+      tp_file_get_requested_cb, NULL, NULL, file_obj);
+
+  tp_cli_dbus_properties_call_get_all (tp_file->priv->channel, -1,
+      TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER,
+      tp_file_get_all_cb, NULL, NULL, file_obj);
+
+  handle = tp_channel_get_handle (tp_file->priv->channel, NULL);
+  empathy_tp_contact_factory_get_from_handle (tp_file->priv->factory,
+      handle, tp_file_got_contact_cb, NULL, NULL, file_obj);
 
   return file_obj;
 }
@@ -611,6 +686,9 @@ tp_file_get_property (GObject *object,
       case PROP_TRANSFERRED_BYTES:
         g_value_set_uint64 (value, tp_file->priv->transferred_bytes);
         break;
+      case PROP_READY:
+        g_value_set_boolean (value, tp_file->priv->ready);
+        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
         break;
@@ -956,6 +1034,14 @@ empathy_tp_file_close (EmpathyTpFile *tp_file)
   empathy_tp_file_cancel (tp_file);
 }
 
+gboolean
+empathy_tp_file_is_ready (EmpathyTpFile *tp_file)
+{
+  g_return_val_if_fail (EMPATHY_IS_TP_FILE (tp_file), FALSE);
+
+  return tp_file->priv->ready;
+}
+
 static void
 empathy_tp_file_class_init (EmpathyTpFileClass *klass)
 {
@@ -996,6 +1082,14 @@ empathy_tp_file_class_init (EmpathyTpFileClass *klass)
           G_PARAM_READWRITE |
           G_PARAM_CONSTRUCT));
 
+  g_object_class_install_property (object_class,
+      PROP_READY,
+      g_param_spec_boolean ("ready",
+          "ready",
+          "Whether the object is ready",
+          FALSE,
+          G_PARAM_READABLE));
+
   g_object_class_install_property (object_class,
       PROP_FILENAME,
       g_param_spec_string ("filename",
index 42c54e4f0b9373a368a458484acd0bb09cf5c669..5f239c8e0df5a999935ad734f412a15605ad36b4 100644 (file)
@@ -81,6 +81,7 @@ guint64 empathy_tp_file_get_size (EmpathyTpFile *tp_file);
 guint64 empathy_tp_file_get_transferred_bytes (EmpathyTpFile *tp_file);
 gint empathy_tp_file_get_remaining_time (EmpathyTpFile *tp_file);
 const gchar *empathy_tp_file_get_content_type (EmpathyTpFile *tp_file);
+gboolean empathy_tp_file_is_ready (EmpathyTpFile *tp_file);
 
 G_END_DECLS
 
diff --git a/libempathy/empathy-tp-group.c b/libempathy/empathy-tp-group.c
deleted file mode 100644 (file)
index c3471c1..0000000
+++ /dev/null
@@ -1,981 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2006 Xavier Claessens <xclaesse@gmail.com>
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Authors: Xavier Claessens <xclaesse@gmail.com>
- */
-
-#include <config.h>
-
-#include <libmissioncontrol/mc-account.h>
-
-#include <telepathy-glib/util.h>
-#include <telepathy-glib/interfaces.h>
-
-#include "empathy-tp-group.h"
-#include "empathy-contact-factory.h"
-#include "empathy-utils.h"
-#include "empathy-marshal.h"
-
-#define DEBUG_FLAG EMPATHY_DEBUG_TP
-#include "empathy-debug.h"
-
-#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpGroup)
-typedef struct {
-       TpChannel             *channel;
-       gboolean               ready;
-
-       EmpathyContactFactory *factory;
-       McAccount             *account;
-       gchar                 *group_name;
-       guint                  self_handle;
-       GList                 *members;
-       GList                 *local_pendings;
-       GList                 *remote_pendings;
-} EmpathyTpGroupPriv;
-
-enum {
-       MEMBER_ADDED,
-       MEMBER_REMOVED,
-       LOCAL_PENDING,
-       REMOTE_PENDING,
-       DESTROY,
-       LAST_SIGNAL
-};
-
-enum {
-       PROP_0,
-       PROP_CHANNEL,
-       PROP_READY
-};
-
-static guint signals[LAST_SIGNAL];
-
-G_DEFINE_TYPE (EmpathyTpGroup, empathy_tp_group, G_TYPE_OBJECT);
-
-static EmpathyContact *
-tp_group_get_contact (EmpathyTpGroup *group,
-                     guint           handle)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-       EmpathyContact     *contact = NULL;
-       
-       if (handle != 0) {
-               contact = empathy_contact_factory_get_from_handle (priv->factory,
-                                                                  priv->account,
-                                                                  handle);
-       }
-
-       if (contact && handle == priv->self_handle) {
-               empathy_contact_set_is_user (contact, TRUE);
-       }
-
-       return contact;
-}
-
-static GList *
-tp_group_get_contacts (EmpathyTpGroup *group,
-                      const GArray   *handles)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-       GList              *contacts,  *l;
-
-       if (!handles) {
-               return NULL;
-       }
-
-       contacts = empathy_contact_factory_get_from_handles (priv->factory,
-                                                            priv->account,
-                                                            handles);
-
-       /* FIXME: Only useful if the group has a different self handle than
-        * the connection, otherwise the contact factory already set that
-        * property. That can be known using group flags. */
-       for (l = contacts; l; l = l->next) {
-               if (empathy_contact_get_handle (l->data) == priv->self_handle) {
-                       empathy_contact_set_is_user (l->data, TRUE);
-               }
-       }
-
-       return contacts;
-}
-
-EmpathyPendingInfo *
-empathy_pending_info_new (EmpathyContact *member,
-                         EmpathyContact *actor,
-                         const gchar    *message)
-{
-       EmpathyPendingInfo *info;
-
-       info = g_slice_new0 (EmpathyPendingInfo);
-
-       if (member) {
-               info->member = g_object_ref (member);
-       }
-       if (actor) {
-               info->actor = g_object_ref (actor);
-       }
-       if (message) {
-               info->message = g_strdup (message);
-       }
-
-       return info;
-}
-
-void
-empathy_pending_info_free (EmpathyPendingInfo *info)
-{
-       if (!info) {
-               return;
-       }
-
-       if (info->member) {
-               g_object_unref (info->member);
-       }
-       if (info->actor) {
-               g_object_unref (info->actor);
-       }
-       g_free (info->message);
-
-       g_slice_free (EmpathyPendingInfo, info);
-}
-
-static gint
-tp_group_local_pending_find (gconstpointer a,
-                            gconstpointer b)
-{
-       const EmpathyPendingInfo *info = a;
-
-       return (info->member != b);
-}
-
-static void
-tp_group_remove_from_pendings (EmpathyTpGroup *group,
-                              EmpathyContact *contact)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-       GList              *l;
-
-       /* local pending */
-       l = g_list_find_custom (priv->local_pendings,
-                               contact,
-                               tp_group_local_pending_find);
-       if (l) {
-               empathy_pending_info_free (l->data);
-               priv->local_pendings = g_list_delete_link (priv->local_pendings, l);
-       }
-
-       /* remote pending */
-       l = g_list_find (priv->remote_pendings, contact);
-       if (l) {
-               g_object_unref (l->data);
-               priv->remote_pendings = g_list_delete_link (priv->remote_pendings, l);
-       }
-}
-
-static void
-tp_group_update_members (EmpathyTpGroup *group,
-                        const gchar    *message,
-                        const GArray   *added,
-                        const GArray   *removed,
-                        const GArray   *local_pending,
-                        const GArray   *remote_pending,
-                        guint           actor,
-                        guint           reason)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-       EmpathyContact     *actor_contact = NULL;
-       GList              *contacts, *l, *ll;
-
-       actor_contact = tp_group_get_contact (group, actor);
-
-       DEBUG ("Members changed for list %s:\n"
-               "  added-len=%d, current-len=%d\n"
-               "  removed-len=%d\n"
-               "  local-pending-len=%d, current-len=%d\n"
-               "  remote-pending-len=%d, current-len=%d",
-               priv->group_name, added ? added->len : 0,
-               g_list_length (priv->members), removed ? removed->len : 0,
-               local_pending ? local_pending->len : 0,
-               g_list_length (priv->local_pendings),
-               remote_pending ? remote_pending->len : 0,
-               g_list_length (priv->remote_pendings));
-
-       /* Contacts added */
-       contacts = tp_group_get_contacts (group, added);
-       for (l = contacts; l; l = l->next) {
-               tp_group_remove_from_pendings (group, l->data);
-
-               /* If the contact is not yet member, add it and emit signal */
-               if (!g_list_find (priv->members, l->data)) {
-                       priv->members = g_list_prepend (priv->members,
-                                                       g_object_ref (l->data));
-                       g_signal_emit (group, signals[MEMBER_ADDED], 0,
-                                      l->data, actor_contact, reason, message);
-               }
-               g_object_unref (l->data);
-       }
-       g_list_free (contacts);
-
-       /* Contacts removed */
-       contacts = tp_group_get_contacts (group, removed);
-       for (l = contacts; l; l = l->next) {
-               tp_group_remove_from_pendings (group, l->data);
-
-               /* If the contact is member, remove it and emit signal */
-               if ((ll = g_list_find (priv->members, l->data))) {
-                       g_object_unref (ll->data);
-                       priv->members = g_list_delete_link (priv->members, ll);
-                       g_signal_emit (group, signals[MEMBER_REMOVED], 0,
-                                      l->data, actor_contact, reason, message);
-               }
-               g_object_unref (l->data);
-       }
-       g_list_free (contacts);
-
-       /* Contacts local pending */
-       contacts = tp_group_get_contacts (group, local_pending);
-       for (l = contacts; l; l = l->next) {
-               /* If the contact is not yet local-pending, add it and emit signal */
-               if (!g_list_find_custom (priv->local_pendings, l->data,
-                                        tp_group_local_pending_find)) {
-                       EmpathyPendingInfo *info;
-
-                       info = empathy_pending_info_new (l->data,
-                                                        actor_contact,
-                                                        message);
-
-                       priv->local_pendings = g_list_prepend (priv->local_pendings, info);
-                       g_signal_emit (group, signals[LOCAL_PENDING], 0,
-                                      l->data, actor_contact, reason, message);
-               }
-               g_object_unref (l->data);
-       }
-       g_list_free (contacts);
-
-       /* Contacts remote pending */
-       contacts = tp_group_get_contacts (group, remote_pending);
-       for (l = contacts; l; l = l->next) {
-               /* If the contact is not yet remote-pending, add it and emit signal */
-               if (!g_list_find (priv->remote_pendings, l->data)) {
-                       priv->remote_pendings = g_list_prepend (priv->remote_pendings,
-                                                               g_object_ref (l->data));
-                       g_signal_emit (group, signals[REMOTE_PENDING], 0,
-                                      l->data, actor_contact, reason, message);
-               }
-               g_object_unref (l->data);
-       }
-       g_list_free (contacts);
-
-       if (actor_contact) {
-               g_object_unref (actor_contact);
-       }
-
-       DEBUG ("Members changed done for list %s:\n"
-               "  members-len=%d\n"
-               "  local-pendings-len=%d\n"
-               "  remote-pendings-len=%d",
-               priv->group_name, g_list_length (priv->members),
-               g_list_length (priv->local_pendings),
-               g_list_length (priv->remote_pendings));
-}
-
-static void
-tp_group_members_changed_cb (TpChannel    *channel,
-                            const gchar  *message,
-                            const GArray *added,
-                            const GArray *removed,
-                            const GArray *local_pending,
-                            const GArray *remote_pending,
-                            guint         actor,
-                            guint         reason,
-                            gpointer      user_data,
-                            GObject      *group)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-
-       if (priv->ready) {
-               tp_group_update_members (EMPATHY_TP_GROUP (group), message,
-                                        added, removed,
-                                        local_pending, remote_pending,
-                                        actor, reason);
-       }
-}
-
-static void
-tp_group_get_members_cb (TpChannel    *channel,
-                        const GArray *handles,
-                        const GError *error,
-                        gpointer      user_data,
-                        GObject      *group)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-
-       if (error) {
-               DEBUG ("Failed to get members: %s", error->message);
-               return;
-       }
-
-       tp_group_update_members (EMPATHY_TP_GROUP (group),
-                                NULL,    /* message */
-                                handles, /* added */
-                                NULL,    /* removed */
-                                NULL,    /* local_pending */
-                                NULL,    /* remote_pending */
-                                0,       /* actor */
-                                0);      /* reason */
-
-       DEBUG ("Ready");
-       priv->ready = TRUE;
-       g_object_notify (group, "ready");
-}
-
-static void
-tp_group_get_local_pending_cb (TpChannel        *channel,
-                              const GPtrArray  *array,
-                              const GError     *error,
-                              gpointer          user_data,
-                              GObject          *group)
-{
-       GArray *handles;
-       guint   i = 0;
-       
-       if (error) {
-               DEBUG ("Failed to get local pendings: %s", error->message);
-               return;
-       }
-
-       handles = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
-       g_array_append_val (handles, i);
-       for (i = 0; array->len > i; i++) {
-               GValueArray *pending_struct;
-               const gchar *message;
-               guint        member_handle;
-               guint        actor_handle;
-               guint        reason;
-
-               pending_struct = g_ptr_array_index (array, i);
-               member_handle = g_value_get_uint (g_value_array_get_nth (pending_struct, 0));
-               actor_handle = g_value_get_uint (g_value_array_get_nth (pending_struct, 1));
-               reason = g_value_get_uint (g_value_array_get_nth (pending_struct, 2));
-               message = g_value_get_string (g_value_array_get_nth (pending_struct, 3));
-
-               g_array_index (handles, guint, 0) = member_handle;
-
-               tp_group_update_members (EMPATHY_TP_GROUP (group),
-                                        message,      /* message */
-                                        NULL,         /* added */
-                                        NULL,         /* removed */
-                                        handles,      /* local_pending */
-                                        NULL,         /* remote_pending */
-                                        actor_handle, /* actor */
-                                        reason);      /* reason */
-       }
-       g_array_free (handles, TRUE);
-}
-
-static void
-tp_group_get_remote_pending_cb (TpChannel    *channel,
-                               const GArray *handles,
-                               const GError *error,
-                               gpointer      user_data,
-                               GObject      *group)
-{
-       if (error) {
-               DEBUG ("Failed to get remote pendings: %s", error->message);
-               return;
-       }
-
-       tp_group_update_members (EMPATHY_TP_GROUP (group),
-                                NULL,    /* message */
-                                NULL,    /* added */
-                                NULL,    /* removed */
-                                NULL,    /* local_pending */
-                                handles, /* remote_pending */
-                                0,       /* actor */
-                                0);      /* reason */
-}
-
-static void
-tp_group_inspect_handles_cb (TpConnection  *connection,
-                            const gchar  **names,
-                            const GError  *error,
-                            gpointer       user_data,
-                            GObject       *group)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-
-       if (error) {
-               DEBUG ("Failed to inspect channel handle: %s", error->message);
-               return;
-       }
-
-       priv->group_name = g_strdup (*names);
-}
-
-static void
-tp_group_invalidated_cb (TpProxy        *proxy,
-                        guint           domain,
-                        gint            code,
-                        gchar          *message,
-                        EmpathyTpGroup *group)
-{
-       DEBUG ("Channel invalidated: %s", message);
-       g_signal_emit (group, signals[DESTROY], 0);
-}
-
-static void
-tp_group_get_self_handle_cb (TpChannel    *proxy,
-                            guint         handle,
-                            const GError *error,
-                            gpointer      user_data,
-                            GObject      *group)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-       TpConnection       *connection;
-       guint               channel_handle;
-       guint               channel_handle_type;
-       GArray             *handles;
-
-       if (error) {
-               DEBUG ("Failed to get self handle: %s", error->message);
-               return;
-       }
-
-       priv->self_handle = handle;
-       tp_cli_channel_interface_group_connect_to_members_changed (priv->channel,
-                                                                  tp_group_members_changed_cb,
-                                                                  NULL, NULL,
-                                                                  group, NULL);
-
-       /* GetMembers is called last, so it will be the last to get the reply,
-        * so we'll be ready once that call return. */
-       g_object_get (priv->channel,
-                     "connection", &connection,
-                     "handle-type", &channel_handle_type,
-                     "handle", &channel_handle,
-                     NULL);
-       handles = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
-       g_array_prepend_val (handles, channel_handle);
-       tp_cli_connection_call_inspect_handles (connection, -1,
-                                               channel_handle_type,
-                                               handles,
-                                               tp_group_inspect_handles_cb,
-                                               NULL, NULL,
-                                               group);
-       g_array_free (handles, TRUE);
-
-       tp_cli_channel_interface_group_call_get_local_pending_members_with_info
-                                                       (priv->channel, -1,
-                                                        tp_group_get_local_pending_cb,
-                                                        NULL, NULL, 
-                                                        group);
-       tp_cli_channel_interface_group_call_get_remote_pending_members
-                                                       (priv->channel, -1,
-                                                        tp_group_get_remote_pending_cb,
-                                                        NULL, NULL, 
-                                                        group);
-       tp_cli_channel_interface_group_call_get_members (priv->channel, -1,
-                                                        tp_group_get_members_cb,
-                                                        NULL, NULL, 
-                                                        group);
-}
-
-static void
-tp_group_factory_ready_cb (EmpathyTpGroup *group)
-{
-       EmpathyTpGroupPriv      *priv = GET_PRIV (group);
-       EmpathyTpContactFactory *tp_factory;
-
-       tp_factory = empathy_contact_factory_get_tp_factory (priv->factory, priv->account);
-       g_signal_handlers_disconnect_by_func (tp_factory, tp_group_factory_ready_cb, group);
-       tp_cli_channel_interface_group_call_get_self_handle (priv->channel, -1,
-                                                            tp_group_get_self_handle_cb,
-                                                            NULL, NULL,
-                                                            G_OBJECT (group));
-}
-
-static void
-tp_group_channel_ready_cb (EmpathyTpGroup *group)
-{
-       EmpathyTpGroupPriv      *priv = GET_PRIV (group);
-       EmpathyTpContactFactory *tp_factory;
-
-       tp_factory = empathy_contact_factory_get_tp_factory (priv->factory,
-                                                            priv->account);
-       if (empathy_tp_contact_factory_is_ready (tp_factory)) {
-               tp_group_factory_ready_cb (group);
-       } else {
-               g_signal_connect_swapped (tp_factory, "notify::ready",
-                                         G_CALLBACK (tp_group_factory_ready_cb),
-                                         group);
-       }
-}
-
-static void
-tp_group_finalize (GObject *object)
-{
-       EmpathyTpGroupPriv      *priv = GET_PRIV (object);
-       EmpathyTpContactFactory *tp_factory;
-
-       DEBUG ("finalize: %p", object);
-
-       tp_factory = empathy_contact_factory_get_tp_factory (priv->factory, priv->account);
-       g_signal_handlers_disconnect_by_func (tp_factory, tp_group_factory_ready_cb, object);
-
-       if (priv->channel) {
-               g_signal_handlers_disconnect_by_func (priv->channel,
-                                                     tp_group_invalidated_cb,
-                                                     object);
-               g_object_unref (priv->channel);
-       }
-       if (priv->account) {
-               g_object_unref (priv->account);
-       }
-       if (priv->factory) {
-               g_object_unref (priv->factory);
-       }
-       g_free (priv->group_name);
-
-       g_list_foreach (priv->members, (GFunc) g_object_unref, NULL);
-       g_list_free (priv->members);
-
-       g_list_foreach (priv->local_pendings, (GFunc) empathy_pending_info_free, NULL);
-       g_list_free (priv->local_pendings);
-
-       g_list_foreach (priv->remote_pendings, (GFunc) g_object_unref, NULL);
-       g_list_free (priv->remote_pendings);
-
-       G_OBJECT_CLASS (empathy_tp_group_parent_class)->finalize (object);
-}
-
-static void
-tp_group_constructed (GObject *group)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-       gboolean            channel_ready;
-
-       priv->factory = empathy_contact_factory_dup_singleton ();
-       priv->account = empathy_channel_get_account (priv->channel);
-
-       g_signal_connect (priv->channel, "invalidated",
-                         G_CALLBACK (tp_group_invalidated_cb),
-                         group);
-
-       g_object_get (priv->channel, "channel-ready", &channel_ready, NULL);
-       if (channel_ready) {
-               tp_group_channel_ready_cb (EMPATHY_TP_GROUP (group));
-       } else {
-               g_signal_connect_swapped (priv->channel, "notify::channel-ready",
-                                         G_CALLBACK (tp_group_channel_ready_cb),
-                                         group);
-       }
-}
-
-static void
-tp_group_get_property (GObject    *object,
-                      guint       param_id,
-                      GValue     *value,
-                      GParamSpec *pspec)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (object);
-
-       switch (param_id) {
-       case PROP_CHANNEL:
-               g_value_set_object (value, priv->channel);
-               break;
-       case PROP_READY:
-               g_value_set_boolean (value, priv->ready);
-               break;
-       default:
-               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-               break;
-       };
-}
-
-static void
-tp_group_set_property (GObject      *object,
-                      guint         param_id,
-                      const GValue *value,
-                      GParamSpec   *pspec)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (object);
-
-       switch (param_id) {
-       case PROP_CHANNEL:
-               priv->channel = g_object_ref (g_value_get_object (value));
-               break;
-       default:
-               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-               break;
-       };
-}
-
-static void
-empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
-{
-       GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-       object_class->finalize = tp_group_finalize;
-       object_class->constructed = tp_group_constructed;
-       object_class->get_property = tp_group_get_property;
-       object_class->set_property = tp_group_set_property;
-
-       g_object_class_install_property (object_class,
-                                        PROP_CHANNEL,
-                                        g_param_spec_object ("channel",
-                                                             "telepathy channel",
-                                                             "The channel for the group",
-                                                             TP_TYPE_CHANNEL,
-                                                             G_PARAM_READWRITE |
-                                                             G_PARAM_CONSTRUCT_ONLY));
-       g_object_class_install_property (object_class,
-                                        PROP_READY,
-                                        g_param_spec_boolean ("ready",
-                                                              "Is the object ready",
-                                                              "This object can't be used until this becomes true",
-                                                              FALSE,
-                                                              G_PARAM_READABLE));
-
-       signals[MEMBER_ADDED] =
-               g_signal_new ("member-added",
-                             G_TYPE_FROM_CLASS (klass),
-                             G_SIGNAL_RUN_LAST,
-                             0,
-                             NULL, NULL,
-                             _empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
-                             G_TYPE_NONE,
-                             4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
-
-       signals[MEMBER_REMOVED] =
-               g_signal_new ("member-removed",
-                             G_TYPE_FROM_CLASS (klass),
-                             G_SIGNAL_RUN_LAST,
-                             0,
-                             NULL, NULL,
-                             _empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
-                             G_TYPE_NONE,
-                             4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
-
-       signals[LOCAL_PENDING] =
-               g_signal_new ("local-pending",
-                             G_TYPE_FROM_CLASS (klass),
-                             G_SIGNAL_RUN_LAST,
-                             0,
-                             NULL, NULL,
-                             _empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
-                             G_TYPE_NONE,
-                             4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
-
-       signals[REMOTE_PENDING] =
-               g_signal_new ("remote-pending",
-                             G_TYPE_FROM_CLASS (klass),
-                             G_SIGNAL_RUN_LAST,
-                             0,
-                             NULL, NULL,
-                             _empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
-                             G_TYPE_NONE,
-                             4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
-
-       signals[DESTROY] =
-               g_signal_new ("destroy",
-                             G_TYPE_FROM_CLASS (klass),
-                             G_SIGNAL_RUN_LAST,
-                             0,
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__VOID,
-                             G_TYPE_NONE,
-                             0);
-
-       g_type_class_add_private (object_class, sizeof (EmpathyTpGroupPriv));
-}
-
-static void
-empathy_tp_group_init (EmpathyTpGroup *group)
-{
-       EmpathyTpGroupPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
-               EMPATHY_TYPE_TP_GROUP, EmpathyTpGroupPriv);
-
-       group->priv = priv;
-}
-
-EmpathyTpGroup *
-empathy_tp_group_new (TpChannel *channel)
-{
-       g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
-
-       return g_object_new (EMPATHY_TYPE_TP_GROUP, 
-                            "channel", channel,
-                            NULL);
-}
-
-static void
-tp_group_async_cb (TpChannel    *channel,
-                  const GError *error,
-                  gpointer      user_data,
-                  GObject      *weak_object)
-{
-       if (error) {
-               DEBUG ("%s: %s", (gchar*) user_data, error->message);
-       }
-}
-
-void
-empathy_tp_group_close (EmpathyTpGroup *group)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-
-       g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
-       g_return_if_fail (priv->ready);
-
-       tp_cli_channel_call_close (priv->channel, -1,
-                                  tp_group_async_cb,
-                                  "Failed to close", NULL,
-                                  G_OBJECT (group));
-}
-
-static GArray *
-tp_group_get_handles (GList *contacts)
-{
-       GArray *handles;
-       guint   length;
-       GList  *l;
-
-       length = g_list_length (contacts);
-       handles = g_array_sized_new (FALSE, FALSE, sizeof (guint), length);
-
-       for (l = contacts; l; l = l->next) {
-               guint handle;
-
-               handle = empathy_contact_get_handle (l->data);
-               g_array_append_val (handles, handle);
-       }
-
-       return handles;
-}
-
-void
-empathy_tp_group_add_members (EmpathyTpGroup *group,
-                             GList          *contacts,
-                             const gchar    *message)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-       GArray             *handles;
-
-       g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
-       g_return_if_fail (contacts != NULL);
-       g_return_if_fail (priv->ready);
-
-       handles = tp_group_get_handles (contacts);
-       tp_cli_channel_interface_group_call_add_members (priv->channel, -1,
-                                                        handles,
-                                                        message,
-                                                        tp_group_async_cb,
-                                                        "Failed to add members", NULL,
-                                                        G_OBJECT (group));
-       g_array_free (handles, TRUE);
-}
-
-void
-empathy_tp_group_remove_members (EmpathyTpGroup *group,
-                                GList          *contacts,
-                                const gchar    *message)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-       GArray             *handles;
-
-       g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
-       g_return_if_fail (contacts != NULL);
-       g_return_if_fail (priv->ready);
-
-       handles = tp_group_get_handles (contacts);
-       tp_cli_channel_interface_group_call_remove_members (priv->channel, -1,
-                                                           handles,
-                                                           message,
-                                                           tp_group_async_cb,
-                                                           "Failed to remove members", NULL,
-                                                           G_OBJECT (group));
-       g_array_free (handles, TRUE);
-}
-
-void
-empathy_tp_group_add_member (EmpathyTpGroup *group,
-                            EmpathyContact *contact,
-                            const gchar    *message)
-{
-       GList *contacts;
-
-       contacts = g_list_prepend (NULL, contact);
-       empathy_tp_group_add_members (group, contacts, message);
-       g_list_free (contacts);
-}
-
-void
-empathy_tp_group_remove_member (EmpathyTpGroup *group,
-                               EmpathyContact *contact,
-                               const gchar    *message)
-{
-       GList *contacts;
-
-       contacts = g_list_prepend (NULL, contact);
-       empathy_tp_group_remove_members (group, contacts, message);
-       g_list_free (contacts);
-}
-
-GList *
-empathy_tp_group_get_members (EmpathyTpGroup *group)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
-
-       g_list_foreach (priv->members, (GFunc) g_object_ref, NULL);
-
-       return g_list_copy (priv->members);
-}
-
-GList *
-empathy_tp_group_get_local_pendings (EmpathyTpGroup *group)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-       GList              *pendings = NULL, *l;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
-
-       for (l = priv->local_pendings; l; l = l->next) {
-               EmpathyPendingInfo *info;
-               EmpathyPendingInfo *new_info;
-
-               info = l->data;
-               new_info = empathy_pending_info_new (info->member,
-                                                    info->actor,
-                                                    info->message);
-               pendings = g_list_prepend (pendings, new_info);
-       }
-
-       return pendings;
-}
-
-GList *
-empathy_tp_group_get_remote_pendings (EmpathyTpGroup *group)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
-
-       g_list_foreach (priv->remote_pendings, (GFunc) g_object_ref, NULL);
-
-       return g_list_copy (priv->remote_pendings);
-}
-
-const gchar *
-empathy_tp_group_get_name (EmpathyTpGroup *group)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
-       g_return_val_if_fail (priv->ready, NULL);
-
-       return priv->group_name;
-}
-
-EmpathyContact *
-empathy_tp_group_get_self_contact (EmpathyTpGroup *group)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
-       g_return_val_if_fail (priv->ready, NULL);
-
-       return tp_group_get_contact (group, priv->self_handle);
-}
-
-gboolean
-empathy_tp_group_is_member (EmpathyTpGroup *group,
-                           EmpathyContact *contact)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), FALSE);
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
-
-       return g_list_find (priv->members, contact) != NULL;
-}
-
-gboolean
-empathy_tp_group_is_ready (EmpathyTpGroup *group)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), FALSE);
-
-       return priv->ready;
-}
-
-EmpathyPendingInfo *
-empathy_tp_group_get_invitation (EmpathyTpGroup  *group,
-                                EmpathyContact **remote_contact)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (group);
-       EmpathyContact     *contact = NULL;
-       EmpathyPendingInfo *invitation = NULL;
-       GList              *l;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), FALSE);
-       g_return_val_if_fail (priv->ready, NULL);
-
-       for (l = priv->local_pendings; l; l = l->next) {
-               EmpathyPendingInfo *info = l->data;
-
-               if (empathy_contact_is_user (info->member)) {
-                       invitation = info;
-                       break;
-               }
-       }
-
-       if (invitation) {
-               contact = invitation->actor;
-       }
-       if (!invitation) {
-               if (priv->remote_pendings) {
-                       contact = priv->remote_pendings->data;
-               }
-               else if (priv->members) {
-                       contact = priv->members->data;
-               }
-       }
-
-       if (remote_contact && contact) {
-               *remote_contact = g_object_ref (contact);
-       }
-
-       return invitation;
-}
-
-TpChannelGroupFlags
-empathy_tp_group_get_flags (EmpathyTpGroup *self)
-{
-       EmpathyTpGroupPriv *priv = GET_PRIV (self);
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (self), 0);
-
-       if (priv->channel == NULL)
-               return 0;
-
-       return tp_channel_group_get_flags (priv->channel);
-}
diff --git a/libempathy/empathy-tp-group.h b/libempathy/empathy-tp-group.h
deleted file mode 100644 (file)
index 9e0dd53..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2006 Xavier Claessens <xclaesse@gmail.com>
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Authors: Xavier Claessens <xclaesse@gmail.com>
- */
-
-#ifndef __EMPATHY_TP_GROUP_H__
-#define __EMPATHY_TP_GROUP_H__
-
-#include <glib.h>
-
-#include <telepathy-glib/channel.h>
-
-#include "empathy-contact.h"
-
-G_BEGIN_DECLS
-
-#define EMPATHY_TYPE_TP_GROUP         (empathy_tp_group_get_type ())
-#define EMPATHY_TP_GROUP(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_TP_GROUP, EmpathyTpGroup))
-#define EMPATHY_TP_GROUP_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), EMPATHY_TYPE_TP_GROUP, EmpathyTpGroupClass))
-#define EMPATHY_IS_TP_GROUP(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_TP_GROUP))
-#define EMPATHY_IS_TP_GROUP_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_TP_GROUP))
-#define EMPATHY_TP_GROUP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_TP_GROUP, EmpathyTpGroupClass))
-
-typedef struct _EmpathyTpGroup      EmpathyTpGroup;
-typedef struct _EmpathyTpGroupClass EmpathyTpGroupClass;
-
-struct _EmpathyTpGroup {
-       GObject parent;
-       gpointer priv;
-};
-
-struct _EmpathyTpGroupClass {
-       GObjectClass parent_class;
-};
-
-typedef struct {
-       EmpathyContact *member;
-       EmpathyContact *actor;
-       gchar          *message;
-       guint           reason;
-} EmpathyPendingInfo;
-
-GType               empathy_tp_group_get_type            (void) G_GNUC_CONST;
-EmpathyTpGroup *    empathy_tp_group_new                 (TpChannel          *channel);
-void                empathy_tp_group_close               (EmpathyTpGroup     *group);
-void                empathy_tp_group_add_members         (EmpathyTpGroup     *group,
-                                                         GList              *contacts,
-                                                         const gchar        *message);
-void                empathy_tp_group_add_member          (EmpathyTpGroup     *group,
-                                                         EmpathyContact     *contact,
-                                                         const gchar        *message);
-void                empathy_tp_group_remove_members      (EmpathyTpGroup     *group,
-                                                         GList              *contacts,
-                                                         const gchar        *message);
-void                empathy_tp_group_remove_member       (EmpathyTpGroup     *group,
-                                                         EmpathyContact     *contact,
-                                                         const gchar        *message);
-GList *             empathy_tp_group_get_members         (EmpathyTpGroup     *group);
-GList *             empathy_tp_group_get_local_pendings  (EmpathyTpGroup     *group);
-GList *             empathy_tp_group_get_remote_pendings (EmpathyTpGroup     *group);
-const gchar *       empathy_tp_group_get_name            (EmpathyTpGroup     *group);
-EmpathyContact *    empathy_tp_group_get_self_contact    (EmpathyTpGroup     *group);
-gboolean            empathy_tp_group_is_member           (EmpathyTpGroup     *group,
-                                                         EmpathyContact     *contact);
-gboolean            empathy_tp_group_is_ready            (EmpathyTpGroup     *group);
-EmpathyPendingInfo *empathy_tp_group_get_invitation      (EmpathyTpGroup     *group,
-                                                         EmpathyContact    **remote_contact);
-EmpathyPendingInfo *empathy_pending_info_new             (EmpathyContact     *member,
-                                                         EmpathyContact     *actor,
-                                                         const gchar        *message);
-void                empathy_pending_info_free            (EmpathyPendingInfo *info);
-TpChannelGroupFlags empathy_tp_group_get_flags           (EmpathyTpGroup     *group);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_TP_GROUP_H__ */
index 746708fc424579e18ec940984f15bd3b3a0ca1aa..7d22f6b783cae6d7d16faedb99e8a8246f4b0f9d 100644 (file)
@@ -390,8 +390,6 @@ empathy_tp_tube_new_stream_tube (EmpathyContact *contact,
                                  const gchar *service,
                                  GHashTable *parameters)
 {
-  MissionControl *mc;
-  McAccount *account;
   TpConnection *connection;
   TpChannel *channel;
   gchar *object_path;
@@ -408,12 +406,7 @@ empathy_tp_tube_new_stream_tube (EmpathyContact *contact,
   g_return_val_if_fail (hostname != NULL, NULL);
   g_return_val_if_fail (service != NULL, NULL);
 
-  mc = empathy_mission_control_dup_singleton ();
-  account = empathy_contact_get_account (contact);
-  connection = mission_control_get_tpconnection (mc, account, NULL);
-  g_object_unref (mc);
-
-  tp_connection_run_until_ready (connection, FALSE, NULL, NULL);
+  connection = empathy_contact_get_connection (contact);
 
   request = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
       (GDestroyNotify) tp_g_value_slice_free);
index a476d9e54da325cb192dd49737f0e9143710a95c..210c3504856b90d7eeec2587beb003f6c921009c 100644 (file)
@@ -37,7 +37,6 @@
 #include <telepathy-glib/dbus.h>
 
 #include "empathy-utils.h"
-#include "empathy-contact-factory.h"
 #include "empathy-contact-manager.h"
 #include "empathy-dispatcher.h"
 #include "empathy-dispatch-operation.h"
@@ -332,97 +331,6 @@ empathy_file_lookup (const gchar *filename, const gchar *subdir)
        return path;
 }
 
-typedef struct {
-       EmpathyRunUntilReadyFunc  func;
-       gpointer                  user_data;
-       GObject                  *object;
-       GMainLoop                *loop;
-} RunUntilReadyData;
-
-static void
-run_until_ready_cb (RunUntilReadyData *data)
-{
-       if (!data->func || data->func (data->object, data->user_data)) {
-               DEBUG ("Object %p is ready", data->object);
-               g_main_loop_quit (data->loop);
-       }
-}
-
-static gboolean
-object_is_ready (GObject *object,
-                gpointer user_data)
-{
-       gboolean ready;
-
-       g_object_get (object, "ready", &ready, NULL);
-
-       return ready;
-}
-
-void
-empathy_run_until_ready_full (gpointer                  object,
-                             const gchar              *signal,
-                             EmpathyRunUntilReadyFunc  func,
-                             gpointer                  user_data,
-                             GMainLoop               **loop)
-{
-       RunUntilReadyData  data;
-       gulong             signal_id;
-
-       g_return_if_fail (G_IS_OBJECT (object));
-       g_return_if_fail (signal != NULL);
-
-       if (func && func (object, user_data)) {
-               return;
-       }
-
-       DEBUG ("Starting run until ready for object %p", object);
-
-       data.func = func;
-       data.user_data = user_data;
-       data.object = object;
-       data.loop = g_main_loop_new (NULL, FALSE);
-
-       signal_id = g_signal_connect_swapped (object, signal,
-                                             G_CALLBACK (run_until_ready_cb),
-                                             &data);
-       if (loop != NULL) {
-               *loop = data.loop;
-       }
-
-       g_main_loop_run (data.loop);
-
-       if (loop != NULL) {
-               *loop = NULL;
-       }
-
-       g_signal_handler_disconnect (object, signal_id);
-       g_main_loop_unref (data.loop);
-}
-
-void
-empathy_run_until_ready (gpointer object)
-{
-       empathy_run_until_ready_full (object, "notify::ready", object_is_ready,
-                                     NULL, NULL);
-}
-
-McAccount *
-empathy_channel_get_account (TpChannel *channel)
-{
-       TpConnection   *connection;
-       McAccount      *account;
-       MissionControl *mc;
-
-       g_object_get (channel, "connection", &connection, NULL);
-       mc = empathy_mission_control_dup_singleton ();
-       account = mission_control_get_account_for_tpconnection (mc, connection, NULL);
-       g_object_unref (connection);
-       g_object_unref (mc);
-
-       return account;
-}
-
 guint
 empathy_proxy_hash (gconstpointer key)
 {
@@ -470,3 +378,4 @@ empathy_check_available_state (void)
 
        return TRUE;
 }
+
index 8684acc0090d38ca3da8bfe1ee3ec56bbb5d4c49..e6bcfebfc68e017145953ee407a3b5d00effd520 100644 (file)
@@ -74,16 +74,6 @@ const gchar * empathy_presence_to_str               (McPresence       presence);
 McPresence    empathy_presence_from_str             (const gchar     *str);
 gchar *       empathy_file_lookup                   (const gchar     *filename,
                                                     const gchar     *subdir);
-
-typedef gboolean (*EmpathyRunUntilReadyFunc)        (GObject         *object,
-                                                    gpointer         user_data);
-void          empathy_run_until_ready               (gpointer         object);
-void          empathy_run_until_ready_full          (gpointer         object,
-                                                    const gchar     *signal,
-                                                    EmpathyRunUntilReadyFunc  func,
-                                                    gpointer         user_data,
-                                                    GMainLoop      **loop);
-McAccount *  empathy_channel_get_account            (TpChannel       *channel);
 gboolean     empathy_proxy_equal                    (gconstpointer    a,
                                                     gconstpointer    b);
 guint        empathy_proxy_hash                     (gconstpointer    key);
index 79eaac4d8c930255cb4a6c44007b0c641a337690..0879e75a5dbad218c1822887d7a5a63382988284 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /* 
  * Copyright (C) 2007 Raphaël Slinckx <raphael@slinckx.net>
- * Copyright (C) 2007 Collabora Ltd.
+ * Copyright (C) 2007-2009 Collabora Ltd.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,7 +34,8 @@
 #include <libmissioncontrol/mission-control.h>
 #include <libmissioncontrol/mc-account.h>
 
-#include <libempathy/empathy-contact-factory.h>
+#include <libempathy/empathy-tp-contact-factory.h>
+#include <libempathy/empathy-account-manager.h>
 #include <libempathy/empathy-contact.h>
 #include <libempathy/empathy-contact-list.h>
 #include <libempathy/empathy-contact-manager.h>
 
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, MegaphoneApplet)
 typedef struct {
-       EmpathyContactFactory *factory;
-       GtkWidget             *image;
-       gint                   image_size;
-       EmpathyContact        *contact;
-       GConfClient           *gconf;
-       guint                  gconf_cnxn;
+       EmpathyTpContactFactory *factory;
+       EmpathyAccountManager   *account_manager;
+       McAccount               *account;
+       gchar                   *id;
+       GtkWidget               *image;
+       gint                     image_size;
+       EmpathyContact          *contact;
+       GConfClient             *gconf;
+       guint                    gconf_cnxn;
 } MegaphoneAppletPriv;
 
-static void megaphone_applet_finalize                  (GObject            *object);
-static void megaphone_applet_size_allocate_cb          (GtkWidget          *widget,
-                                                       GtkAllocation      *allocation,
-                                                       MegaphoneApplet    *applet);
-static gboolean megaphone_applet_button_press_event_cb (GtkWidget          *widget,
-                                                       GdkEventButton     *event, 
-                                                       MegaphoneApplet    *applet);
-static void megaphone_applet_information_cb            (BonoboUIComponent  *uic,
-                                                       MegaphoneApplet    *applet, 
-                                                       const gchar        *verb_name);
-static void megaphone_applet_preferences_cb            (BonoboUIComponent  *uic,
-                                                       MegaphoneApplet    *applet, 
-                                                       const gchar        *verb_name);
-static void megaphone_applet_about_cb                  (BonoboUIComponent  *uic,
-                                                       MegaphoneApplet    *applet, 
-                                                       const gchar        *verb_name);
-
 G_DEFINE_TYPE(MegaphoneApplet, megaphone_applet, PANEL_TYPE_APPLET)
 
-static const BonoboUIVerb megaphone_applet_menu_verbs [] = {
-       BONOBO_UI_UNSAFE_VERB ("information", megaphone_applet_information_cb),
-       BONOBO_UI_UNSAFE_VERB ("preferences", megaphone_applet_preferences_cb),
-       BONOBO_UI_UNSAFE_VERB ("about",       megaphone_applet_about_cb),
-       BONOBO_UI_VERB_END
-};
-
-static const char* authors[] = {
-       "Raphaël Slinckx <raphael@slinckx.net>", 
-       "Xavier Claessens <xclaesse@gmail.com>", 
-       NULL
-};
-
-static void
-megaphone_applet_class_init (MegaphoneAppletClass *class)
-{
-       GObjectClass *object_class;
-
-       object_class = G_OBJECT_CLASS (class);
-
-       object_class->finalize = megaphone_applet_finalize;
-
-       g_type_class_add_private (object_class, sizeof (MegaphoneAppletPriv));
-       empathy_gtk_init ();
-}
-
-static void
-megaphone_applet_init (MegaphoneApplet *applet)
-{
-       MegaphoneAppletPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (applet,
-               MEGAPHONE_TYPE_APPLET, MegaphoneAppletPriv);
-
-       applet->priv = priv;
-       priv->factory = empathy_contact_factory_dup_singleton ();
-       priv->gconf = gconf_client_get_default ();
-
-       /* Image holds the contact avatar */
-       priv->image = gtk_image_new ();
-       gtk_widget_show (priv->image);
-       gtk_container_add (GTK_CONTAINER (applet), priv->image);
-
-       /* We want transparency */
-       panel_applet_set_flags (PANEL_APPLET (applet), PANEL_APPLET_EXPAND_MINOR);
-       panel_applet_set_background_widget (PANEL_APPLET (applet), GTK_WIDGET (applet));
-
-       /* Listen for clicks on the applet to dispatch a channel */
-       g_signal_connect (applet, "button-press-event",
-                         G_CALLBACK (megaphone_applet_button_press_event_cb),
-                         applet);
-
-       /* Allow to resize our avatar when needed */
-       g_signal_connect (applet, "size-allocate",
-                         G_CALLBACK (megaphone_applet_size_allocate_cb),
-                         applet);
-}
-
-static void
-megaphone_applet_finalize (GObject *object)
-{
-       MegaphoneAppletPriv *priv = GET_PRIV (object);
-       
-       if (priv->contact) {
-               g_object_unref (priv->contact);
-       }
-       g_object_unref (priv->factory);
-
-       if (priv->gconf_cnxn != 0) {
-               gconf_client_notify_remove (priv->gconf, priv->gconf_cnxn);
-       }
-       g_object_unref (priv->gconf);
-
-       G_OBJECT_CLASS (megaphone_applet_parent_class)->finalize (object);
-}
-
 static void
 megaphone_applet_update_icon (MegaphoneApplet *applet)
 {
@@ -258,46 +171,42 @@ megaphone_applet_update_contact (MegaphoneApplet *applet)
 }
 
 static void
-megaphone_applet_set_contact (MegaphoneApplet *applet,
-                             const gchar     *str)
+megaphone_applet_got_contact_cb (EmpathyTpContactFactory *factory,
+                                EmpathyContact          *contact,
+                                const GError            *error,
+                                gpointer                 user_data,
+                                GObject                 *applet)
 {
        MegaphoneAppletPriv *priv = GET_PRIV (applet);
-       McAccount           *account = NULL;
-       gchar              **strv = NULL;
-
-       DEBUG ("Setting new contact %s", str);
 
-       /* Release old contact, if any */
-       if (priv->contact) {
-               g_signal_handlers_disconnect_by_func (priv->contact,
-                                                     megaphone_applet_update_contact,
-                                                     applet);
-               g_object_unref (priv->contact),
-               priv->contact = NULL;
+       if (error != NULL) {
+               DEBUG ("Error: %s", error->message);
+               return;
        }
 
-       /* Lookup the new contact */
-       if (str) {
-               strv = g_strsplit (str, "/", 2);
-               account = mc_account_lookup (strv[0]);
-       }
-       if (account) {
-               priv->contact = empathy_contact_factory_get_from_id (priv->factory,
-                                                                    account,
-                                                                    strv[1]);
-               g_object_unref (account);
-       }
-       g_strfreev (strv);
+       priv->contact = g_object_ref (contact);
+       g_signal_connect_swapped (priv->contact, "notify",
+                                 G_CALLBACK (megaphone_applet_update_contact),
+                                 applet);
+       megaphone_applet_update_contact (MEGAPHONE_APPLET (applet));
+}
 
-       /* Take hold of the new contact if any */
-       if (priv->contact) {
-               /* Listen for updates on the contact, and force a first update */
-               g_signal_connect_swapped (priv->contact, "notify",
-                                         G_CALLBACK (megaphone_applet_update_contact),
-                                         applet);
+static void
+megaphone_applet_new_connection_cb (EmpathyAccountManager *manager,
+                                   TpConnection          *connection,
+                                   McAccount             *account,
+                                   MegaphoneApplet       *applet)
+{
+       MegaphoneAppletPriv *priv = GET_PRIV (applet);
+
+       if (priv->contact || !empathy_account_equal (account, priv->account)) {
+               return;
        }
 
-       megaphone_applet_update_contact (applet);
+       priv->factory = empathy_tp_contact_factory_dup_singleton (connection);
+       empathy_tp_contact_factory_get_from_id (priv->factory, priv->id,
+               megaphone_applet_got_contact_cb,
+               NULL, NULL, G_OBJECT (applet));
 }
 
 static void
@@ -312,7 +221,7 @@ megaphone_applet_preferences_response_cb (GtkWidget       *dialog,
                /* Retrieve the selected contact, if any and set it up in gconf.
                 * GConf will notify us from the change and we will adjust ourselves */
                contact_list = g_object_get_data (G_OBJECT (dialog), "contact-list");
-               contact = empathy_contact_list_view_get_selected (contact_list);
+               contact = empathy_contact_list_view_dup_selected (contact_list);
                if (contact) {
                        McAccount   *account;
                        const gchar *account_id;
@@ -331,6 +240,7 @@ megaphone_applet_preferences_response_cb (GtkWidget       *dialog,
                                                       "contact_id", str,
                                                       NULL);
                        g_free (str);
+                       g_object_unref (contact);
                }
        }
        gtk_widget_destroy (dialog);
@@ -384,42 +294,6 @@ megaphone_applet_show_preferences (MegaphoneApplet *applet)
        gtk_widget_show (dialog);
 }
 
-static void
-megaphone_applet_information_cb (BonoboUIComponent *uic,
-                                MegaphoneApplet   *applet,
-                                const gchar       *verb_name)
-{
-       MegaphoneAppletPriv *priv = GET_PRIV (applet);
-
-       /* FIXME: We should grey out the menu item if there are no available contact */
-       if (priv->contact) {
-               empathy_contact_information_dialog_show (priv->contact, NULL, FALSE, FALSE);
-       }
-}
-
-static void
-megaphone_applet_preferences_cb (BonoboUIComponent *uic, 
-                                MegaphoneApplet   *applet, 
-                                const gchar       *verb_name)
-{
-       megaphone_applet_show_preferences (applet);
-}
-
-static void
-megaphone_applet_about_cb (BonoboUIComponent *uic, 
-                          MegaphoneApplet   *applet, 
-                          const gchar       *verb_name)
-{
-       gtk_show_about_dialog (NULL,
-                              "name", "Megaphone", 
-                              "version", PACKAGE_VERSION,
-                              "copyright", "Raphaël Slinckx 2007\nCollabora Ltd 2007",
-                              "comments", _("Talk!"),
-                              "authors", authors,
-                              "logo-icon-name", "stock_people",
-                              NULL);
-}
-
 static gboolean
 megaphone_applet_button_press_event_cb (GtkWidget       *widget,
                                        GdkEventButton  *event, 
@@ -478,6 +352,144 @@ megaphone_applet_size_allocate_cb (GtkWidget       *widget,
        }
 }
 
+static void
+megaphone_applet_finalize (GObject *object)
+{
+       MegaphoneAppletPriv *priv = GET_PRIV (object);
+       
+       if (priv->contact) {
+               g_object_unref (priv->contact);
+       }
+       if (priv->factory) {
+               g_object_unref (priv->factory);
+       }
+       if (priv->account_manager) {
+               g_signal_handlers_disconnect_by_func (priv->account_manager,
+                       megaphone_applet_new_connection_cb, object);
+               g_object_unref (priv->account_manager);
+       }
+
+       if (priv->gconf_cnxn != 0) {
+               gconf_client_notify_remove (priv->gconf, priv->gconf_cnxn);
+       }
+       g_object_unref (priv->gconf);
+       g_free (priv->id);
+
+       G_OBJECT_CLASS (megaphone_applet_parent_class)->finalize (object);
+}
+
+static void
+megaphone_applet_class_init (MegaphoneAppletClass *class)
+{
+       GObjectClass *object_class;
+
+       object_class = G_OBJECT_CLASS (class);
+
+       object_class->finalize = megaphone_applet_finalize;
+
+       g_type_class_add_private (object_class, sizeof (MegaphoneAppletPriv));
+       empathy_gtk_init ();
+}
+
+static void
+megaphone_applet_init (MegaphoneApplet *applet)
+{
+       MegaphoneAppletPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (applet,
+               MEGAPHONE_TYPE_APPLET, MegaphoneAppletPriv);
+
+       applet->priv = priv;
+       priv->gconf = gconf_client_get_default ();
+       priv->account_manager = empathy_account_manager_dup_singleton ();
+       g_signal_connect (priv->account_manager, "new-connection",
+               G_CALLBACK (megaphone_applet_new_connection_cb), applet);
+
+       /* Image holds the contact avatar */
+       priv->image = gtk_image_new ();
+       gtk_widget_show (priv->image);
+       gtk_container_add (GTK_CONTAINER (applet), priv->image);
+
+       /* We want transparency */
+       panel_applet_set_flags (PANEL_APPLET (applet), PANEL_APPLET_EXPAND_MINOR);
+       panel_applet_set_background_widget (PANEL_APPLET (applet), GTK_WIDGET (applet));
+
+       /* Listen for clicks on the applet to dispatch a channel */
+       g_signal_connect (applet, "button-press-event",
+                         G_CALLBACK (megaphone_applet_button_press_event_cb),
+                         applet);
+
+       /* Allow to resize our avatar when needed */
+       g_signal_connect (applet, "size-allocate",
+                         G_CALLBACK (megaphone_applet_size_allocate_cb),
+                         applet);
+}
+
+static void
+megaphone_applet_set_contact (MegaphoneApplet *applet,
+                             const gchar     *str)
+{
+       MegaphoneAppletPriv *priv = GET_PRIV (applet);
+       TpConnection        *connection;
+       gchar              **strv = NULL;
+
+       DEBUG ("Setting new contact %s", str);
+
+       /* Release old contact, if any */
+       if (priv->contact) {
+               g_signal_handlers_disconnect_by_func (priv->contact,
+                                                     megaphone_applet_update_contact,
+                                                     applet);
+               g_object_unref (priv->contact),
+               priv->contact = NULL;
+       }
+       if (priv->account) {
+               g_object_unref (priv->account),
+               priv->account = NULL;
+       }
+       if (priv->factory) {
+               g_object_unref (priv->factory),
+               priv->factory = NULL;
+       }
+
+       /* Lookup the new contact */
+       if (str) {
+               strv = g_strsplit (str, "/", 2);
+               priv->account = mc_account_lookup (strv[0]);
+               priv->id = strv[1];
+               g_free (strv[0]);
+               g_free (strv);
+       }
+
+       if (priv->account) {
+               connection = empathy_account_manager_get_connection (
+                       priv->account_manager, priv->account);
+               if (connection) {
+                       megaphone_applet_new_connection_cb (priv->account_manager,
+                               connection, priv->account, applet);
+               }
+       }
+}
+
+static void
+megaphone_applet_information_cb (BonoboUIComponent *uic,
+                                MegaphoneApplet   *applet,
+                                const gchar       *verb_name)
+{
+       MegaphoneAppletPriv *priv = GET_PRIV (applet);
+
+       /* FIXME: We should grey out the menu item if there are no available contact */
+       if (priv->contact) {
+               empathy_contact_information_dialog_show (priv->contact, NULL);
+       }
+}
+
+static void
+megaphone_applet_preferences_cb (BonoboUIComponent *uic, 
+                                MegaphoneApplet   *applet, 
+                                const gchar       *verb_name)
+{
+       megaphone_applet_show_preferences (applet);
+}
+
 static void
 megaphone_applet_gconf_notify_cb (GConfClient     *client,
                                  guint            cnxn_id,
@@ -497,6 +509,34 @@ megaphone_applet_gconf_notify_cb (GConfClient     *client,
        }
 }
 
+static void
+megaphone_applet_about_cb (BonoboUIComponent *uic, 
+                          MegaphoneApplet   *applet, 
+                          const gchar       *verb_name)
+{
+       const char* authors[] = {
+               "Raphaël Slinckx <raphael@slinckx.net>", 
+               "Xavier Claessens <xclaesse@gmail.com>", 
+               NULL
+       };
+
+       gtk_show_about_dialog (NULL,
+                              "name", "Megaphone", 
+                              "version", PACKAGE_VERSION,
+                              "copyright", "Raphaël Slinckx 2007\nCollabora Ltd 2007",
+                              "comments", _("Talk!"),
+                              "authors", authors,
+                              "logo-icon-name", "stock_people",
+                              NULL);
+}
+
+static const BonoboUIVerb megaphone_applet_menu_verbs [] = {
+       BONOBO_UI_UNSAFE_VERB ("information", megaphone_applet_information_cb),
+       BONOBO_UI_UNSAFE_VERB ("preferences", megaphone_applet_preferences_cb),
+       BONOBO_UI_UNSAFE_VERB ("about",       megaphone_applet_about_cb),
+       BONOBO_UI_VERB_END
+};
+
 static gboolean
 megaphone_applet_factory (PanelApplet *applet, 
                          const gchar *iid, 
index 32c38153c88f7b69a12748426bc040cf3e734c30..c29bb60c77db85e62216432958a7340666198d80 100644 (file)
@@ -37,9 +37,8 @@ libempathy-gtk/empathy-log-window.c
 [type: gettext/glade]libempathy-gtk/empathy-log-window.ui
 [type: gettext/glade]libempathy-gtk/empathy-new-message-dialog.ui
 libempathy-gtk/empathy-presence-chooser.c
-[type: gettext/glade]libempathy-gtk/empathy-presence-chooser.ui
-libempathy-gtk/empathy-spell-dialog.c
-[type: gettext/glade]libempathy-gtk/empathy-spell-dialog.ui
+libempathy-gtk/empathy-status-preset-dialog.c
+[type: gettext/glade]libempathy-gtk/empathy-status-preset-dialog.ui
 libempathy-gtk/empathy-theme-boxes.c
 libempathy-gtk/empathy-theme-irc.c
 libempathy-gtk/empathy-theme-manager.c
index 15eb63c3b08a9656e3955bbcac7619e743b833b8..7e5b0c26df6178b18462e3afaaa7449185357d12 100644 (file)
--- a/po/es.po
+++ b/po/es.po
@@ -8,8 +8,8 @@ msgstr ""
 "Project-Id-Version: empathy.HEAD\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
 "product=empathy&component=general\n"
-"POT-Creation-Date: 2009-04-17 20:26+0000\n"
-"PO-Revision-Date: 2009-04-18 20:33+0200\n"
+"POT-Creation-Date: 2009-04-21 15:44+0000\n"
+"PO-Revision-Date: 2009-04-21 21:02+0200\n"
 "Last-Translator: Jorge González <jorgegonz@svn.gnome.org>\n"
 "Language-Team: Español <gnome-es-list@gnome.org>\n"
 "MIME-Version: 1.0\n"
@@ -355,7 +355,7 @@ msgstr ""
 "predeterminado es ordenar por el nombre del contacto con el valor \"name"
 "\" (nombre). Un valor \"state\" (estado) ordenará la lista por el estado."
 
-#: ../libempathy/empathy-tp-contact-list.c:731 ../src/empathy.c:271
+#: ../libempathy/empathy-tp-contact-list.c:732 ../src/empathy.c:271
 msgid "People nearby"
 msgstr "Gente cerca"
 
@@ -571,7 +571,7 @@ msgid "_Room List locale:"
 msgstr "Configuración de la lista de _salas:"
 
 #: ../libempathy-gtk/empathy-avatar-chooser.c:462
-#: ../libempathy-gtk/empathy-avatar-chooser.c:537
+#: ../libempathy-gtk/empathy-avatar-chooser.c:538
 msgid "Couldn't convert image"
 msgstr "No se pudo convertir la imagen"
 
@@ -579,19 +579,19 @@ msgstr "No se pudo convertir la imagen"
 msgid "None of the accepted image formats is supported on your system"
 msgstr "Su sistema no soporta ninguno de los formatos de imagen aceptados"
 
-#: ../libempathy-gtk/empathy-avatar-chooser.c:954
+#: ../libempathy-gtk/empathy-avatar-chooser.c:957
 msgid "Select Your Avatar Image"
 msgstr "Seleccione su imagen de avatar"
 
-#: ../libempathy-gtk/empathy-avatar-chooser.c:957
+#: ../libempathy-gtk/empathy-avatar-chooser.c:960
 msgid "No Image"
 msgstr "Sin imagen"
 
-#: ../libempathy-gtk/empathy-avatar-chooser.c:1019
+#: ../libempathy-gtk/empathy-avatar-chooser.c:1022
 msgid "Images"
 msgstr "Imágenes"
 
-#: ../libempathy-gtk/empathy-avatar-chooser.c:1023
+#: ../libempathy-gtk/empathy-avatar-chooser.c:1026
 msgid "All Files"
 msgstr "Todos los archivos"
 
@@ -761,7 +761,8 @@ msgid "_Chat"
 msgstr "_Chat"
 
 #: ../libempathy-gtk/empathy-contact-menu.c:161
-#: ../src/empathy-call-window.ui.h:5
+#| msgid "_Call"
+msgctxt "menu item"
 msgid "_Call"
 msgstr "_Llamar"
 
@@ -787,7 +788,7 @@ msgstr "_Editar"
 msgid "Inviting to this room"
 msgstr "Invitando a esta sala"
 
-#: ../libempathy-gtk/empathy-contact-menu.c:369
+#: ../libempathy-gtk/empathy-contact-menu.c:367
 msgid "_Invite to chatroom"
 msgstr "_Invitar a la sala"
 
@@ -795,19 +796,19 @@ msgstr "_Invitar a la sala"
 msgid "Select a contact"
 msgstr "Seleccionar un contacto"
 
-#: ../libempathy-gtk/empathy-contact-widget.c:354
+#: ../libempathy-gtk/empathy-contact-widget.c:353
 msgid "Save Avatar"
 msgstr "Guardar avatar"
 
-#: ../libempathy-gtk/empathy-contact-widget.c:410
+#: ../libempathy-gtk/empathy-contact-widget.c:409
 msgid "Unable to save avatar"
 msgstr "No se pudo guardar el avatar"
 
-#: ../libempathy-gtk/empathy-contact-widget.c:905
+#: ../libempathy-gtk/empathy-contact-widget.c:904
 msgid "Select"
 msgstr "Seleccionar"
 
-#: ../libempathy-gtk/empathy-contact-widget.c:914
+#: ../libempathy-gtk/empathy-contact-widget.c:913
 #: ../src/empathy-main-window.c:882
 msgid "Group"
 msgstr "Grupo"
@@ -959,16 +960,24 @@ msgstr "Mensaje personalizado…"
 msgid "Edit Custom Messages..."
 msgstr "Editar mensajes personalizados…"
 
-#: ../libempathy-gtk/empathy-presence-chooser.c:269
+#: ../libempathy-gtk/empathy-presence-chooser.c:316
+msgid "Click to remove this status as a favorite"
+msgstr "Pulse pare eliminar este estado de los favoritos"
+
+#: ../libempathy-gtk/empathy-presence-chooser.c:325
+msgid "Click to make this status a favorite"
+msgstr "Pulse para hacer este estado uno favorito"
+
+#: ../libempathy-gtk/empathy-presence-chooser.c:359
 msgid "Set status"
 msgstr "Establecer estado"
 
-#: ../libempathy-gtk/empathy-presence-chooser.c:653
+#: ../libempathy-gtk/empathy-presence-chooser.c:766
 msgid "Set your presence and current status"
 msgstr "Establecer su presencia y estado actual"
 
 #. Custom messages
-#: ../libempathy-gtk/empathy-presence-chooser.c:873
+#: ../libempathy-gtk/empathy-presence-chooser.c:987
 msgid "Custom messages..."
 msgstr "Mensajes personalizados…"
 
@@ -1419,6 +1428,11 @@ msgstr ""
 msgid "Type:"
 msgstr "Tipo:"
 
+#: ../src/empathy-accounts-dialog.ui.h:10
+#| msgid "_Add Contact..."
+msgid "_Add..."
+msgstr "_Añadir…"
+
 #: ../src/empathy-call-window.c:319
 msgid "Contrast"
 msgstr "Contraste"
@@ -1477,6 +1491,10 @@ msgstr "Enviar vídeo"
 msgid "Video preview"
 msgstr "Vista preliminar de vídeo"
 
+#: ../src/empathy-call-window.ui.h:5
+msgid "_Call"
+msgstr "_Llamar"
+
 #: ../src/empathy-call-window.ui.h:6
 msgid "_View"
 msgstr "_Ver"
@@ -1658,7 +1676,6 @@ msgid "%s of %s"
 msgstr "%s de %s"
 
 #: ../src/empathy-ft-manager.c:254
-#| msgid "Waiting the other participant's response"
 msgid "Waiting for the other participant's response"
 msgstr "Esperando la respuesta del otro participante"
 
@@ -1840,7 +1857,7 @@ msgstr "Error desconocido"
 msgid "Contact"
 msgstr "Contacto"
 
-#: ../src/empathy-main-window.c:1202
+#: ../src/empathy-main-window.c:1205
 msgid "Show and edit accounts"
 msgstr "Mostrar y editar cuentas"
 
@@ -1881,7 +1898,6 @@ msgid "_Help"
 msgstr "Ay_uda"
 
 #: ../src/empathy-main-window.ui.h:12
-#| msgid "_Join"
 msgid "_Join..."
 msgstr "_Unirse…"
 
@@ -1898,12 +1914,10 @@ msgid "_Room"
 msgstr "_Sala"
 
 #: ../src/empathy-new-chatroom-dialog.c:313
-#| msgid "Chat Rooms"
 msgid "Chat Room"
 msgstr "Sala de chat"
 
 #: ../src/empathy-new-chatroom-dialog.c:328
-#| msgid "Themes"
 msgid "Members"
 msgstr "Miembros"
 
@@ -1949,12 +1963,10 @@ msgstr ""
 "la cuenta del servidor actual"
 
 #: ../src/empathy-new-chatroom-dialog.ui.h:4
-#| msgid "Room"
 msgid "Join Room"
 msgstr "Unirse a sala"
 
 #: ../src/empathy-new-chatroom-dialog.ui.h:5
-#| msgid "_Room List locale:"
 msgid "Room List"
 msgstr "Lista de salas"
 
@@ -1990,7 +2002,7 @@ msgstr "Cuenta conectada"
 msgid "Account disconnected"
 msgstr "Cuenta desconectada"
 
-#: ../src/empathy-preferences.c:396
+#: ../src/empathy-preferences.c:397
 msgid "Language"
 msgstr "Idioma"
 
@@ -2116,12 +2128,12 @@ msgstr "_Salir"
 msgid "_Show Contact List"
 msgstr "_Mostrar lista de contactos"
 
-#: ../src/empathy-tube-dispatch.c:364
+#: ../src/empathy-tube-dispatch.c:375
 #, c-format
 msgid "Unable to start application for service %s: %s"
 msgstr "No se pudo iniciar la aplicación para el servicio %s: %s"
 
-#: ../src/empathy-tube-dispatch.c:435
+#: ../src/empathy-tube-dispatch.c:446
 #, c-format
 msgid ""
 "An invitation was offered for service %s, but you don't have the needed "
index 66a269784741b1dcddca24bf58af077f8dfb92df..3e9fd624c146d10ec31ef0f7d8d4871aa2fc6394 100644 (file)
   (gtype-id "EMPATHY_TYPE_CONTACT")
 )
 
-(define-object ContactFactory
-  (in-module "Empathy")
-  (parent "GObject")
-  (c-name "EmpathyContactFactory")
-  (gtype-id "EMPATHY_TYPE_CONTACT_FACTORY")
-)
-
 (define-interface ContactList
   (in-module "Empathy")
   (c-name "EmpathyContactList")
   (gtype-id "EMPATHY_TYPE_TP_FILE")
 )
 
-(define-object TpGroup
-  (in-module "Empathy")
-  (parent "GObject")
-  (c-name "EmpathyTpGroup")
-  (gtype-id "EMPATHY_TYPE_TP_GROUP")
-)
-
 (define-object TpRoomlist
   (in-module "Empathy")
   (parent "GObject")
   )
 )
 
-(define-flags ContactReady
-  (in-module "Empathy")
-  (c-name "EmpathyContactReady")
-  (gtype-id "EMPATHY_TYPE_CONTACT_READY")
-  (values
-    '("none" "EMPATHY_CONTACT_READY_NONE")
-    '("id" "EMPATHY_CONTACT_READY_ID")
-    '("handle" "EMPATHY_CONTACT_READY_HANDLE")
-    '("name" "EMPATHY_CONTACT_READY_NAME")
-    '("all" "EMPATHY_CONTACT_READY_ALL")
-  )
-)
-
 (define-flags DebugFlags
   (in-module "Empathy")
   (c-name "EmpathyDebugFlags")
   (return-type "int")
 )
 
+(define-method get_account
+  (of-object "EmpathyAccountManager")
+  (c-name "empathy_account_manager_get_account")
+  (return-type "McAccount*")
+  (parameters
+    '("TpConnection*" "connection")
+  )
+)
+
+(define-method dup_accounts
+  (of-object "EmpathyAccountManager")
+  (c-name "empathy_account_manager_dup_accounts")
+  (return-type "GList*")
+)
+
+(define-method get_connection
+  (of-object "EmpathyAccountManager")
+  (c-name "empathy_account_manager_get_connection")
+  (return-type "TpConnection*")
+  (parameters
+    '("McAccount*" "account")
+  )
+)
+
+(define-method dup_connections
+  (of-object "EmpathyAccountManager")
+  (c-name "empathy_account_manager_dup_connections")
+  (return-type "GList*")
+)
+
 
 
 ;; From empathy-chatroom.h
   )
 )
 
+(define-method get_subject
+  (of-object "EmpathyChatroom")
+  (c-name "empathy_chatroom_get_subject")
+  (return-type "const-gchar*")
+)
+
+(define-method set_subject
+  (of-object "EmpathyChatroom")
+  (c-name "empathy_chatroom_set_subject")
+  (return-type "none")
+  (parameters
+    '("const-gchar*" "subject")
+  )
+)
+
+(define-method get_members_count
+  (of-object "EmpathyChatroom")
+  (c-name "empathy_chatroom_get_members_count")
+  (return-type "guint")
+)
+
+(define-method set_members_count
+  (of-object "EmpathyChatroom")
+  (c-name "empathy_chatroom_set_members_count")
+  (return-type "none")
+  (parameters
+    '("guint" "count")
+  )
+)
+
+(define-method get_need_password
+  (of-object "EmpathyChatroom")
+  (c-name "empathy_chatroom_get_need_password")
+  (return-type "gboolean")
+)
+
+(define-method set_need_password
+  (of-object "EmpathyChatroom")
+  (c-name "empathy_chatroom_set_need_password")
+  (return-type "none")
+  (parameters
+    '("gboolean" "need_password")
+  )
+)
+
+(define-method get_invite_only
+  (of-object "EmpathyChatroom")
+  (c-name "empathy_chatroom_get_invite_only")
+  (return-type "gboolean")
+)
+
+(define-method set_invite_only
+  (of-object "EmpathyChatroom")
+  (c-name "empathy_chatroom_set_invite_only")
+  (return-type "none")
+  (parameters
+    '("gboolean" "invite_only")
+  )
+)
+
 (define-function chatroom_equal
   (c-name "empathy_chatroom_equal")
   (return-type "gboolean")
   (is-constructor-of "EmpathyContact")
   (return-type "EmpathyContact*")
   (parameters
-    '("McAccount*" "account")
+    '("TpContact*" "tp_contact")
   )
 )
 
-(define-function contact_new_full
-  (c-name "empathy_contact_new_full")
-  (return-type "EmpathyContact*")
-  (parameters
-    '("McAccount*" "account")
-    '("const-gchar*" "id")
-    '("const-gchar*" "name")
-  )
+(define-method get_tp_contact
+  (of-object "EmpathyContact")
+  (c-name "empathy_contact_get_tp_contact")
+  (return-type "TpContact*")
 )
 
 (define-method get_id
   (return-type "McAccount*")
 )
 
-(define-method set_account
+(define-method get_connection
   (of-object "EmpathyContact")
-  (c-name "empathy_contact_set_account")
-  (return-type "none")
-  (parameters
-    '("McAccount*" "account")
-  )
+  (c-name "empathy_contact_get_connection")
+  (return-type "TpConnection*")
 )
 
 (define-method get_presence
   )
 )
 
-(define-method get_ready
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_get_ready")
-  (return-type "EmpathyContactReady")
-)
-
 (define-method is_user
   (of-object "EmpathyContact")
   (c-name "empathy_contact_is_user")
   (return-type "gboolean")
 )
 
-(define-function contact_equal
-  (c-name "empathy_contact_equal")
-  (return-type "gboolean")
-  (parameters
-    '("gconstpointer" "v1")
-    '("gconstpointer" "v2")
-  )
-)
-
 (define-function contact_hash
   (c-name "empathy_contact_hash")
   (return-type "guint")
   )
 )
 
-(define-method call_when_ready
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_call_when_ready")
-  (return-type "none")
-  (parameters
-    '("EmpathyContactReady" "ready")
-    '("EmpathyContactReadyCb*" "callback")
-    '("gpointer" "user_data")
-    '("GDestroyNotify" "destroy")
-    '("GObject*" "weak_object")
-  )
-)
-
-(define-method run_until_ready
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_run_until_ready")
-  (return-type "none")
-  (parameters
-    '("EmpathyContactReady" "ready")
-    '("GMainLoop**" "loop")
-  )
-)
-
 (define-method load_avatar_data
   (of-object "EmpathyContact")
   (c-name "empathy_contact_load_avatar_data")
 
 
 
-;; From empathy-contact-factory.h
-
-(define-function contact_factory_get_type
-  (c-name "empathy_contact_factory_get_type")
-  (return-type "GType")
-)
-
-(define-function contact_factory_dup_singleton
-  (c-name "empathy_contact_factory_dup_singleton")
-  (return-type "EmpathyContactFactory*")
-)
-
-(define-method get_tp_factory
-  (of-object "EmpathyContactFactory")
-  (c-name "empathy_contact_factory_get_tp_factory")
-  (return-type "EmpathyTpContactFactory*")
-  (parameters
-    '("McAccount*" "account")
-  )
-)
-
-(define-method get_user
-  (of-object "EmpathyContactFactory")
-  (c-name "empathy_contact_factory_get_user")
-  (return-type "EmpathyContact*")
-  (parameters
-    '("McAccount*" "account")
-  )
-)
-
-(define-method get_from_id
-  (of-object "EmpathyContactFactory")
-  (c-name "empathy_contact_factory_get_from_id")
-  (return-type "EmpathyContact*")
-  (parameters
-    '("McAccount*" "account")
-    '("const-gchar*" "id")
-  )
-)
-
-(define-method get_from_handle
-  (of-object "EmpathyContactFactory")
-  (c-name "empathy_contact_factory_get_from_handle")
-  (return-type "EmpathyContact*")
-  (parameters
-    '("McAccount*" "account")
-    '("guint" "handle")
-  )
-)
-
-(define-method get_from_handles
-  (of-object "EmpathyContactFactory")
-  (c-name "empathy_contact_factory_get_from_handles")
-  (return-type "GList*")
-  (parameters
-    '("McAccount*" "account")
-    '("const-GArray*" "handles")
-  )
-)
-
-(define-method set_alias
-  (of-object "EmpathyContactFactory")
-  (c-name "empathy_contact_factory_set_alias")
-  (return-type "none")
-  (parameters
-    '("EmpathyContact*" "contact")
-    '("const-gchar*" "alias")
-  )
-)
-
-(define-method set_avatar
-  (of-object "EmpathyContactFactory")
-  (c-name "empathy_contact_factory_set_avatar")
-  (return-type "none")
-  (parameters
-    '("McAccount*" "account")
-    '("const-gchar*" "data")
-    '("gsize" "size")
-    '("const-gchar*" "mime_type")
-  )
-)
-
-
-
 ;; From empathy-contact-groups.h
 
 (define-function contact_groups_get_all
   (c-name "empathy_contact_manager_get_list")
   (return-type "EmpathyTpContactList*")
   (parameters
-    '("McAccount*" "account")
+    '("TpConnection*" "connection")
   )
 )
 
   (c-name "empathy_contact_manager_can_add")
   (return-type "gboolean")
   (parameters
-    '("McAccount*" "account")
+    '("TpConnection*" "connection")
   )
 )
 
   (c-name "empathy_dispatcher_create_channel")
   (return-type "none")
   (parameters
-    '("McAccount*" "account")
+    '("TpConnection*" "connection")
     '("GHashTable*" "request")
     '("EmpathyDispatcherRequestCb*" "callback")
     '("gpointer" "user_data")
   )
 )
 
-(define-function dispatcher_call_with_contact
-  (c-name "empathy_dispatcher_call_with_contact")
-  (return-type "none")
-  (parameters
-    '("EmpathyContact*" "contact")
-    '("EmpathyDispatcherRequestCb*" "callback")
-    '("gpointer" "user_data")
-  )
-)
-
 (define-function dispatcher_chat_with_contact_id
   (c-name "empathy_dispatcher_chat_with_contact_id")
   (return-type "none")
   (parameters
-    '("McAccount*" "account")
+    '("TpConnection*" "connection")
     '("const-gchar*" "contact_id")
     '("EmpathyDispatcherRequestCb*" "callback")
     '("gpointer" "user_data")
   (c-name "empathy_dispatcher_join_muc")
   (return-type "none")
   (parameters
-    '("McAccount*" "account")
+    '("TpConnection*" "connection")
     '("const-gchar*" "roomname")
     '("EmpathyDispatcherRequestCb*" "callback")
     '("gpointer" "user_data")
   (c-name "empathy_dispatcher_find_channel_class")
   (return-type "GStrv")
   (parameters
-    '("McAccount*" "account")
+    '("TpConnection*" "connection")
     '("const-gchar*" "channel_type")
     '("guint" "handle_type")
   )
   (return-type "EmpathyContact*")
 )
 
-(define-method get_account
-  (of-object "EmpathyTpChat")
-  (c-name "empathy_tp_chat_get_account")
-  (return-type "McAccount*")
-)
-
 (define-method get_channel
   (of-object "EmpathyTpChat")
   (c-name "empathy_tp_chat_get_channel")
   (return-type "TpChannel*")
 )
 
-(define-method is_ready
+(define-method get_connection
   (of-object "EmpathyTpChat")
-  (c-name "empathy_tp_chat_is_ready")
-  (return-type "gboolean")
+  (c-name "empathy_tp_chat_get_connection")
+  (return-type "TpConnection*")
 )
 
-(define-method get_members_count
+(define-method is_ready
   (of-object "EmpathyTpChat")
-  (c-name "empathy_tp_chat_get_members_count")
-  (return-type "guint")
+  (c-name "empathy_tp_chat_is_ready")
+  (return-type "gboolean")
 )
 
 (define-method send
   (return-type "GType")
 )
 
-(define-function tp_contact_factory_new
-  (c-name "empathy_tp_contact_factory_new")
-  (is-constructor-of "EmpathyTpContactFactory")
+(define-function tp_contact_factory_dup_singleton
+  (c-name "empathy_tp_contact_factory_dup_singleton")
   (return-type "EmpathyTpContactFactory*")
   (parameters
-    '("McAccount*" "account")
-  )
-)
-
-(define-method get_user
-  (of-object "EmpathyTpContactFactory")
-  (c-name "empathy_tp_contact_factory_get_user")
-  (return-type "EmpathyContact*")
-)
-
-(define-method get_from_id
-  (of-object "EmpathyTpContactFactory")
-  (c-name "empathy_tp_contact_factory_get_from_id")
-  (return-type "EmpathyContact*")
-  (parameters
-    '("const-gchar*" "id")
+    '("TpConnection*" "connection")
   )
 )
 
-(define-method get_from_handle
+(define-method get_from_ids
   (of-object "EmpathyTpContactFactory")
-  (c-name "empathy_tp_contact_factory_get_from_handle")
-  (return-type "EmpathyContact*")
+  (c-name "empathy_tp_contact_factory_get_from_ids")
+  (return-type "none")
   (parameters
-    '("guint" "handle")
+    '("guint" "n_ids")
+    '("const-gchar*-const*" "ids")
+    '("EmpathyTpContactFactoryGotContactsCb" "callback")
+    '("gpointer" "user_data")
+    '("GDestroyNotify" "destroy")
+    '("GObject*" "weak_object")
   )
 )
 
 (define-method get_from_handles
   (of-object "EmpathyTpContactFactory")
   (c-name "empathy_tp_contact_factory_get_from_handles")
-  (return-type "GList*")
+  (return-type "none")
   (parameters
-    '("const-GArray*" "handles")
+    '("guint" "n_handles")
+    '("const-TpHandle*" "handles")
+    '("EmpathyTpContactFactoryGotContactsCb" "callback")
+    '("gpointer" "user_data")
+    '("GDestroyNotify" "destroy")
+    '("GObject*" "weak_object")
   )
 )
 
   )
 )
 
-(define-method is_ready
-  (of-object "EmpathyTpContactFactory")
-  (c-name "empathy_tp_contact_factory_is_ready")
-  (return-type "gboolean")
-)
-
 
 
 ;; From empathy-tp-contact-list.h
   (is-constructor-of "EmpathyTpContactList")
   (return-type "EmpathyTpContactList*")
   (parameters
-    '("McAccount*" "account")
+    '("TpConnection*" "connection")
   )
 )
 
-(define-method get_account
+(define-method get_connection
   (of-object "EmpathyTpContactList")
-  (c-name "empathy_tp_contact_list_get_account")
-  (return-type "McAccount*")
+  (c-name "empathy_tp_contact_list_get_connection")
+  (return-type "TpConnection*")
 )
 
 (define-method can_add
   (return-type "gboolean")
 )
 
+(define-method remove_all
+  (of-object "EmpathyTpContactList")
+  (c-name "empathy_tp_contact_list_remove_all")
+  (return-type "none")
+)
+
 
 
 ;; From empathy-tp-file.h
   (return-type "const-gchar*")
 )
 
-
-
-;; From empathy-tp-group.h
-
-(define-function tp_group_get_type
-  (c-name "empathy_tp_group_get_type")
-  (return-type "GType")
-)
-
-(define-function tp_group_new
-  (c-name "empathy_tp_group_new")
-  (is-constructor-of "EmpathyTpGroup")
-  (return-type "EmpathyTpGroup*")
-  (parameters
-    '("TpChannel*" "channel")
-  )
-)
-
-(define-method close
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_close")
-  (return-type "none")
-)
-
-(define-method add_members
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_add_members")
-  (return-type "none")
-  (parameters
-    '("GList*" "contacts")
-    '("const-gchar*" "message")
-  )
-)
-
-(define-method add_member
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_add_member")
-  (return-type "none")
-  (parameters
-    '("EmpathyContact*" "contact")
-    '("const-gchar*" "message")
-  )
-)
-
-(define-method remove_members
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_remove_members")
-  (return-type "none")
-  (parameters
-    '("GList*" "contacts")
-    '("const-gchar*" "message")
-  )
-)
-
-(define-method remove_member
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_remove_member")
-  (return-type "none")
-  (parameters
-    '("EmpathyContact*" "contact")
-    '("const-gchar*" "message")
-  )
-)
-
-(define-method get_members
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_get_members")
-  (return-type "GList*")
-)
-
-(define-method get_local_pendings
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_get_local_pendings")
-  (return-type "GList*")
-)
-
-(define-method get_remote_pendings
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_get_remote_pendings")
-  (return-type "GList*")
-)
-
-(define-method get_name
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_get_name")
-  (return-type "const-gchar*")
-)
-
-(define-method get_self_contact
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_get_self_contact")
-  (return-type "EmpathyContact*")
-)
-
-(define-method is_member
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_is_member")
-  (return-type "gboolean")
-  (parameters
-    '("EmpathyContact*" "contact")
-  )
-)
-
 (define-method is_ready
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_is_ready")
+  (of-object "EmpathyTpFile")
+  (c-name "empathy_tp_file_is_ready")
   (return-type "gboolean")
 )
 
-(define-method get_invitation
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_get_invitation")
-  (return-type "EmpathyPendingInfo*")
-  (parameters
-    '("EmpathyContact**" "remote_contact")
-  )
-)
-
-(define-function pending_info_new
-  (c-name "empathy_pending_info_new")
-  (is-constructor-of "EmpathyPendingInfo")
-  (return-type "EmpathyPendingInfo*")
-  (parameters
-    '("EmpathyContact*" "member")
-    '("EmpathyContact*" "actor")
-    '("const-gchar*" "message")
-  )
-)
-
-(define-method free
-  (of-object "EmpathyPendingInfo")
-  (c-name "empathy_pending_info_free")
-  (return-type "none")
-)
-
-(define-method get_flags
-  (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_get_flags")
-  (return-type "TpChannelGroupFlags")
-)
-
 
 
 ;; From empathy-tp-roomlist.h
   )
 )
 
-(define-function run_until_ready
-  (c-name "empathy_run_until_ready")
-  (return-type "none")
-  (parameters
-    '("gpointer" "object")
-  )
-)
-
-(define-function run_until_ready_full
-  (c-name "empathy_run_until_ready_full")
-  (return-type "none")
-  (parameters
-    '("gpointer" "object")
-    '("const-gchar*" "signal")
-    '("EmpathyRunUntilReadyFunc" "func")
-    '("gpointer" "user_data")
-    '("GMainLoop**" "loop")
-  )
-)
-
-(define-function channel_get_account
-  (c-name "empathy_channel_get_account")
-  (return-type "McAccount*")
-  (parameters
-    '("TpChannel*" "channel")
-  )
-)
-
 (define-function proxy_equal
   (c-name "empathy_proxy_equal")
   (return-type "gboolean")
index 72d7ccb0ee8a3da32bfdf252a18823a5b6ae1794..e4c99086c994ccb019b37348f18a93effcfeab66 100644 (file)
@@ -7,7 +7,6 @@ headers
 #include "empathy-chatroom.h"
 #include "empathy-chatroom-manager.h"
 #include "empathy-contact.h"
-#include "empathy-contact-factory.h"
 #include "empathy-contact-groups.h"
 #include "empathy-contact-list.h"
 #include "empathy-contact-manager.h"
@@ -29,7 +28,6 @@ headers
 #include "empathy-tp-contact-factory.h"
 #include "empathy-tp-contact-list.h"
 #include "empathy-tp-file.h"
-#include "empathy-tp-group.h"
 #include "empathy-tp-roomlist.h"
 #include "empathy-tp-tube.h"
 #include "empathy-tube-handler.h"
@@ -66,25 +64,3 @@ _wrap_empathy_contact_list_get_members(PyGObject *self, PyObject *args, PyObject
 
 }
 %%
-override empathy_dispatcher_chat_with_contact_id kwargs
-static PyObject *
-_wrap_empathy_dispatcher_chat_with_contact_id(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    static char *kwlist[] = { "account_id", "contact_id", NULL };
-    char *account_id, *contact_id;
-    McAccount *account;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"ss:dispatcher_chat_with_contact_id", kwlist, &account_id, &contact_id))
-        return NULL;
-
-    account = mc_account_lookup (account_id);
-    if (account) {
-        empathy_dispatcher_chat_with_contact_id(account, contact_id,
-          NULL, NULL);
-        g_object_unref (account);
-    }
-    
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-%%
index 1cb19f52744799441f1a515bbfd29bd1814aa3a9..df829a0313eaaf5391a9caa64908c0f32a113da0 100644 (file)
   (return-type "McAccount*")
 )
 
+(define-method get_connection
+  (of-object "EmpathyAccountChooser")
+  (c-name "empathy_account_chooser_get_connection")
+  (return-type "TpConnection*")
+)
+
 (define-method set_account
   (of-object "EmpathyAccountChooser")
   (c-name "empathy_account_chooser_set_account")
   (return-type "EmpathyContact*")
 )
 
-(define-method get_members_count
-  (of-object "EmpathyChat")
-  (c-name "empathy_chat_get_members_count")
-  (return-type "guint")
-)
-
 (define-method get_contact_menu
   (of-object "EmpathyChat")
   (c-name "empathy_chat_get_contact_menu")
   (return-type "none")
   (parameters
     '("GtkWindow*" "parent")
-    '("gboolean" "edit")
-    '("gboolean" "is_user")
+  )
+)
+
+(define-method edit_dialog_show
+  (of-object "EmpathyContact")
+  (c-name "empathy_contact_edit_dialog_show")
+  (return-type "none")
+  (parameters
+    '("GtkWindow*" "parent")
+  )
+)
+
+(define-function contact_personal_dialog_show
+  (c-name "empathy_contact_personal_dialog_show")
+  (return-type "none")
+  (parameters
+    '("GtkWindow*" "parent")
   )
 )
 
 
 
 
-;; From empathy-spell-dialog.h
-
-(define-function spell_dialog_show
-  (c-name "empathy_spell_dialog_show")
-  (return-type "none")
-  (parameters
-    '("EmpathyChat*" "chat")
-    '("GtkTextIter*" "start")
-    '("GtkTextIter*" "end")
-    '("const-gchar*" "word")
-  )
-)
-
-
-
 ;; From empathy-theme-boxes.h
 
 (define-function theme_boxes_get_type
index 1480cef66c8a197cd5e6303b23d8bfb52e67f56f..3af554ec40f11ee72b4aa969691fc1b13b071f35 100644 (file)
@@ -29,7 +29,6 @@ headers
 #include "empathy-presence-chooser.h"
 #include "empathy-profile-chooser.h"
 #include "empathy-smiley-manager.h"
-#include "empathy-spell-dialog.h"
 #include "empathy-spell.h"
 #include "empathy-theme-boxes.h"
 #include "empathy-theme-irc.h"
@@ -76,6 +75,5 @@ ignore
        empathy_chat_correct_word
        empathy_chat_view_set_margin
        empathy_chat_get_view
-       empathy_spell_dialog_show
        empathy_window_iconify
 %%
index 19c8f10b0b5487f9d29faa07140aee940cb6354f..14a5ddec335882558101e022892b99267a4532be 100755 (executable)
@@ -11,7 +11,6 @@ python /usr/share/pygobject/2.0/codegen/h2def.py      \
        empathy-call-factory.h                  \
        empathy-call-handler.h                  \
        empathy-contact.h                       \
-       empathy-contact-factory.h               \
        empathy-contact-groups.h                \
        empathy-contact-list.h                  \
        empathy-contact-manager.h               \
@@ -34,7 +33,6 @@ python /usr/share/pygobject/2.0/codegen/h2def.py      \
        empathy-tp-contact-factory.h            \
        empathy-tp-contact-list.h               \
        empathy-tp-file.h                       \
-       empathy-tp-group.h                      \
        empathy-tp-roomlist.h                   \
        empathy-tp-tube.h                       \
        empathy-tube-handler.h                  \
@@ -78,7 +76,6 @@ python /usr/share/pygobject/2.0/codegen/h2def.py      \
        empathy-profile-chooser.h               \
        empathy-smiley-manager.h                \
        empathy-spell.h                         \
-       empathy-spell-dialog.h                  \
        empathy-theme-boxes.h                   \
        empathy-theme-irc.h                     \
        empathy-theme-manager.h                 \
index 036c7f86b16e495d5a7fabdf5dd89619d2e4dcbc..e15c0eab1f070809d9d7372f84514fe0a7803d3f 100644 (file)
@@ -819,13 +819,14 @@ accounts_dialog_button_create_clicked_cb (GtkWidget             *button,
        gchar     *str;
        McProfileCapabilityFlags cap;
 
-       profile = empathy_profile_chooser_get_selected (dialog->combobox_profile);
+       profile = empathy_profile_chooser_dup_selected (dialog->combobox_profile);
 
        /* Create account */
        account = mc_account_create (profile);
        if (account == NULL) {
                /* We can't display an error to the user as MC doesn't give us
                 * any clue about the reason of the failure... */
+               g_object_unref (profile);
                return;
        }
 
@@ -869,7 +870,7 @@ accounts_dialog_profile_changed_cb (GtkWidget             *widget,
        McProfile *profile;
        McProfileCapabilityFlags cap;
 
-       profile = empathy_profile_chooser_get_selected (dialog->combobox_profile);
+       profile = empathy_profile_chooser_dup_selected (dialog->combobox_profile);
        cap = mc_profile_get_capabilities (profile);
 
        if (cap & MC_PROFILE_CAPABILITY_REGISTRATION_UI) {
index d7d79df90ff40da5861538d015b169e0cf9bbb00..49ad14142278ea78f6a3f2f5314475944992a61e 100644 (file)
@@ -107,6 +107,7 @@ struct _EmpathyCallWindowPriv
 
   GMutex *lock;
   gboolean call_started;
+  gboolean sending_video;
 };
 
 #define GET_PRIV(o) \
@@ -757,6 +758,7 @@ empathy_call_window_disconnected (EmpathyCallWindow *self)
 
   gtk_widget_set_sensitive (priv->camera_button, FALSE);
   gtk_action_set_sensitive (priv->send_video, FALSE);
+  priv->sending_video = FALSE;
 }
 
 
@@ -1157,20 +1159,35 @@ static void
 empathy_call_window_camera_toggled_cb (GtkToggleToolButton *toggle,
   EmpathyCallWindow *window)
 {
+  EmpathyCallWindowPriv *priv = GET_PRIV (window);
   gboolean active;
 
   active = (gtk_toggle_tool_button_get_active (toggle));
+
+  if (priv->sending_video == active)
+    return;
+  priv->sending_video = active;
+
   empathy_call_window_set_send_video (window, active);
+  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->send_video), active);
 }
 
 static void
 empathy_call_window_send_video_toggled_cb (GtkToggleAction *toggle,
   EmpathyCallWindow *window)
 {
+  EmpathyCallWindowPriv *priv = GET_PRIV (window);
   gboolean active;
 
   active = (gtk_toggle_action_get_active (toggle));
+
+  if (priv->sending_video == active)
+    return;
+  priv->sending_video = active;
+
   empathy_call_window_set_send_video (window, active);
+  gtk_toggle_tool_button_set_active (
+      GTK_TOGGLE_TOOL_BUTTON (priv->camera_button), active);
 }
 
 static void
index 00b8ffa886868e907d17b90cfaaef0611e42275e..ce3d85b56e11e1b0d264f2d7b9907948097c67e1 100644 (file)
@@ -14,6 +14,7 @@
           <object class="GtkToggleAction" id="send_video">
             <property name="name">send_video</property>
             <property name="label" translatable="yes">Send video</property>
+            <property name="sensitive">False</property>
           </object>
         </child>
         <child>
index 145d45e7fac5f98dcf97c9dfd37ae6a3f84f9784..0738f6e52386a255eca4c28d4fe45b40577f0539 100644 (file)
 #include <telepathy-glib/util.h>
 #include <libmissioncontrol/mission-control.h>
 
-#include <libempathy/empathy-contact-factory.h>
 #include <libempathy/empathy-contact.h>
 #include <libempathy/empathy-message.h>
 #include <libempathy/empathy-dispatcher.h>
 #include <libempathy/empathy-chatroom-manager.h>
+#include <libempathy/empathy-account-manager.h>
 #include <libempathy/empathy-utils.h>
 
 #include <libempathy-gtk/empathy-images.h>
@@ -953,7 +953,7 @@ chat_window_new_message_cb (EmpathyChat       *chat,
        if (has_focus && priv->current_chat == chat) {
                return;
        }
-       
+
        /* If empathy_chat_is_room() returns TRUE, that means it's a named MUC.
         * If empathy_chat_get_remote_contact() returns NULL, that means it's
         * an unamed MUC (msn-like).
@@ -1161,17 +1161,33 @@ chat_window_drag_data_received (GtkWidget        *widget,
                McAccount             *account;
                const gchar           *id;
                gchar                **strv;
+               const gchar           *account_id;
+               const gchar           *contact_id;
 
                id = (const gchar*) selection->data;
 
                DEBUG ("DND contact from roster with id:'%s'", id);
                
                strv = g_strsplit (id, "/", 2);
-               account = mc_account_lookup (strv[0]);
-               chat = empathy_chat_window_find_chat (account, strv[1]);
+               account_id = strv[0];
+               contact_id = strv[1];
+               account = mc_account_lookup (account_id);
+               chat = empathy_chat_window_find_chat (account, contact_id);
 
                if (!chat) {
-                       empathy_dispatcher_chat_with_contact_id (account, strv[2], NULL, NULL);
+                       EmpathyAccountManager *account_manager;
+                       TpConnection *connection;
+
+                       account_manager = empathy_account_manager_dup_singleton ();
+                       connection = empathy_account_manager_get_connection (
+                               account_manager, account);
+
+                       if (connection) {
+                               empathy_dispatcher_chat_with_contact_id (
+                                       connection, contact_id, NULL, NULL);
+                       }
+
+                       g_object_unref (account_manager);
                        g_object_unref (account);
                        g_strfreev (strv);
                        return;
@@ -1700,17 +1716,3 @@ empathy_chat_window_present_chat (EmpathyChat *chat)
        gtk_widget_grab_focus (chat->input_text_view); 
 }
 
-#if 0
-static gboolean
-chat_window_should_play_sound (EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv = GET_PRIV (window);
-       gboolean               has_focus = FALSE;
-
-       g_return_val_if_fail (EMPATHY_IS_CHAT_WINDOW (window), FALSE);
-
-       g_object_get (priv->dialog, "has-toplevel-focus", &has_focus, NULL);
-
-       return !has_focus;
-}
-#endif
index acd559e5f03c0497d1f934a067bebe09874db984..fa63d5a514e044ce7d1856eea124c888d16e453f 100644 (file)
@@ -318,7 +318,7 @@ chatrooms_window_model_refresh_data (EmpathyChatroomsWindow *window,
 
        /* Look up chatrooms */
        account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
-       account = empathy_account_chooser_get_account (account_chooser);
+       account = empathy_account_chooser_dup_account (account_chooser);
 
        chatrooms = empathy_chatroom_manager_get_chatrooms (window->manager, account);
 
@@ -509,7 +509,7 @@ chatrooms_window_chatroom_added_cb (EmpathyChatroomManager *manager,
        McAccount            *account;
 
        account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
-       account = empathy_account_chooser_get_account (account_chooser);
+       account = empathy_account_chooser_dup_account (account_chooser);
 
        if (!account) {
                chatrooms_window_model_add (window, chatroom, FALSE);
index adb5e73f9520d5fb8f01f91e7af5ff9985694e67..0b4fa775a73157045907cb52d2017d89011daf28 100644 (file)
 #include <telepathy-glib/util.h>
 
 #include <libempathy/empathy-dispatcher.h>
-#include <libempathy/empathy-contact-factory.h>
+#include <libempathy/empathy-tp-contact-factory.h>
 #include <libempathy/empathy-contact-manager.h>
 #include <libempathy/empathy-tp-chat.h>
 #include <libempathy/empathy-tp-call.h>
+#include <libempathy/empathy-tp-file.h>
 #include <libempathy/empathy-utils.h>
 #include <libempathy/empathy-call-factory.h>
 
@@ -372,8 +373,7 @@ event_channel_process_voip_func (EventPriv *event)
       return;
     }
 
-  dialog = gtk_message_dialog_new (GTK_WINDOW (empathy_main_window_get()),
-      GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+  dialog = gtk_message_dialog_new (NULL, 0,
       GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, _("Incoming call"));
   gtk_message_dialog_format_secondary_text (
     GTK_MESSAGE_DIALOG (dialog),
@@ -500,21 +500,12 @@ event_manager_operation_invalidated_cb (EmpathyDispatchOperation *operation,
 }
 
 static void
-event_manager_media_channel_got_name_cb (EmpathyContact *contact,
-  const GError *error, gpointer user_data, GObject *object)
+event_manager_media_channel_got_contact (EventManagerApproval *approval)
 {
-  EventManagerApproval *approval = user_data;
   gchar *header;
 
-  if (error != NULL)
-    {
-      /* FIXME just returning assuming the operation will be invalidated as
-       * well */
-      return;
-    }
-
   header = g_strdup_printf (_("Incoming call from %s"),
-    empathy_contact_get_name (contact));
+    empathy_contact_get_name (approval->contact));
 
   event_manager_add (approval->manager,
     approval->contact, EMPATHY_IMAGE_VOIP, header, NULL,
@@ -524,14 +515,6 @@ event_manager_media_channel_got_name_cb (EmpathyContact *contact,
   event_manager_start_ringing (approval->manager);
 }
 
-static void
-event_manager_media_channel_got_contact (EventManagerApproval *approval)
-{
-  empathy_contact_call_when_ready (approval->contact,
-     EMPATHY_CONTACT_READY_NAME, event_manager_media_channel_got_name_cb,
-        approval, NULL, G_OBJECT (approval->manager));
-}
-
 static void
 event_manager_media_channel_contact_changed_cb (EmpathyTpCall *call,
   GParamSpec *param, EventManagerApproval *approval)
@@ -604,23 +587,27 @@ event_manager_tube_dispatch_ability_cb (GObject *object,
 }
 
 static void
-event_manager_tube_got_contact_name_cb (EmpathyContact *contact,
-  const GError *error, gpointer user_data, GObject *object)
+event_manager_tube_got_contact_cb (EmpathyTpContactFactory *factory,
+                                   EmpathyContact *contact,
+                                   const GError *error,
+                                   gpointer user_data,
+                                   GObject *object)
 {
   EventManagerApproval *approval = (EventManagerApproval *)user_data;
   EmpathyTubeDispatchAbility dispatchability;
 
   if (error != NULL)
     {
-      /* FIXME?, we assume that the operation gets invalidated as well (if it
-       * didn't already */
-       return;
+      /* FIXME: We should probably still display the event */
+      DEBUG ("Error: %s", error->message);
+      return;
     }
 
+  approval->contact = g_object_ref (contact);
+
   dispatchability = empathy_tube_dispatch_is_dispatchable
     (approval->tube_dispatch);
 
-
   switch (dispatchability)
     {
       case EMPATHY_TUBE_DISPATCHABILITY_UNKNOWN:
@@ -724,10 +711,11 @@ event_room_channel_process_func (EventPriv *event)
 }
 
 static void
-event_manager_muc_invite_got_contact_name_cb (EmpathyContact *contact,
-                                              const GError *error,
-                                              gpointer user_data,
-                                              GObject *object)
+event_manager_muc_invite_got_contact_cb (EmpathyTpContactFactory *factory,
+                                         EmpathyContact *contact,
+                                         const GError *error,
+                                         gpointer user_data,
+                                         GObject *object)
 {
   EventManagerApproval *approval = (EventManagerApproval *) user_data;
   TpChannel *channel;
@@ -735,6 +723,14 @@ event_manager_muc_invite_got_contact_name_cb (EmpathyContact *contact,
   gchar *msg;
   TpHandle self_handle;
 
+  if (error != NULL)
+    {
+      /* FIXME: We should probably still display the event */
+      DEBUG ("Error: %s", error->message);
+      return;
+    }
+
+  approval->contact = g_object_ref (contact);
   channel = empathy_dispatch_operation_get_channel (approval->operation);
 
   self_handle = tp_channel_group_get_self_handle (channel);
@@ -795,24 +791,20 @@ event_manager_approve_channel_cb (EmpathyDispatcher *dispatcher,
                 channel, self_handle, &inviter, NULL, NULL))
             {
               /* We are invited to a room */
-              EmpathyContactFactory *contact_factory;
-              McAccount *account;
+              EmpathyTpContactFactory *factory;
+              TpConnection *connection;
 
               DEBUG ("Have been invited to %s. Ask user if he wants to accept",
                   tp_channel_get_identifier (channel));
 
-              account = empathy_tp_chat_get_account (tp_chat);
-              contact_factory = empathy_contact_factory_dup_singleton ();
-
-              approval->contact = empathy_contact_factory_get_from_handle (
-                  contact_factory, account, inviter);
+              connection = empathy_tp_chat_get_connection (tp_chat);
+              factory = empathy_tp_contact_factory_dup_singleton (connection);
 
-              empathy_contact_call_when_ready (approval->contact,
-                EMPATHY_CONTACT_READY_NAME,
-                event_manager_muc_invite_got_contact_name_cb, approval, NULL,
-                G_OBJECT (manager));
+              empathy_tp_contact_factory_get_from_handle (factory,
+                  inviter, event_manager_muc_invite_got_contact_cb,
+                  approval, NULL, G_OBJECT (manager));
 
-              g_object_unref (contact_factory);
+              g_object_unref (factory);
               return;
             }
 
@@ -847,73 +839,45 @@ event_manager_approve_channel_cb (EmpathyDispatcher *dispatcher,
     }
   else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER))
     {
-      EmpathyContact        *contact;
-      gchar                 *header;
-      TpHandle               handle;
-      McAccount             *account;
-      EmpathyContactFactory *factory;
-      TpChannel *channel = empathy_dispatch_operation_get_channel (operation);
+      EmpathyTpFile *file;
+      gchar *header;
 
-      factory = empathy_contact_factory_dup_singleton ();
-      handle = tp_channel_get_handle (channel, NULL);
-      account = empathy_channel_get_account (channel);
-
-      contact = empathy_contact_factory_get_from_handle (factory, account,
-        handle);
-
-      empathy_contact_run_until_ready (contact,
-        EMPATHY_CONTACT_READY_NAME, NULL);
+      file = EMPATHY_TP_FILE (empathy_dispatch_operation_get_channel_wrapper (operation));
+      approval->contact = g_object_ref (empathy_tp_file_get_contact (file));
 
       header = g_strdup_printf (_("Incoming file transfer from %s"),
-        empathy_contact_get_name (contact));
+        empathy_contact_get_name (approval->contact));
 
-      event_manager_add (manager, contact, EMPATHY_IMAGE_DOCUMENT_SEND,
+      event_manager_add (manager, approval->contact, EMPATHY_IMAGE_DOCUMENT_SEND,
         header, NULL, approval, event_channel_process_func, NULL);
 
       /* FIXME better sound for incoming file transfers ?*/
       empathy_sound_play (empathy_main_window_get (),
         EMPATHY_SOUND_CONVERSATION_NEW);
 
-      g_object_unref (factory);
-      g_object_unref (account);
       g_free (header);
     }
   else if (!tp_strdiff (channel_type, EMP_IFACE_CHANNEL_TYPE_STREAM_TUBE) ||
       !tp_strdiff (channel_type, EMP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
     {
-      EmpathyContact        *contact;
-      TpHandle               handle;
-      TpHandleType           handle_type;
-      McAccount             *account;
-      EmpathyContactFactory *factory;
-      EmpathyTubeDispatch *tube_dispatch;
       TpChannel *channel;
+      TpHandle handle;
+      TpHandleType handle_type;
+      TpConnection *connection;
+      EmpathyTpContactFactory *factory;
 
       channel = empathy_dispatch_operation_get_channel (operation);
-
       handle = tp_channel_get_handle (channel, &handle_type);
 
       /* Only understand p2p tubes */
       if (handle_type != TP_HANDLE_TYPE_CONTACT)
         return;
 
-      factory = empathy_contact_factory_dup_singleton ();
-      account = empathy_channel_get_account (channel);
-
-      contact = empathy_contact_factory_get_from_handle (factory, account,
-        handle);
-
-      tube_dispatch = empathy_tube_dispatch_new (operation);
-
-      approval->contact = contact;
-      approval->tube_dispatch = tube_dispatch;
-
-      empathy_contact_call_when_ready (contact,
-        EMPATHY_CONTACT_READY_NAME, event_manager_tube_got_contact_name_cb,
-        approval, NULL, G_OBJECT (manager));
-
-      g_object_unref (factory);
-      g_object_unref (account);
+      approval->tube_dispatch = empathy_tube_dispatch_new (operation);
+      connection = tp_channel_borrow_connection (channel);
+      factory = empathy_tp_contact_factory_dup_singleton (connection);
+      empathy_tp_contact_factory_get_from_handle (factory, handle,
+        event_manager_tube_got_contact_cb, approval, NULL, G_OBJECT (manager));
     }
   else
     {
@@ -945,19 +909,17 @@ event_manager_pendings_changed_cb (EmpathyContactList  *list,
         {
           EventPriv *event = l->data;
 
-      if (event->public.contact == contact &&
-          event->func == event_pending_subscribe_func)
-        {
-          event_remove (event);
-          break;
+          if (event->public.contact == contact &&
+              event->func == event_pending_subscribe_func)
+            {
+              event_remove (event);
+              break;
+            }
         }
-      }
 
       return;
     }
 
-  empathy_contact_run_until_ready (contact, EMPATHY_CONTACT_READY_NAME, NULL);
-
   header = g_strdup_printf (_("Subscription requested by %s"),
     empathy_contact_get_name (contact));
 
index 6c5f1fa2c0f1e094caf133af60d0b79b05a6890f..b9993a8f543edc65dbefc9b49119506f91658f20 100644 (file)
@@ -35,7 +35,6 @@
 #include <libempathy/empathy-chatroom.h>
 #include <libempathy/empathy-contact-list.h>
 #include <libempathy/empathy-contact-manager.h>
-#include <libempathy/empathy-contact-factory.h>
 #include <libempathy/empathy-status-presets.h>
 
 #include <libempathy-gtk/empathy-contact-dialogs.h>
@@ -703,23 +702,21 @@ main_window_chat_show_offline_cb (GtkToggleAction   *action,
 static void
 main_window_favorite_chatroom_join (EmpathyChatroom *chatroom)
 {
-       MissionControl *mc;
+       EmpathyAccountManager *manager;
        McAccount      *account;
+       TpConnection   *connection;
        const gchar    *room;
 
-       mc = empathy_mission_control_dup_singleton ();
+       manager = empathy_account_manager_dup_singleton ();
        account = empathy_chatroom_get_account (chatroom);
+       connection = empathy_account_manager_get_connection (manager, account);
        room = empathy_chatroom_get_room (chatroom);
+       g_object_unref (manager);
 
-       if (mission_control_get_connection_status (mc, account, NULL) !=
-           TP_CONNECTION_STATUS_CONNECTED) {
-               return;
+       if (connection != NULL) {
+               DEBUG ("Requesting channel for '%s'", room);
+               empathy_dispatcher_join_muc (connection, room, NULL, NULL);
        }
-
-       DEBUG ("Requesting channel for '%s'", room);
-       empathy_dispatcher_join_muc (account, room, NULL, NULL);
-
-       g_object_unref (mc);
 }
 
 static void
@@ -906,31 +903,7 @@ static void
 main_window_edit_personal_information_cb (GtkAction         *action,
                                          EmpathyMainWindow *window)
 {
-       GSList *accounts;
-
-       accounts = mission_control_get_online_connections (window->mc, NULL);
-       if (accounts) {
-               EmpathyContactFactory *factory;
-               EmpathyContact        *contact;
-               McAccount             *account;
-
-               account = accounts->data;
-               factory = empathy_contact_factory_dup_singleton ();
-               contact = empathy_contact_factory_get_user (factory, account);
-               empathy_contact_run_until_ready (contact,
-                                                EMPATHY_CONTACT_READY_HANDLE |
-                                                EMPATHY_CONTACT_READY_ID,
-                                                NULL);
-
-               empathy_contact_information_dialog_show (contact,
-                                                        GTK_WINDOW (window->window),
-                                                        TRUE, TRUE);
-
-               g_slist_foreach (accounts, (GFunc) g_object_unref, NULL);
-               g_slist_free (accounts);
-               g_object_unref (factory);
-               g_object_unref (contact);
-       }
+       empathy_contact_personal_dialog_show (GTK_WINDOW (window->window));
 }
 
 static void
index bf107d1b6b2e207a81e4352362bed6a4d62e5dc6..837d9acfe466ad889d4a82f16b2948b8affdb2ee 100644 (file)
@@ -342,7 +342,7 @@ new_chatroom_dialog_update_widgets (EmpathyNewChatroomDialog *dialog)
        const gchar           *room;
        
        account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
-       account = empathy_account_chooser_get_account (account_chooser);
+       account = empathy_account_chooser_dup_account (account_chooser);
        profile = mc_account_get_profile (account);
        protocol = mc_profile_get_protocol_name (profile);
 
@@ -388,7 +388,7 @@ new_chatroom_dialog_account_changed_cb (GtkComboBox             *combobox,
        new_chatroom_dialog_model_clear (dialog);
 
        account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
-       account = empathy_account_chooser_get_account (account_chooser);
+       account = empathy_account_chooser_dup_account (account_chooser);
        dialog->room_list = empathy_tp_roomlist_new (account);
 
        if (dialog->room_list) {
@@ -409,6 +409,8 @@ new_chatroom_dialog_account_changed_cb (GtkComboBox             *combobox,
        }
 
        new_chatroom_dialog_update_widgets (dialog);
+
+       g_object_unref (account);
 }
 
 static void
@@ -533,7 +535,7 @@ static void
 new_chatroom_dialog_join (EmpathyNewChatroomDialog *dialog)
 {
        EmpathyAccountChooser *account_chooser;
-       McAccount             *account;
+       TpConnection          *connection;
        const gchar           *room;
        const gchar           *server = NULL;
        gchar                 *room_name = NULL;
@@ -542,7 +544,7 @@ new_chatroom_dialog_join (EmpathyNewChatroomDialog *dialog)
        server = gtk_entry_get_text (GTK_ENTRY (dialog->entry_server));
 
        account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
-       account = empathy_account_chooser_get_account (account_chooser);
+       connection = empathy_account_chooser_get_connection (account_chooser);
 
        if (!EMP_STR_EMPTY (server)) {
                room_name = g_strconcat (room, "@", server, NULL);
@@ -551,7 +553,7 @@ new_chatroom_dialog_join (EmpathyNewChatroomDialog *dialog)
        }
 
        DEBUG ("Requesting channel for '%s'", room_name);
-       empathy_dispatcher_join_muc (account, room_name, NULL, NULL);
+       empathy_dispatcher_join_muc (connection, room_name, NULL, NULL);
 
        g_free (room_name);
 }
index a2115a6cff4cf9568ef5b9fbf2a487f4ec472d95..817b9bc37fe6cdd6344522f01c014acd0f7aba65 100644 (file)
@@ -42,6 +42,7 @@
 #include <libempathy/empathy-utils.h>
 #include <libempathy/empathy-call-factory.h>
 #include <libempathy/empathy-chatroom-manager.h>
+#include <libempathy/empathy-account-manager.h>
 #include <libempathy/empathy-dispatcher.h>
 #include <libempathy/empathy-dispatch-operation.h>
 #include <libempathy/empathy-log-manager.h>
@@ -96,10 +97,16 @@ dispatch_cb (EmpathyDispatcher *dispatcher,
                }
 
                if (id) {
+                       EmpathyAccountManager *manager;
+                       TpConnection *connection;
                        McAccount *account;
 
-                       account = empathy_tp_chat_get_account (tp_chat);
+                       manager = empathy_account_manager_dup_singleton ();
+                       connection = empathy_tp_chat_get_connection (tp_chat);
+                       account = empathy_account_manager_get_account (manager,
+                                                                      connection);
                        chat = empathy_chat_window_find_chat (account, id);
+                       g_object_unref (manager);
                }
 
                if (chat) {
index 442cafd51a95f99252cd07fb76f94316874ac4f3..a37f3e5a027cbe2bcabc37d778e0fbfcb9d95b3c 100644 (file)
@@ -5,3 +5,4 @@ contact-run-until-ready-2
 *.log
 empetit
 test-empathy-presence-chooser
+test-empathy-status-preset-dialog
index 67f6ec9af8647af47b20d4476728ee84936197b1..7740d1f8beeefd2b387e028f4464a980f9e44188 100644 (file)
@@ -24,16 +24,14 @@ LDADD =                                                             \
 
 noinst_PROGRAMS =                      \
        contact-manager                 \
-       contact-run-until-ready         \
-       contact-run-until-ready-2       \
        empetit                         \
-       test-empathy-presence-chooser
+       test-empathy-presence-chooser   \
+       test-empathy-status-preset-dialog
 
 contact_manager_SOURCES = contact-manager.c
-contact_run_until_ready_SOURCES = contact-run-until-ready.c
-contact_run_until_ready_2_SOURCES = contact-run-until-ready-2.c
 empetit_SOURCES = empetit.c
 test_empathy_presence_chooser_SOURCES = test-empathy-presence-chooser.c
+test_empathy_status_preset_dialog_SOURCES = test-empathy-status-preset-dialog.c
 
 check_PROGRAMS = check-main
 TESTS = check-main
index 2e808c0e742b2f58215a59315f6438f43cc8b566..65273f8c85ca4724cb02dbb60e491970abcf9107 100644 (file)
@@ -143,7 +143,7 @@ destroy_test_account (McAccount *account)
           error = NULL;
         }
 
-      gconf_entry_free (entry);
+      gconf_entry_unref (entry);
     }
 
   g_slist_free (entries);
diff --git a/tests/contact-run-until-ready-2.c b/tests/contact-run-until-ready-2.c
deleted file mode 100644 (file)
index 4265341..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <stdlib.h>
-
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <libempathy/empathy-contact-factory.h>
-#include <libempathy/empathy-contact-manager.h>
-#include <libmissioncontrol/mc-account.h>
-
-static void
-pending_cb (EmpathyContactManager *manager,
-           EmpathyContact        *contact,
-           EmpathyContact        *actor,
-           guint                  reason,
-           gchar                 *message,
-           gboolean               is_pending,
-           gpointer               data)
-{
-       if (!is_pending) {
-               return;
-       }
-
-       g_print ("Contact handle=%d alias=%s\n",
-                empathy_contact_get_handle (contact),
-                empathy_contact_get_name (contact));
-
-       empathy_contact_run_until_ready (contact,
-                                        EMPATHY_CONTACT_READY_NAME,
-                                        NULL);
-
-       g_print ("Contact ready: handle=%d alias=%s ready=%d\n",
-                empathy_contact_get_handle (contact),
-                empathy_contact_get_name (contact),
-                empathy_contact_get_ready (contact));
-
-       g_object_unref (manager);
-       gtk_main_quit ();
-}
-
-static gboolean
-callback (gpointer data)
-{
-       EmpathyContactManager *manager;
-
-       manager = empathy_contact_manager_dup_singleton ();
-       g_signal_connect (manager, "pendings-changed",
-                         G_CALLBACK (pending_cb),
-                         NULL);
-
-       return FALSE;
-}
-
-int
-main (int argc, char **argv)
-{
-       gtk_init (&argc, &argv);
-
-       g_idle_add (callback, NULL);
-
-       gtk_main ();
-
-       return EXIT_SUCCESS;
-}
-
diff --git a/tests/contact-run-until-ready.c b/tests/contact-run-until-ready.c
deleted file mode 100644 (file)
index 13fad63..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <stdlib.h>
-
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <libempathy/empathy-contact-factory.h>
-#include <libmissioncontrol/mc-account.h>
-
-static gboolean
-callback (gpointer data)
-{
-       EmpathyContactFactory *factory;
-       McAccount             *account;
-       EmpathyContact        *contact;
-       EmpathyContactReady    ready_flags;
-
-       factory = empathy_contact_factory_dup_singleton ();
-       account = mc_account_lookup ("jabber0");
-       contact = empathy_contact_factory_get_from_handle (factory, account, 2);
-
-       g_print ("Contact handle=%d alias=%s\n",
-                empathy_contact_get_handle (contact),
-                empathy_contact_get_name (contact));
-
-       ready_flags = EMPATHY_CONTACT_READY_HANDLE | EMPATHY_CONTACT_READY_NAME;
-       empathy_contact_run_until_ready (contact, ready_flags, NULL);
-
-       g_print ("Contact ready: handle=%d alias=%s ready=%d needed-ready=%d\n",
-                empathy_contact_get_handle (contact),
-                empathy_contact_get_name (contact),
-                empathy_contact_get_ready (contact),
-                ready_flags);
-
-       g_object_unref (factory);
-       g_object_unref (account);
-       g_object_unref (contact);
-
-       gtk_main_quit ();
-
-       return FALSE;
-}
-
-int
-main (int argc, char **argv)
-{
-       gtk_init (&argc, &argv);
-
-       g_idle_add (callback, NULL);
-
-       gtk_main ();
-
-       return EXIT_SUCCESS;
-}
-
index 02991e859b46316212ced429e41abf6eec32ca64..12d35b4c623f90b4052bd24170f240be3b626fc2 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <gtk/gtk.h>
 
+#include <libempathy/empathy-status-presets.h>
+
 #include <libempathy-gtk/empathy-ui-utils.h>
 #include <libempathy-gtk/empathy-presence-chooser.h>
 
@@ -36,6 +38,8 @@ main (int argc, char **argv)
        gtk_init (&argc, &argv);
        empathy_gtk_init ();
 
+       empathy_status_presets_get_all ();
+
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        chooser = empathy_presence_chooser_new ();
        gtk_container_add (GTK_CONTAINER (window), chooser);
diff --git a/tests/test-empathy-status-preset-dialog.c b/tests/test-empathy-status-preset-dialog.c
new file mode 100644 (file)
index 0000000..6602e4f
--- /dev/null
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Davyd Madeley <davyd.madeley@collabora.co.uk>
+ */
+
+#include <config.h>
+
+#include <gtk/gtk.h>
+
+#include <libempathy/empathy-status-presets.h>
+
+#include <libempathy-gtk/empathy-ui-utils.h>
+#include <libempathy-gtk/empathy-status-preset-dialog.h>
+
+int
+main (int argc, char **argv)
+{
+       GtkWidget *dialog;
+
+       gtk_init (&argc, &argv);
+       empathy_gtk_init ();
+
+       empathy_status_presets_get_all ();
+
+       dialog = empathy_status_preset_dialog_new (NULL);
+
+       gtk_widget_show (dialog);
+
+       gtk_main ();
+
+       return 0;
+}