]> git.0d.be Git - empathy.git/commitdiff
Completely reworked ContactList API. Fixes bug #471611, bug #467280, bug #459540...
authorXavier Claessens <xclaesse@src.gnome.org>
Thu, 30 Aug 2007 16:49:52 +0000 (16:49 +0000)
committerXavier Claessens <xclaesse@src.gnome.org>
Thu, 30 Aug 2007 16:49:52 +0000 (16:49 +0000)
svn path=/trunk/; revision=280

49 files changed:
ChangeLog
configure.ac
doc/libempathy-gtk/tmpl/empathy-contact-list-store.sgml
doc/libempathy-gtk/tmpl/empathy-contact-list-view.sgml
doc/libempathy-gtk/tmpl/empathy-images.sgml
doc/libempathy-gtk/tmpl/empathy-preferences.sgml
doc/libempathy/libempathy.types
doc/libempathy/tmpl/empathy-avatar.sgml
doc/libempathy/tmpl/empathy-contact-list.sgml
doc/libempathy/tmpl/empathy-contact-manager.sgml
doc/libempathy/tmpl/empathy-contact.sgml
doc/libempathy/tmpl/empathy-tp-contact-list.sgml
doc/libempathy/tmpl/empathy-tp-group.sgml
libempathy-gtk/empathy-chat-window.c
libempathy-gtk/empathy-contact-dialogs.c
libempathy-gtk/empathy-contact-list-store.c
libempathy-gtk/empathy-contact-list-store.h
libempathy-gtk/empathy-contact-list-view.c
libempathy-gtk/empathy-contact-list-view.h
libempathy-gtk/empathy-contact-widget.c
libempathy-gtk/empathy-group-chat.c
libempathy-gtk/empathy-images.h
libempathy-gtk/empathy-main-window.c
libempathy-gtk/empathy-private-chat.c
libempathy-gtk/empathy-status-icon.c
libempathy-gtk/empathy-ui-utils.c
libempathy/Makefile.am
libempathy/empathy-avatar.c
libempathy/empathy-avatar.h
libempathy/empathy-contact-factory.c [new file with mode: 0644]
libempathy/empathy-contact-factory.h [new file with mode: 0644]
libempathy/empathy-contact-list.c
libempathy/empathy-contact-list.h
libempathy/empathy-contact-manager.c
libempathy/empathy-contact-manager.h
libempathy/empathy-contact.c
libempathy/empathy-contact.h
libempathy/empathy-log-manager.c
libempathy/empathy-marshal.list
libempathy/empathy-tp-chat.c
libempathy/empathy-tp-chatroom.c
libempathy/empathy-tp-contact-list.c
libempathy/empathy-tp-contact-list.h
libempathy/empathy-tp-group.c
libempathy/empathy-tp-group.h
python/README [new file with mode: 0644]
python/pyempathy/pyempathy.defs
python/pyempathy/pyempathy.override
python/pyempathygtk/pyempathygtk.defs

index fdb0c4d9a4f292a624fa392453c4c4bc0827f7aa..976db9ebabea051ba0ce0a357aa8c3150985ddfe 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,23 +1,69 @@
-2007-08-24 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-30  Xavier Claessens  <xclaesse@gmail.com>
+
+       * python/pyempathy/pyempathy.defs:
+       * python/pyempathy/pyempathy.override:
+       * python/pyempathygtk/pyempathygtk.defs: Updated for new API.
+       * python/README: Explain how to update python binding.
+
+       * libempathy-gtk/empathy-images.h:
+       * libempathy-gtk/empathy-private-chat.c:
+       * libempathy-gtk/empathy-main-window.c:
+       * libempathy-gtk/empathy-status-icon.c:
+       * libempathy-gtk/empathy-group-chat.c:
+       * libempathy-gtk/empathy-ui-utils.c:
+       * libempathy-gtk/empathy-contact-dialogs.c:
+       * libempathy-gtk/empathy-contact-list-view.c:
+       * libempathy-gtk/empathy-contact-list-view.h:
+       * libempathy-gtk/empathy-contact-widget.c:
+       * libempathy-gtk/empathy-contact-list-store.c:
+       * libempathy-gtk/empathy-contact-list-store.h:
+       * libempathy-gtk/empathy-chat-window.c: Updated to use new libempathy
+       API.
+
+       * libempathy/empathy-log-manager.c:
+       * libempathy/empathy-contact.c:
+       * libempathy/empathy-contact.h:
+       * libempathy/empathy-tp-chat.c:
+       * libempathy/empathy-contact-manager.c:
+       * libempathy/empathy-contact-manager.h:
+       * libempathy/empathy-avatar.c:
+       * libempathy/empathy-avatar.h:
+       * libempathy/empathy-tp-contact-list.c:
+       * libempathy/empathy-tp-contact-list.h:
+       * libempathy/empathy-tp-chatroom.c:
+       * libempathy/empathy-contact-factory.c:
+       * libempathy/empathy-contact-factory.h:
+       * libempathy/empathy-contact-list.c:
+       * libempathy/empathy-contact-list.h:
+       * libempathy/empathy-tp-group.c:
+       * libempathy/empathy-marshal.list:
+       * libempathy/empathy-tp-group.h:
+       * libempathy/Makefile.am:
+       * configure.ac: Completely reworked ContactList API. Fixes bug #471611,
+       bug #467280, bug #459540 and bug #462907.
+
+       * doc/*: Updated.
+
+2007-08-24  Xavier Claessens  <xclaesse@gmail.com>
 
        * python/pyempathy/Makefile.am:
        * python/pyempathygtk/Makefile.am:
        * configure.ac: Make use of AM_PATH_PYTHON to get python variables.
        Fixes bug #470642 (Daniel Gryniewicz).
 
-2007-08-24 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-24  Xavier Claessens  <xclaesse@gmail.com>
 
        * configure.ac: Bump version to 0.13.
        * NEWS: Last NEWS entry is for version 0.12 and not 0.11.
 
-2007-08-24 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-24  Xavier Claessens  <xclaesse@gmail.com>
 
         * configure.ac:
         * doc/libempathy-gtk/tmpl/empathy-preferences.sgml:
         * NEWS:
         * po/POTFILES.in: Updated.
 
-2007-08-24 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-24  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-new-chatroom-dialog.c:
        * libempathy-gtk/empathy-contact-widget.c:
        * data/salut.profile: Salut's protocol name is going to change to
        local-xmpp. Fixes bug #469638 (Sjoerd Simons)
 
-2007-08-24 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-24  Xavier Claessens  <xclaesse@gmail.com>
 
        * src/empathy.c: Check if there is already a Salut account before
        creating a new one and add more debug messages.
 
-2007-08-24 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-24  Xavier Claessens  <xclaesse@gmail.com>
 
        * configure.ac:
        * data/22x22/Makefile.am:
@@ -52,7 +98,7 @@
        * data/Makefile.am: Change jabber icon. Fixes bug #466377
        (Björn Martensen).
 
-2007-08-23 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-23  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-account-widget-salut.glade:
        * libempathy-gtk/empathy-account-widget-salut.c:
        salut CM installed using gnome-about-me information. Fixes bug #447467
        (Cosimo Cecchi, Xavier Claessens).
 
-2007-08-19 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-19  Xavier Claessens  <xclaesse@gmail.com>
 
        * python/pyempathy/Makefile.am:
        * python/pyempathy/pyempathy.override:
        * python/pyempathygtk/Makefile.am: Fix build system, make distcheck now
        works.
 
-2007-08-19 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-19  Xavier Claessens  <xclaesse@gmail.com>
 
        * python/pyempathy/pyempathy.defs:
        * python/pyempathy/pyempathymodule.c:
        * configure.ac:
        * Makefile.am: Add python binding. Fixes bug #457660 (Michael Sheldon).
 
-2007-08-19 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-19  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-main-window.glade: Edit menu should be second
        from the left. Fixes bug #467827 (Cosimo Cecchi).
 
-2007-08-13 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-13  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-group-chat.c: Only update the topic of it has
        really be changed, avoid diplaying many times "Topic set to:" message.
        if we already logged them last time we joined that room. Previous
        workaround prevented Empathy to log offline messages.
 
-2007-08-12 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-12  Xavier Claessens  <xclaesse@gmail.com>
 
        * configure.ac: Bump version to 0.12.
 
-2007-08-12 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-12  Xavier Claessens  <xclaesse@gmail.com>
 
        * configure.ac: Update libtool version.
 
        * doc/libempathy-gtk/tmpl/empathy-status-presets.sgml:
        * NEWS: Updated.
 
-2007-08-12 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-12  Xavier Claessens  <xclaesse@gmail.com>
 
        * data/irc.profile: Removed spaces in the SupportedPresences key to
        workaround a MC warning SF bug 1772539.
 
-2007-08-11 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-11  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-accounts-dialog.c: Make "Add account" button
        insensitive when we are creating one. Fixes bug #459170
        (Jaap A. Haitsma).
 
-2007-08-11 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-11  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/empathy-tp-contact-list.c: s/Local Network/People nearby/
        (Sjoerd Simons)
 
-2007-08-10 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-10  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-accounts-dialog.c: Unselect accounts when
        clicking on "add" button. Fixes bug #459173 (Cosimo Cecchi).
 
-2007-08-10 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-10  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-presence-chooser.glade: add some spacing in
        "Custom message" dialog. Fixes bug #465360 (Frederic Peters).
 
-2007-08-10 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-10  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-images.h:
        * libempathy-gtk/empathy-presence-chooser.c:
        * data/irc.profile:
        * data/msn.profile: Updated to use SupportedPresences field.
 
-2007-08-09 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-09  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-presence-chooser.glade:
        * libempathy-gtk/empathy-presence-chooser.c:
        messages. Make easier to add other states to the list if needed.
        Fixes bug #460678.
 
-2007-08-09 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-09  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/empathy-presence.c:
        * libempathy/empathy-idle.c:
        * configure.ac: Remove workaround for mc-enum-types.h not being
        installed by MC and bump MC minimal version to 4.33.
 
-2007-08-09 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-09  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-preferences.c:
        * libempathy-gtk/empathy-preferences.glade: Useless spell checker
        option. Fixes bug #459164 (Cosimo Cecchi).
 
-2007-08-08 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-08  Xavier Claessens  <xclaesse@gmail.com>
 
        * autogen.sh: Requier automake 1.9. Fixes bug #464822 (Cosimo Cecchi).
 
-2007-08-08 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-08  Xavier Claessens  <xclaesse@gmail.com>
 
        * MAINTAINERS: Updated the MAINTAINERS file to match new syntax.
 
        empathy_contact_list_store_sort_get_type() as it's now auto-generated
        by glib-mkenums.
 
-2007-08-06 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-06  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-main-window.glade: Change main window's title
        to "Contact list".
 
-2007-08-06 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-06  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/empathy-tp-chat.c: Don't forget to reverse the glist of
        pending messages.
        * libempathy/empathy-tp-roomlist.c: Fix wrong room list names when
        listing them.
 
-2007-08-06 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-06  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-account-widget-msn.glade:
        * libempathy-gtk/empathy-account-widget-msn.c: Add an Advanced section
 
        * README: Use ./autogen.sh instead of gnome-autogen.sh.
 
-2007-08-02 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-02  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-accounts-dialog.glade:
        * libempathy-gtk/empathy-accounts-dialog.c: Click on the treeview to
        edit the name of an account. Fixes bug #459166.
 
-2007-08-02 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-02  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-account-widget-jabber.c: Do not try to guess
        the Jabber server from the jid, gabble does that for us.
 
-2007-08-02 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-02  Xavier Claessens  <xclaesse@gmail.com>
 
        * doc/libempathy-gtk/tmpl/empathy-account-chooser.sgml:
        * doc/libempathy-gtk/tmpl/empathy-ui-utils.sgml:
        * doc/libempathy/tmpl/empathy-message.sgml:
        * doc/libempathy/tmpl/empathy-utils.sgml: Update doc.
 
-2007-08-02 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-02  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-profile-chooser.c: Do not list profiles that
        don't have the corresponding CM installed when creating a new account.
        This is a workaround for MC bug: SF #1688779.
 
-2007-08-02 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-02  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-account-widget-generic.c: Remove size_group.
        Fixes bug #462792.
 
-2007-08-02 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-02  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-accounts-dialog.c:
        * libempathy/empathy-utils.c:
        telepathy-glib. It check if strings are != NULL before using strcmp.
        Using that API to fix bug #461886. Should be used in more places.
 
-2007-08-02 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-02  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-status-icon.c: Click on the tray icon shows the
        window if it's not active and hide if it is. Fixes bug #462057
        (Olivier Valentin).
 
-2007-08-02 Xavier Claessens  <xclaesse@gmail.com>
+2007-08-02  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-group-chat.c: don't display
        "Topic set to: (null)". Fixes bug #460205 (Michael Scherer).
 
-2007-07-30 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-30  Xavier Claessens  <xclaesse@gmail.com>
 
        * autogen.sh: Added back, it calls gnome-autogen.sh.
 
-2007-07-29 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-29  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-profile-chooser.c:
        * libempathy/empathy-message.c: Add missing include string.h.
 
-2007-07-29 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-29  Xavier Claessens  <xclaesse@gmail.com>
 
        * configure.ac: Bump version to 0.11.
 
-2007-07-29 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-29  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-account-widget-generic.c:
        * libempathy-gtk/empathy-account-widget-generic.h: Align param names
 
        * configure.ac: Set Collabora Ltd. in the Copyright.
 
-2007-07-28 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-28  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-profile-chooser.c: Makes easier to change to
        profile order.
 
-2007-07-28 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-28  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-account-widget-jabber.c: Try to guess the
        server from the jid only if we are using the jabber profile. When we
        guessed a server don't forget to set the "server" McAccount param,
        setting the entry's text is not enough.
 
-2007-07-28 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-28  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-profile-chooser.c: Improve the sort function
        a bit to have Jabber before GTalk.
 
-2007-07-28 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-28  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-accounts-dialog.glade:
        * libempathy-gtk/empathy-accounts-dialog.c: Update the Enable/Disable
        button even if there is no account selected. Set it insensitive if no
        account is selected. Fixes bug #459012.
 
-2007-07-27 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-27  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-profile-chooser.c: Sort profiles to have
        free protocols first. Fixes bug #460605.
 
-2007-07-27 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-27  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/empathy-message.c:
        * libempathy/empathy-message.h:
 
        * doc/*: Updated.
 
-2007-07-26 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-26  Xavier Claessens  <xclaesse@gmail.com>
 
        * po/POTFILES.in: Add missing file
        libempathy-gtk/empathy-account-widget-msn.glade.
 
-2007-07-26 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-26  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-account-widget-jabber.glade:
        * libempathy-gtk/empathy-account-widget-jabber.c: Hide
        "advanced options" for jabber in a GtkExpander. Fixes bug #459168
        (Guillaume Desmottes).
 
-2007-07-26 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-26  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-new-chatroom-dialog.c:
        * libempathy/empathy-tp-roomlist.c: Fix Room listing. Fixes bug #460416
        (Sjoerd Simons).
 
-2007-07-26 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-26  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/Makefile.am:
        * libempathy/Makefile.am:
        * configure.ac: Use libtool -version-info. Fixes bug #460579
        (Laurent Bigonville).
 
-2007-07-26 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-26  Xavier Claessens  <xclaesse@gmail.com>
 
        * README:
        * autogen.sh: Remove the autogen.sh script and use gnome-autogen.sh
        instead. Fixes bug #460590.
 
-2007-07-26 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-26  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-account-chooser.c:
        * libempathy-gtk/empathy-new-chatroom-dialog.c:
        a bit EmpathyContactWidget. Fixes bug #459100
        (Guillaume Desmottes, Xavier Claessens).
 
-2007-07-26 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-26  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-accounts-dialog.c: add contact frame is not
        hidden after cancelling. Fixes bug #458997 (Frederic Peters).
 
-2007-07-26 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-26  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/empathy-idle.c: Fix problems when NM is not running. Fixes
        bug #460419.
 
        * doc/*: Updated documentation.
 
-2007-07-26 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-26  Xavier Claessens  <xclaesse@gmail.com>
 
        * configure.ac: Bump version to 0.10
 
-2007-07-25 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-25  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/empathy-filter.c: Adding more debug output.
 
-2007-07-25 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-25  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/empathy-tp-contact-list.c: Add a check to be sure the
        new channel is valid in the NewChannel cb. Fixes bug #451564.
 
-2007-07-20 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-20  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/Makefile.am:
        * libempathy/empathy-tp-roomlist.h:
        * data/empathy.desktop.in.in: Change application description
        (Jaap A. Haitsma).
 
-2007-07-14 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-14  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-contact-list-store.c: Show avatars by default.
 
-2007-07-13 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-13  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-status-icon.c: If there is no pending msg
        when a text channel should be filtered wait for the first message
        instead of not dispatching the channel which may cause messages to be
        lost.
 
-2007-07-13 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-13  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/empathy-tp-contact-list.c: Fix avatar request queue.
 
-2007-07-13 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-13  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-new-chatroom-dialog.c:
        * libempathy-gtk/empathy-new-chatroom-dialog.glade: Remove unused
        * libempathy/empathy-tp-contact-list.c: Add more debug msg for avatar
        handling.
 
-2007-07-12 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-12  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/Makefile.am: Fix missing header for
        EmpathyAccountWidgetMSN.
 
        * autogen.sh: run gtkdocize if needed.
 
-2007-07-12 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-12  Xavier Claessens  <xclaesse@gmail.com>
 
        * configure.ac:
        * doc/*:
        * Makefile.am: Adding initial API documentation using gtk-doc.
 
-2007-07-12 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-12  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/empathy-tp-contact-list.c: Auto-accept to publish presence
        to contacts that are in our subscribe list. When accepting a pending
        contact add it to publish and subscribe list.
 
-2007-07-09 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-09  Xavier Claessens  <xclaesse@gmail.com>
 
        * src/empathy.c:
        * libempathy/empathy-debug.c:
        * libempathy/empathy-debug.h: Add EMPATHY_LOGFILE env variable. Fixes
        bug #455240 (Guillaume Desmottes).
 
-2007-07-09 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-09  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-account-widget-msn.glade:
        * libempathy-gtk/empathy-account-widget-msn.c:
        * libempathy/empathy-log-manager.h: Add needed API to show chat logs in
        Tracker. Fixes bug #452536.
 
-2007-07-07 Xavier Claessens  <xclaesse@gmail.com>
+2007-07-07  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-account-widget-generic.c: Workaround to fix a 
        commonly reported crash. Fixes bug #454277
        * libempathy/empathy-tp-group.c: Add a missing check.
 
-2007-06-30 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-30  Xavier Claessens  <xclaesse@gmail.com>
 
        * configure.ac: Bump MC version required to 4.27.
        * TODO: Updated.
 
-2007-06-30 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-30  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-account-widget-generic.c: Fix a leaked ref.
 
        status icon flash when there we receive a new message. Dispatch the
        channel only when we get a message and the user click on the icon.
 
-2007-06-22 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-22  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/libempathy-gtk.pc.in:
        * libempathy-gtk/Makefile.am:
        * configure.ac: Install libempathy and libempathy-gtk and make their
        API public.
 
-2007-06-22 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-22  Xavier Claessens  <xclaesse@gmail.com>
 
        * po/POTFILES.in: s/gossip/empathy/
 
-2007-06-22 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-22  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/*.[ch]:
        * libempathy-gtk/*.[ch]:
        change namespace of all gossip_*() functions to empathy_*().
        Fixes bug #444490 (Mario Danic, Xavier Claessens).
 
-2007-06-21 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-21  Xavier Claessens  <xclaesse@gmail.com>
 
        * configure.ac: Bump version to 0.9
 
-2007-06-21 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-21  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/empathy-tp-contact-list.c: Fix typo causing warnings.
 
-2007-06-21 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-21  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-contact-dialogs.c:
        * libempathy-gtk/gossip-contact-list-store.c:
        only add/remove from subscribe list. Accept/Reject a contact in
        local-pending of publish list is done using _process_pending().
 
-2007-06-15 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-15  Xavier Claessens  <xclaesse@gmail.com>
 
        * src/empathy.c:
        * libempathy/empathy-idle.c: Adding NetworkManager support.
 
-2007-06-15 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-15  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-status-icon.c:
        * libempathy-gtk/gossip-presence-chooser.c:
        * libempathy/empathy-idle.h: Prepare for slack time when coming back
        from auto away. Not yet fully implemented.
 
-2007-06-14 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-14  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-images.h:
        * libempathy-gtk/gossip-chat.c: Use gtk-info for contact informaiton.
        * data/scalable/Makefile.am:
        * data/salut.profile: Add salut icon. Fixes bug #447659 (Michael Monreal).
 
-2007-06-14 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-14  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/gossip-contact-list-view.c: Show logs when right
        click on a contact in the roster.
 
-2007-06-14 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-14  Xavier Claessens  <xclaesse@gmail.com>
 
        * src/org.gnome.Empathy.Chat.service.in:
        * src/empathy-accounts.c:
        debugging more difficult when emmpathy-chat crashes. It's also more
        optimised like that since contact objects can be shared.
 
-2007-06-14 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-14  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/gossip-chat-window.c: Disconnect signals from
        chatroom_manager. Fixes bug #447178.
 
-2007-06-14 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-14  Xavier Claessens  <xclaesse@gmail.com>
 
        * po/POTFILES.in:
        * po/POTFILES.skip: Get strings in empathy.desktop.in.in and skip
        empathy.desktop.in. Fixes bug #446161.
 
-2007-06-14 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-14  Xavier Claessens  <xclaesse@gmail.com>
 
        * po/POTFILES.in: Adding missing files.
 
-2007-06-14 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-14  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/gossip-log-window.c:
        * libempathy-gtk/gossip-chat-window.c:
        chat if there is no messages to put in. Show logs and information for
        the contact we are speaking with in the chat window menu.
 
-2007-06-13 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-13  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/Makefile.am:
        * libempathy-gtk/gossip-log-window.glade:
        * libempathy/gossip-message.c: Add a "receiver" property like that we
        have our self contact for nick highlight.
 
-2007-06-10 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-10  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/gossip-spell-dialog.glade:
        * libempathy-gtk/gossip-spell-dialog.c:
        * libempathy-gtk/gossip-spell.c:
        * libempathy/gossip-conf.c: Remove useless debug messages.
 
-2007-06-10 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-10  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/gossip-chat-view.c: Smooth scrolling.
        Fixes bug #445859 (Raphael Slinckx).
 
-2007-06-09 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-09  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/gossip-contact.c: Emit notify signal only if the property
        value effectively changed.
 
-2007-06-09 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-09  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/gossip-contact-list-view.c: Fix warning for DnD.
        patch imported from gossip.
 
-2007-06-09 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-09  Xavier Claessens  <xclaesse@gmail.com>
 
        * configure.ac: Bump version to 0.8
 
        * data/msn.profile: Add VCardField and VCardDefault to profiles for
        eds-sync support.
 
-2007-06-09 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-09  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-contact-widget.c: Fix a warning.
 
-2007-06-09 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-09  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-main-window.c:
        * libempathy-gtk/empathy-contact-widget.glade:
 
        * libempathy/empathy-tp-contact-list.c: Fix a refcount bug.
 
-2007-06-08 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-08  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy/gossip-chatroom-manager.c: Checks if the chatroom has
        an account and a room. Fixes bug #444135.
 
-2007-06-08 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-08  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-contact-dialogs.c:
        * libempathy-gtk/empathy-contact-widget.c:
        gossip_contact_add/remove_group(). This fixes leaks when a contact is
        added/removed from a group.
 
-2007-06-08 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-08  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/gossip-chat.c: Fix build on 64bits arch.
        Fixes bug #444680 (Matej Cepl).
 
-2007-06-06 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-06  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-contact-dialogs.glade:
        * libempathy-gtk/empathy-contact-dialogs.c: Fix response and action
        buttons.
 
-2007-06-06 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-06  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-contact-dialogs.glade:
        * libempathy-gtk/empathy-contact-widget.glade:
        * libempathy-gtk/empathy-subscription-dialog.h: Implement editing and
        viewing contact information with right click on the roster.
 
-2007-06-06 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-06  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-contact-widget.glade:
        * libempathy-gtk/empathy-contact-widget.c:
        * libempathy-gtk/empathy-subscription-dialog.c: EmpatchContactWidget
        has 2 modes: editable or not.
 
-2007-06-06 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-06  Xavier Claessens  <xclaesse@gmail.com>
 
        * po/POTFILES.in: Updated with new files.
 
-2007-06-06 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-06  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-status-icon.c:
        * libempathy-gtk/empathy-subscription-dialog.glade:
        dialog appears when clicking on the status icon when it blinks. You
        can also remove contacts when right-click on it in the roster.
 
-2007-06-06 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-06  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-status-icon.c:
        * libempathy-gtk/empathy-contact-widget.glade:
        gossip_presence_state_get_default_status (MC_PRESENCE_OFFLINE)
        when there is no presence.
 
-2007-06-06 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-06  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/empathy-status-icon.c: Add support for blinking when
        there is an event. Make use of EmpathyIdle for presence handling. Add
 
        * TODO: Updated.
 
-2007-06-03 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-03  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/gossip-accounts-dialog.glade: Set use_stock for
        button_connect to False, to avoid a crasher when opening the accounts
        * libempathy-gtk/gossip-chat.c: Do not add backlog for chatrooms and
        do not log backlog from jabber server.
 
-2007-06-03 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-03  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/gossip-ui-utils.c
        * libempathy-gtk/gossip-accounts-dialog.c
        * libempathy/gossip-paths.h: Remove unused code and append DATADIR to
        dirs where GTK should search icons.
 
-2007-06-03 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-03  Xavier Claessens  <xclaesse@gmail.com>
 
        * po/POTFILES.in:
        * po/POTFILES.skip: Add missing files that have strings for translation.
        Skip empathy-desktop.in.in. (Olivier Crete)
 
-2007-06-03 Xavier Claessens  <xclaesse@gmail.com>
+2007-06-03  Xavier Claessens  <xclaesse@gmail.com>
 
        * libempathy-gtk/gossip-group-chat.c:
        * libempathy-gtk/gossip-private-chat.c:
index c31afd82c1a114162e51ac2886b1052ec76ede90..49a09b7b83bcde882830a58673a3b346b15eb542 100644 (file)
@@ -155,62 +155,58 @@ AC_ARG_ENABLE(python,
                              [build python bindings to libempathy and libempathy-gtk]), ,
                              enable_python=auto)
 
-PKG_CHECK_MODULES(PYTHON_BINDING,
-[
-   pygtk-2.0,
-   glib-2.0 >= $GLIB_REQUIRED
-   gobject-2.0
-   gconf-2.0 >= $GCONF_REQUIRED
-   libxml-2.0
-   gnome-vfs-2.0
-   libtelepathy >= $TELEPATHY_REQUIRED
-   libmissioncontrol >= $MISSION_CONTROL_REQUIRED
-   gtk+-2.0 >= $GTK_REQUIRED
-   libglade-2.0 >= $LIBGLADE_REQUIRED
-   libgnomeui-2.0
-], have_python="yes", have_python="no")
-
-if test "x$have_python" = "xno"; then
-       if test "x$enable_python" = "xyes"; then
-               AC_MSG_ERROR([Could not find python dependencies])
-       fi
-       enable_python="no (missing dependencies)"
+if test "x$enable_python" != "xno"; then
+   AM_PATH_PYTHON
+   if test -z "$PYTHON" ; then
+      have_python="no"
+   else
+      PKG_CHECK_MODULES(PYTHON_BINDING,
+      [
+         pygtk-2.0,
+         glib-2.0 >= $GLIB_REQUIRED
+         gobject-2.0
+         gconf-2.0 >= $GCONF_REQUIRED
+         libxml-2.0
+         gnome-vfs-2.0
+         libtelepathy >= $TELEPATHY_REQUIRED
+         libmissioncontrol >= $MISSION_CONTROL_REQUIRED
+         gtk+-2.0 >= $GTK_REQUIRED
+         libglade-2.0 >= $LIBGLADE_REQUIRED
+         libgnomeui-2.0
+      ], have_python="yes", have_python="no")
+   fi
 else
-       if test "x$enable_python" != "xno"; then
-               AM_PATH_PYTHON
-               if test -z "$PYTHON" ; then
-                       enable_python="no"
-               else
-                       enable_python="yes"
-               fi
-       else
-               enable_python="no (disabled)"
-       fi
+   have_python=no
+fi
+
+if test "x$enable_python" = "xyes" -a "x$have_python" != "xyes"; then
+   AC_MSG_ERROR([Couldn't find python.])
 fi
-AM_CONDITIONAL(HAVE_PYTHON, test x$enable_python = xyes)
+
+AM_CONDITIONAL(HAVE_PYTHON, test "x$have_python" = "xyes")
 
 dnl -----------------------------------------------------------
 
 AC_OUTPUT([
-  Makefile
-  data/Makefile
-  data/empathy.desktop.in
-  data/16x16/Makefile
-  data/22x22/Makefile
-  data/24x24/Makefile
-  data/32x32/Makefile
-  data/48x48/Makefile
-  data/scalable/Makefile
-  po/Makefile.in
-  libempathy/Makefile
-  libempathy/libempathy.pc
-  libempathy-gtk/Makefile
-  libempathy-gtk/libempathy-gtk.pc
-  src/Makefile
-  doc/Makefile
-  doc/libempathy/Makefile
-  doc/libempathy-gtk/Makefile
-  python/Makefile
-  python/pyempathy/Makefile
-  python/pyempathygtk/Makefile
+   Makefile
+   data/Makefile
+   data/empathy.desktop.in
+   data/16x16/Makefile
+   data/22x22/Makefile
+   data/24x24/Makefile
+   data/32x32/Makefile
+   data/48x48/Makefile
+   data/scalable/Makefile
+   po/Makefile.in
+   libempathy/Makefile
+   libempathy/libempathy.pc
+   libempathy-gtk/Makefile
+   libempathy-gtk/libempathy-gtk.pc
+   src/Makefile
+   doc/Makefile
+   doc/libempathy/Makefile
+   doc/libempathy-gtk/Makefile
+   python/Makefile
+   python/pyempathy/Makefile
+   python/pyempathygtk/Makefile
 ])
index a4430da4971dc6ee9f643785f1d8b6f4c28864dc..cc74feef8e7809241e0947b6601588b0c672449d 100644 (file)
@@ -173,22 +173,3 @@ EmpathyContactListStore
 @Returns: 
 
 
-<!-- ##### FUNCTION empathy_contact_list_store_set_contact_groups_func ##### -->
-<para>
-
-</para>
-
-@store: 
-@func: 
-@user_data: 
-
-
-<!-- ##### FUNCTION empathy_contact_list_store_update_contact_groups ##### -->
-<para>
-
-</para>
-
-@store: 
-@contact: 
-
-
index ad7a1ff71d110a009f78c8ffe5ff95ad96bd17df..188033ebf619a5a4f2af9c006295fac3298c3b29 100644 (file)
@@ -39,23 +39,6 @@ EmpathyContactListView
 @arg2: 
 @arg3: 
 
-<!-- ##### ARG EmpathyContactListView:filter ##### -->
-<para>
-
-</para>
-
-<!-- ##### USER_FUNCTION EmpathyContactListViewDragReceivedFunc ##### -->
-<para>
-
-</para>
-
-@contact: 
-@action: 
-@old_group: 
-@new_group: 
-@user_data: 
-
-
 <!-- ##### FUNCTION empathy_contact_list_view_new ##### -->
 <para>
 
@@ -102,22 +85,3 @@ EmpathyContactListView
 @Returns: 
 
 
-<!-- ##### FUNCTION empathy_contact_list_view_set_filter ##### -->
-<para>
-
-</para>
-
-@view: 
-@filter: 
-
-
-<!-- ##### FUNCTION empathy_contact_list_view_set_drag_received_func ##### -->
-<para>
-
-</para>
-
-@view: 
-@func: 
-@user_data: 
-
-
index c55b21f1c85f7c0115a47b6edec10e9cf3ee308f..5b8c6541c5b262dd0314b81fb77190fd0ca71ca0 100644 (file)
@@ -59,13 +59,6 @@ empathy-images
 
 
 
-<!-- ##### MACRO EMPATHY_IMAGE_PENDING ##### -->
-<para>
-
-</para>
-
-
-
 <!-- ##### MACRO EMPATHY_IMAGE_MESSAGE ##### -->
 <para>
 
index d97f5b57b732cc9c077fae935406da47a1eeea04..0b7a7d27abb36058566e1c52a9833b68b6a307f3 100644 (file)
@@ -143,13 +143,6 @@ empathy-preferences
 
 
 
-<!-- ##### MACRO EMPATHY_PREFS_SALUT_ACCOUNT_CREATED ##### -->
-<para>
-
-</para>
-
-
-
 <!-- ##### FUNCTION empathy_preferences_show ##### -->
 <para>
 
index 0211e40b11748342a83279b5cab77137ac37e61f..15955d12b07c5659015dcf92a4cf96ec3ccc0940 100644 (file)
@@ -16,7 +16,7 @@
 #include <libempathy/empathy-message.h>
 #include <libempathy/empathy-tp-chatroom.h>
 
-empathy_avatar_get_gtype
+empathy_avatar_get_type
 empathy_chatroom_manager_get_type
 empathy_contact_manager_get_type
 empathy_idle_get_type
@@ -26,7 +26,7 @@ empathy_conf_get_type
 empathy_log_manager_get_type
 empathy_tp_group_get_type
 empathy_chandler_get_type
-empathy_contact_get_gtype
+empathy_contact_get_type
 empathy_tp_chat_get_type
 empathy_chatroom_get_type
 empathy_contact_list_get_type
index 44035517e0f1bbfc7685edcb87afa1dacefcf1e4..3f71285c866f67d754a10066559c4f0c59d9fdfe 100644 (file)
@@ -34,14 +34,6 @@ empathy-avatar
 @format: 
 @refcount: 
 
-<!-- ##### FUNCTION empathy_avatar_get_gtype ##### -->
-<para>
-
-</para>
-
-@Returns: 
-
-
 <!-- ##### FUNCTION empathy_avatar_new ##### -->
 <para>
 
index 1a2839fc761857643f03ba8154cec74c36c4cac3..a84646a8ea3bc083635af76b03c160d00ceb3f0d 100644 (file)
@@ -23,23 +23,29 @@ empathy-contact-list
 </para>
 
 
-<!-- ##### SIGNAL EmpathyContactList::contact-added ##### -->
+<!-- ##### SIGNAL EmpathyContactList::groups-changed ##### -->
 <para>
 
 </para>
 
 @empathycontactlist: the object which received the signal.
 @arg1: 
+@arg2: 
+@arg3: 
 
-<!-- ##### SIGNAL EmpathyContactList::contact-removed ##### -->
+<!-- ##### SIGNAL EmpathyContactList::members-changed ##### -->
 <para>
 
 </para>
 
 @empathycontactlist: the object which received the signal.
 @arg1: 
+@arg2: 
+@arg3: 
+@arg4: 
+@arg5: 
 
-<!-- ##### SIGNAL EmpathyContactList::local-pending ##### -->
+<!-- ##### SIGNAL EmpathyContactList::pendings-changed ##### -->
 <para>
 
 </para>
@@ -47,6 +53,9 @@ empathy-contact-list
 @empathycontactlist: the object which received the signal.
 @arg1: 
 @arg2: 
+@arg3: 
+@arg4: 
+@arg5: 
 
 <!-- ##### STRUCT EmpathyContactListIface ##### -->
 <para>
@@ -54,57 +63,15 @@ empathy-contact-list
 </para>
 
 @base_iface: 
-@setup: 
-@find: 
 @add: 
 @remove: 
 @get_members: 
-@get_local_pending: 
-@process_pending: 
-
-<!-- ##### STRUCT EmpathyContactListInfo ##### -->
-<para>
-
-</para>
-
-@contact: 
-@message: 
-
-<!-- ##### FUNCTION empathy_contact_list_info_new ##### -->
-<para>
-
-</para>
-
-@contact: 
-@message: 
-@Returns: 
-
-
-<!-- ##### FUNCTION empathy_contact_list_info_free ##### -->
-<para>
-
-</para>
-
-@info: 
-
-
-<!-- ##### FUNCTION empathy_contact_list_setup ##### -->
-<para>
-
-</para>
-
-@list: 
-
-
-<!-- ##### FUNCTION empathy_contact_list_find ##### -->
-<para>
-
-</para>
-
-@list: 
-@id: 
-@Returns: 
-
+@get_pendings: 
+@get_all_groups: 
+@get_groups: 
+@add_to_group: 
+@remove_from_group: 
+@rename_group: 
 
 <!-- ##### FUNCTION empathy_contact_list_add ##### -->
 <para>
@@ -135,22 +102,3 @@ empathy-contact-list
 @Returns: 
 
 
-<!-- ##### FUNCTION empathy_contact_list_get_local_pending ##### -->
-<para>
-
-</para>
-
-@list: 
-@Returns: 
-
-
-<!-- ##### FUNCTION empathy_contact_list_process_pending ##### -->
-<para>
-
-</para>
-
-@list: 
-@contact: 
-@accept: 
-
-
index 0defe4840fbc5159017eaec64fd25613d5cf088e..fe25eb7eb970c4c80f9959dde96ffe1aa0bba05d 100644 (file)
@@ -47,43 +47,3 @@ EmpathyContactManager
 @Returns: 
 
 
-<!-- ##### FUNCTION empathy_contact_manager_get_user ##### -->
-<para>
-
-</para>
-
-@manager: 
-@account: 
-@Returns: 
-
-
-<!-- ##### FUNCTION empathy_contact_manager_create ##### -->
-<para>
-
-</para>
-
-@manager: 
-@account: 
-@id: 
-@Returns: 
-
-
-<!-- ##### FUNCTION empathy_contact_manager_rename_group ##### -->
-<para>
-
-</para>
-
-@manager: 
-@old_group: 
-@new_group: 
-
-
-<!-- ##### FUNCTION empathy_contact_manager_get_groups ##### -->
-<para>
-
-</para>
-
-@manager: 
-@Returns: 
-
-
index 1ab2321afc3c22c3f13055940d53a280a4b985e2..861151fb6e920600419385ef8e5cf5e9f249982e 100644 (file)
@@ -33,11 +33,6 @@ EmpathyContact
 
 </para>
 
-<!-- ##### ARG EmpathyContact:groups ##### -->
-<para>
-
-</para>
-
 <!-- ##### ARG EmpathyContact:handle ##### -->
 <para>
 
@@ -63,29 +58,6 @@ EmpathyContact
 
 </para>
 
-<!-- ##### ARG EmpathyContact:subscription ##### -->
-<para>
-
-</para>
-
-<!-- ##### ENUM EmpathySubscription ##### -->
-<para>
-
-</para>
-
-@EMPATHY_SUBSCRIPTION_NONE: 
-@EMPATHY_SUBSCRIPTION_TO: 
-@EMPATHY_SUBSCRIPTION_FROM: 
-@EMPATHY_SUBSCRIPTION_BOTH: 
-
-<!-- ##### FUNCTION empathy_contact_get_gtype ##### -->
-<para>
-
-</para>
-
-@Returns: 
-
-
 <!-- ##### FUNCTION empathy_contact_new ##### -->
 <para>
 
@@ -151,24 +123,6 @@ EmpathyContact
 @Returns: 
 
 
-<!-- ##### FUNCTION empathy_contact_get_groups ##### -->
-<para>
-
-</para>
-
-@contact: 
-@Returns: 
-
-
-<!-- ##### FUNCTION empathy_contact_get_subscription ##### -->
-<para>
-
-</para>
-
-@contact: 
-@Returns: 
-
-
 <!-- ##### FUNCTION empathy_contact_get_handle ##### -->
 <para>
 
@@ -232,24 +186,6 @@ EmpathyContact
 @presence: 
 
 
-<!-- ##### FUNCTION empathy_contact_set_groups ##### -->
-<para>
-
-</para>
-
-@contact: 
-@categories: 
-
-
-<!-- ##### FUNCTION empathy_contact_set_subscription ##### -->
-<para>
-
-</para>
-
-@contact: 
-@subscription: 
-
-
 <!-- ##### FUNCTION empathy_contact_set_handle ##### -->
 <para>
 
@@ -268,24 +204,6 @@ EmpathyContact
 @is_user: 
 
 
-<!-- ##### FUNCTION empathy_contact_add_group ##### -->
-<para>
-
-</para>
-
-@contact: 
-@group: 
-
-
-<!-- ##### FUNCTION empathy_contact_remove_group ##### -->
-<para>
-
-</para>
-
-@contact: 
-@group: 
-
-
 <!-- ##### FUNCTION empathy_contact_is_online ##### -->
 <para>
 
@@ -295,16 +213,6 @@ EmpathyContact
 @Returns: 
 
 
-<!-- ##### FUNCTION empathy_contact_is_in_group ##### -->
-<para>
-
-</para>
-
-@contact: 
-@group: 
-@Returns: 
-
-
 <!-- ##### FUNCTION empathy_contact_get_status ##### -->
 <para>
 
index 3420151dbbbe4fe09049ffca0f2e5e1c1acc0f02..a3ff09ef1dafeb596d460ba51d1d64420e38ef6b 100644 (file)
@@ -54,61 +54,3 @@ EmpathyTpContactList
 @Returns: 
 
 
-<!-- ##### FUNCTION empathy_tp_contact_list_get_user ##### -->
-<para>
-
-</para>
-
-@list: 
-@Returns: 
-
-
-<!-- ##### FUNCTION empathy_tp_contact_list_get_from_id ##### -->
-<para>
-
-</para>
-
-@list: 
-@id: 
-@Returns: 
-
-
-<!-- ##### FUNCTION empathy_tp_contact_list_get_from_handle ##### -->
-<para>
-
-</para>
-
-@list: 
-@handle: 
-@Returns: 
-
-
-<!-- ##### FUNCTION empathy_tp_contact_list_get_from_handles ##### -->
-<para>
-
-</para>
-
-@list: 
-@handles: 
-@Returns: 
-
-
-<!-- ##### FUNCTION empathy_tp_contact_list_rename_group ##### -->
-<para>
-
-</para>
-
-@list: 
-@old_group: 
-@new_group: 
-
-
-<!-- ##### FUNCTION empathy_tp_contact_list_get_groups ##### -->
-<para>
-
-</para>
-
-@list: 
-@Returns: 
-
-
index 988b5d8f6b54a6c79a2959f53a820ae926b9bbd7..6ea6206e4193311f4a80755b42f939819a378a5d 100644 (file)
@@ -29,6 +29,13 @@ EmpathyTpGroup
 </para>
 
 
+<!-- ##### SIGNAL EmpathyTpGroup::destroy ##### -->
+<para>
+
+</para>
+
+@empathytpgroup: the object which received the signal.
+
 <!-- ##### SIGNAL EmpathyTpGroup::local-pending ##### -->
 <para>
 
@@ -40,7 +47,7 @@ EmpathyTpGroup
 @arg3: 
 @arg4: 
 
-<!-- ##### SIGNAL EmpathyTpGroup::members-added ##### -->
+<!-- ##### SIGNAL EmpathyTpGroup::member-added ##### -->
 <para>
 
 </para>
@@ -51,7 +58,7 @@ EmpathyTpGroup
 @arg3: 
 @arg4: 
 
-<!-- ##### SIGNAL EmpathyTpGroup::members-removed ##### -->
+<!-- ##### SIGNAL EmpathyTpGroup::member-removed ##### -->
 <para>
 
 </para>
@@ -73,16 +80,6 @@ EmpathyTpGroup
 @arg3: 
 @arg4: 
 
-<!-- ##### STRUCT EmpathyTpGroupInfo ##### -->
-<para>
-
-</para>
-
-@member: 
-@actor: 
-@reason: 
-@message: 
-
 <!-- ##### FUNCTION empathy_tp_group_new ##### -->
 <para>
 
@@ -99,7 +96,7 @@ EmpathyTpGroup
 </para>
 
 @group: 
-@handles: 
+@contacts: 
 @message: 
 
 
@@ -109,7 +106,7 @@ EmpathyTpGroup
 </para>
 
 @group: 
-@handle
+@contact
 @message: 
 
 
@@ -119,7 +116,7 @@ EmpathyTpGroup
 </para>
 
 @group: 
-@handle
+@contacts
 @message: 
 
 
@@ -129,7 +126,7 @@ EmpathyTpGroup
 </para>
 
 @group: 
-@handle
+@contact
 @message: 
 
 
@@ -142,34 +139,6 @@ EmpathyTpGroup
 @Returns: 
 
 
-<!-- ##### FUNCTION empathy_tp_group_get_all_members ##### -->
-<para>
-
-</para>
-
-@group: 
-@members: 
-@local_pending: 
-@remote_pending: 
-
-
-<!-- ##### FUNCTION empathy_tp_group_get_local_pending_members_with_info ##### -->
-<para>
-
-</para>
-
-@group: 
-@Returns: 
-
-
-<!-- ##### FUNCTION empathy_tp_group_info_list_free ##### -->
-<para>
-
-</para>
-
-@infos: 
-
-
 <!-- ##### FUNCTION empathy_tp_group_get_name ##### -->
 <para>
 
@@ -179,15 +148,6 @@ EmpathyTpGroup
 @Returns: 
 
 
-<!-- ##### FUNCTION empathy_tp_group_get_self_handle ##### -->
-<para>
-
-</para>
-
-@group: 
-@Returns: 
-
-
 <!-- ##### FUNCTION empathy_tp_group_get_object_path ##### -->
 <para>
 
@@ -203,7 +163,7 @@ EmpathyTpGroup
 </para>
 
 @group: 
-@handle
+@contact
 @Returns: 
 
 
index 7d48abf8ade5e55a253d6d8a0b43638747644d7e..c1df38b1503b192799e2970bb03481d57aeb3170 100644 (file)
@@ -34,7 +34,7 @@
 #include <glade/glade.h>
 #include <glib/gi18n.h>
 
-#include <libempathy/empathy-contact-manager.h>
+#include <libempathy/empathy-contact-factory.h>
 #include <libempathy/empathy-contact-list.h>
 #include <libempathy/empathy-log-manager.h>
 #include <libempathy/empathy-chatroom-manager.h>
@@ -823,17 +823,20 @@ chat_window_update_menu (EmpathyChatWindow *window)
                                                   window);
        } else {
                EmpathyPrivateChat  *chat;
-               EmpathySubscription  subscription;
                EmpathyContact      *contact;
+               EmpathyPresence     *presence;
 
                chat = EMPATHY_PRIVATE_CHAT (priv->current_chat);
 
                /* Show / Hide widgets */
                gtk_widget_hide (priv->menu_room);
 
+               /* presence==NULL means this contact refuses to send us his
+                * presence. By adding the contact we ask the contact to accept
+                * to send his presence. */
                contact = empathy_private_chat_get_contact (chat);
-               subscription = empathy_contact_get_subscription (contact);
-               if (!(subscription & EMPATHY_SUBSCRIPTION_FROM)) {
+               presence = empathy_contact_get_presence (contact);
+               if (!presence) {
                        gtk_widget_show (priv->menu_conv_add_contact);
                } else {
                        gtk_widget_hide (priv->menu_conv_add_contact);
@@ -1583,12 +1586,13 @@ chat_window_drag_data_received (GtkWidget        *widget,
 {
        /* FIXME: DnD of contact do not seems to work... */
        if (info == DND_DRAG_TYPE_CONTACT_ID) {
-               EmpathyContactManager *manager;
-               EmpathyContact         *contact;
-               EmpathyChat            *chat;
-               EmpathyChatWindow      *old_window;
+               EmpathyContactFactory *factory;
+               EmpathyContact        *contact = NULL;
+               EmpathyChat           *chat;
+               EmpathyChatWindow     *old_window;
                McAccount             *account;
                const gchar           *id = NULL;
+               gchar                **strv;
 
                if (selection) {
                        id = (const gchar*) selection->data;
@@ -1596,9 +1600,18 @@ chat_window_drag_data_received (GtkWidget        *widget,
 
                empathy_debug (DEBUG_DOMAIN, "DND contact from roster with id:'%s'", id);
                
-               manager = empathy_contact_manager_new ();
-               contact = empathy_contact_list_find (EMPATHY_CONTACT_LIST (manager), id);
-               g_object_unref (manager);
+               strv = g_strsplit (id, "/", 2);
+               factory = empathy_contact_factory_new ();
+               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_object_unref (account);
+               g_strfreev (strv);
 
                if (!contact) {
                        empathy_debug (DEBUG_DOMAIN, "DND contact from roster not found");
index 437e255fa80d0d01c236579216692082f6b0faae..553f85bcc4241ea7ca7f7d6e66504478a4943f1e 100644 (file)
@@ -42,7 +42,7 @@ static GtkWidget *new_contact_dialog = NULL;
 
 
 static gint
-contact_dialogs_find (GtkDialog     *dialog,
+contact_dialogs_find (GtkDialog      *dialog,
                      EmpathyContact *contact)
 {
        GtkWidget     *contact_widget;
@@ -64,18 +64,18 @@ subscription_dialog_response_cb (GtkDialog *dialog,
                                 GtkWidget *contact_widget)
 {
        EmpathyContactManager *manager;
-       EmpathyContact         *contact;
+       EmpathyContact        *contact;
 
        manager = empathy_contact_manager_new ();
        contact = empathy_contact_widget_get_contact (contact_widget);
 
        if (response == GTK_RESPONSE_YES) {
-               empathy_contact_list_process_pending (EMPATHY_CONTACT_LIST (manager),
-                                                     contact, TRUE);
+               empathy_contact_list_add (EMPATHY_CONTACT_LIST (manager),
+                                         contact, "");
        }
        else if (response == GTK_RESPONSE_NO) {
-               empathy_contact_list_process_pending (EMPATHY_CONTACT_LIST (manager),
-                                                     contact, FALSE);
+               empathy_contact_list_remove (EMPATHY_CONTACT_LIST (manager),
+                                            contact, "");
        }
 
        subscription_dialogs = g_list_remove (subscription_dialogs, dialog);
index ac2fa62cd3e70e4e60bd2275171df5b048602282..9cf03bfe853508ae51c9bf3d6d9bb5b4fb5d4259 100644 (file)
@@ -57,10 +57,10 @@ struct _EmpathyContactListStorePriv {
        gboolean                    show_avatars;
        gboolean                    is_compact;
        gboolean                    show_active;
-       EmpathyContactListStoreSort  sort_criterium;
+       EmpathyContactListStoreSort sort_criterium;
        guint                       inhibit_active;
 
-       EmpathyContactGroupsFunc     get_contact_groups;
+       EmpathyContactGroupsFunc    get_contact_groups;
        gpointer                    get_contact_groups_data;
 };
 
@@ -84,71 +84,74 @@ typedef struct {
 
 static void             empathy_contact_list_store_class_init         (EmpathyContactListStoreClass *klass);
 static void             empathy_contact_list_store_init               (EmpathyContactListStore      *list);
-static void             contact_list_store_finalize                  (GObject                     *object);
-static void             contact_list_store_get_property              (GObject                     *object,
-                                                                     guint                        param_id,
-                                                                     GValue                      *value,
-                                                                     GParamSpec                  *pspec);
-static void             contact_list_store_set_property              (GObject                     *object,
-                                                                     guint                        param_id,
-                                                                     const GValue                *value,
-                                                                     GParamSpec                  *pspec);
-static void             contact_list_store_setup                     (EmpathyContactListStore      *store);
-static gboolean         contact_list_store_inibit_active_cb          (EmpathyContactListStore      *store);
-static void             contact_list_store_contact_added_cb          (EmpathyContactList          *list_iface,
-                                                                     EmpathyContact               *contact,
-                                                                     EmpathyContactListStore      *store);
-static void             contact_list_store_add_contact               (EmpathyContactListStore      *store,
-                                                                     EmpathyContact               *contact);
-static void             contact_list_store_contact_removed_cb        (EmpathyContactList          *list_iface,
-                                                                     EmpathyContact               *contact,
-                                                                     EmpathyContactListStore      *store);
-static void             contact_list_store_remove_contact            (EmpathyContactListStore      *store,
-                                                                     EmpathyContact               *contact);
-static void             contact_list_store_contact_update            (EmpathyContactListStore      *store,
-                                                                     EmpathyContact               *contact);
-static void             contact_list_store_contact_groups_updated_cb (EmpathyContact               *contact,
-                                                                     GParamSpec                  *param,
-                                                                     EmpathyContactListStore      *store);
-static void             contact_list_store_contact_updated_cb        (EmpathyContact               *contact,
-                                                                     GParamSpec                  *param,
-                                                                     EmpathyContactListStore      *store);
-static void             contact_list_store_contact_set_active        (EmpathyContactListStore      *store,
-                                                                     EmpathyContact               *contact,
-                                                                     gboolean                     active,
-                                                                     gboolean                     set_changed);
-static ShowActiveData * contact_list_store_contact_active_new        (EmpathyContactListStore      *store,
-                                                                     EmpathyContact               *contact,
-                                                                     gboolean                     remove);
-static void             contact_list_store_contact_active_free       (ShowActiveData              *data);
-static gboolean         contact_list_store_contact_active_cb         (ShowActiveData              *data);
-static gboolean         contact_list_store_get_group_foreach         (GtkTreeModel                *model,
-                                                                     GtkTreePath                 *path,
-                                                                     GtkTreeIter                 *iter,
-                                                                     FindGroup                   *fg);
-static void             contact_list_store_get_group                 (EmpathyContactListStore      *store,
-                                                                     const gchar                 *name,
-                                                                     GtkTreeIter                 *iter_group_to_set,
-                                                                     GtkTreeIter                 *iter_separator_to_set,
-                                                                     gboolean                    *created);
-static gint             contact_list_store_state_sort_func           (GtkTreeModel                *model,
-                                                                     GtkTreeIter                 *iter_a,
-                                                                     GtkTreeIter                 *iter_b,
-                                                                     gpointer                     user_data);
-static gint             contact_list_store_name_sort_func            (GtkTreeModel                *model,
-                                                                     GtkTreeIter                 *iter_a,
-                                                                     GtkTreeIter                 *iter_b,
-                                                                     gpointer                     user_data);
-static gboolean         contact_list_store_find_contact_foreach      (GtkTreeModel                *model,
-                                                                     GtkTreePath                 *path,
-                                                                     GtkTreeIter                 *iter,
-                                                                     FindContact                 *fc);
-static GList *          contact_list_store_find_contact              (EmpathyContactListStore      *store,
-                                                                     EmpathyContact               *contact);
-static gboolean         contact_list_store_update_list_mode_foreach  (GtkTreeModel                *model,
-                                                                     GtkTreePath                 *path,
-                                                                     GtkTreeIter                 *iter,
-                                                                     EmpathyContactListStore      *store);
+static void             contact_list_store_finalize                  (GObject                       *object);
+static void             contact_list_store_get_property              (GObject                       *object,
+                                                                     guint                          param_id,
+                                                                     GValue                        *value,
+                                                                     GParamSpec                    *pspec);
+static void             contact_list_store_set_property              (GObject                       *object,
+                                                                     guint                          param_id,
+                                                                     const GValue                  *value,
+                                                                     GParamSpec                    *pspec);
+static void             contact_list_store_setup                     (EmpathyContactListStore       *store);
+static gboolean         contact_list_store_inibit_active_cb          (EmpathyContactListStore       *store);
+static void             contact_list_store_members_changed_cb        (EmpathyContactList            *list_iface,
+                                                                     EmpathyContact                *contact,
+                                                                     EmpathyContact                *actor,
+                                                                     guint                          reason,
+                                                                     gchar                         *message,
+                                                                     gboolean                       is_member,
+                                                                     EmpathyContactListStore       *store);
+static void             contact_list_store_groups_changed_cb         (EmpathyContactList            *list_iface,
+                                                                     EmpathyContact                *contact,
+                                                                     gchar                         *group,
+                                                                     gboolean                       is_member,
+                                                                     EmpathyContactListStore       *store);
+static void             contact_list_store_add_contact               (EmpathyContactListStore       *store,
+                                                                     EmpathyContact                *contact);
+static void             contact_list_store_remove_contact            (EmpathyContactListStore       *store,
+                                                                     EmpathyContact                *contact);
+static void             contact_list_store_contact_update            (EmpathyContactListStore       *store,
+                                                                     EmpathyContact                *contact);
+static void             contact_list_store_contact_updated_cb        (EmpathyContact                *contact,
+                                                                     GParamSpec                    *param,
+                                                                     EmpathyContactListStore       *store);
+static void             contact_list_store_contact_set_active        (EmpathyContactListStore       *store,
+                                                                     EmpathyContact                *contact,
+                                                                     gboolean                       active,
+                                                                     gboolean                       set_changed);
+static ShowActiveData * contact_list_store_contact_active_new        (EmpathyContactListStore       *store,
+                                                                     EmpathyContact                *contact,
+                                                                     gboolean                       remove);
+static void             contact_list_store_contact_active_free       (ShowActiveData                *data);
+static gboolean         contact_list_store_contact_active_cb         (ShowActiveData                *data);
+static gboolean         contact_list_store_get_group_foreach         (GtkTreeModel                  *model,
+                                                                     GtkTreePath                   *path,
+                                                                     GtkTreeIter                   *iter,
+                                                                     FindGroup                     *fg);
+static void             contact_list_store_get_group                 (EmpathyContactListStore       *store,
+                                                                     const gchar                   *name,
+                                                                     GtkTreeIter                   *iter_group_to_set,
+                                                                     GtkTreeIter                   *iter_separator_to_set,
+                                                                     gboolean                      *created);
+static gint             contact_list_store_state_sort_func           (GtkTreeModel                  *model,
+                                                                     GtkTreeIter                   *iter_a,
+                                                                     GtkTreeIter                   *iter_b,
+                                                                     gpointer                       user_data);
+static gint             contact_list_store_name_sort_func            (GtkTreeModel                  *model,
+                                                                     GtkTreeIter                   *iter_a,
+                                                                     GtkTreeIter                   *iter_b,
+                                                                     gpointer                       user_data);
+static gboolean         contact_list_store_find_contact_foreach      (GtkTreeModel                  *model,
+                                                                     GtkTreePath                   *path,
+                                                                     GtkTreeIter                   *iter,
+                                                                     FindContact                   *fc);
+static GList *          contact_list_store_find_contact              (EmpathyContactListStore       *store,
+                                                                     EmpathyContact                *contact);
+static gboolean         contact_list_store_update_list_mode_foreach  (GtkTreeModel                  *model,
+                                                                     GtkTreePath                   *path,
+                                                                     GtkTreeIter                   *iter,
+                                                                     EmpathyContactListStore       *store);
 
 enum {
        PROP_0,
@@ -317,24 +320,23 @@ empathy_contact_list_store_new (EmpathyContactList *list_iface)
 
        /* Signal connection. */
        g_signal_connect (priv->list,
-                         "contact-added",
-                         G_CALLBACK (contact_list_store_contact_added_cb),
+                         "members-changed",
+                         G_CALLBACK (contact_list_store_members_changed_cb),
                          store);
        g_signal_connect (priv->list,
-                         "contact-removed",
-                         G_CALLBACK (contact_list_store_contact_removed_cb),
+                         "groups-changed",
+                         G_CALLBACK (contact_list_store_groups_changed_cb),
                          store);
 
        /* Add contacts already created. */
        contacts = empathy_contact_list_get_members (priv->list);
        for (l = contacts; l; l = l->next) {
-               EmpathyContact *contact;
+               contact_list_store_members_changed_cb (priv->list, l->data,
+                                                      NULL, 0, NULL,
+                                                      TRUE,
+                                                      store);
 
-               contact = l->data;
-
-               contact_list_store_contact_added_cb (priv->list, contact, store);
-
-               g_object_unref (contact);
+               g_object_unref (l->data);
        }
        g_list_free (contacts);
 
@@ -385,13 +387,9 @@ empathy_contact_list_store_set_show_offline (EmpathyContactListStore *store,
 
        contacts = empathy_contact_list_get_members (priv->list);
        for (l = contacts; l; l = l->next) {
-               EmpathyContact *contact;
-
-               contact = EMPATHY_CONTACT (l->data);
-
-               contact_list_store_contact_update (store, contact);
+               contact_list_store_contact_update (store, l->data);
 
-               g_object_unref (contact);
+               g_object_unref (l->data);
        }
        g_list_free (contacts);
 
@@ -611,80 +609,6 @@ empathy_contact_list_store_search_equal_func (GtkTreeModel *model,
        return ret;
 }
 
-void
-empathy_contact_list_store_set_contact_groups_func (EmpathyContactListStore  *store,
-                                                  EmpathyContactGroupsFunc  func,
-                                                  gpointer                 user_data)
-{
-       EmpathyContactListStorePriv *priv;
-       GList                      *contacts, *l;
-
-       g_return_if_fail (EMPATHY_IS_CONTACT_LIST_STORE (store));
-
-       priv = GET_PRIV (store);
-
-       if (func) {
-               priv->get_contact_groups = func;
-               priv->get_contact_groups_data = user_data;
-       } else {
-               priv->get_contact_groups = NULL;
-               priv->get_contact_groups_data = NULL;
-       }
-
-       /* If we set a custom function to get contacts groups  we have to
-        * disconnect our default notify::groups signal and wait for the user
-        * to call himself empathy_contact_list_store_update_contact_groups ()
-        * when needed. If func is NULL we come back to default.
-        */
-       contacts = empathy_contact_list_get_members (priv->list);
-       for (l = contacts; l; l = l->next) {
-               EmpathyContact *contact;
-
-               contact = l->data;
-
-               if (func) {
-                       g_signal_handlers_disconnect_by_func (contact, 
-                                                             G_CALLBACK (contact_list_store_contact_groups_updated_cb),
-                                                             store);
-               } else {
-                       g_signal_connect (contact, "notify::groups",
-                                         G_CALLBACK (contact_list_store_contact_groups_updated_cb),
-                                         store);
-               }
-
-               empathy_contact_list_store_update_contact_groups (store, contact);
-
-               g_object_unref (contact);
-       }
-       g_list_free (contacts);
-}
-
-void
-empathy_contact_list_store_update_contact_groups (EmpathyContactListStore *store,
-                                                EmpathyContact          *contact)
-{
-       EmpathyContactListStorePriv *priv;
-       gboolean                    show_active;
-
-       g_return_if_fail (EMPATHY_IS_CONTACT_LIST_STORE (store));
-       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
-       priv = GET_PRIV (store);
-
-       empathy_debug (DEBUG_DOMAIN, "Contact:'%s' updating groups",
-                     empathy_contact_get_name (contact));
-
-       /* We do this to make sure the groups are correct, if not, we
-        * would have to check the groups already set up for each
-        * contact and then see what has been updated.
-        */
-       show_active = priv->show_active;
-       priv->show_active = FALSE;
-       contact_list_store_remove_contact (store, contact);
-       contact_list_store_add_contact (store, contact);
-       priv->show_active = show_active;
-}
-
 static void
 contact_list_store_setup (EmpathyContactListStore *store)
 {
@@ -733,37 +657,73 @@ contact_list_store_inibit_active_cb (EmpathyContactListStore *store)
 }
 
 static void
-contact_list_store_contact_added_cb (EmpathyContactList     *list_iface,
-                                    EmpathyContact          *contact,
-                                    EmpathyContactListStore *store)
+contact_list_store_members_changed_cb (EmpathyContactList      *list_iface,
+                                      EmpathyContact          *contact,
+                                      EmpathyContact          *actor,
+                                      guint                    reason,
+                                      gchar                   *message,
+                                      gboolean                 is_member,
+                                      EmpathyContactListStore *store)
 {
        EmpathyContactListStorePriv *priv;
 
        priv = GET_PRIV (store);
 
        empathy_debug (DEBUG_DOMAIN, 
-                     "Contact:'%s' added",
-                     empathy_contact_get_name (contact));
-
-       if (!priv->get_contact_groups) {
-               g_signal_connect (contact, "notify::groups",
-                                 G_CALLBACK (contact_list_store_contact_groups_updated_cb),
+                     "Contact %s (%d) %s",
+                     empathy_contact_get_id (contact),
+                     empathy_contact_get_handle (contact),
+                     is_member ? "added" : "removed");
+
+       if (is_member) {
+               g_signal_connect (contact, "notify::presence",
+                                 G_CALLBACK (contact_list_store_contact_updated_cb),
+                                 store);
+               g_signal_connect (contact, "notify::name",
+                                 G_CALLBACK (contact_list_store_contact_updated_cb),
                                  store);
+               g_signal_connect (contact, "notify::avatar",
+                                 G_CALLBACK (contact_list_store_contact_updated_cb),
+                                 store);
+               g_signal_connect (contact, "notify::type",
+                                 G_CALLBACK (contact_list_store_contact_updated_cb),
+                                 store);
+
+               contact_list_store_add_contact (store, contact);
+       } else {
+               g_signal_handlers_disconnect_by_func (contact,
+                                                     G_CALLBACK (contact_list_store_contact_updated_cb),
+                                                     store);
+
+               contact_list_store_remove_contact (store, contact);
        }
-       g_signal_connect (contact, "notify::presence",
-                         G_CALLBACK (contact_list_store_contact_updated_cb),
-                         store);
-       g_signal_connect (contact, "notify::name",
-                         G_CALLBACK (contact_list_store_contact_updated_cb),
-                         store);
-       g_signal_connect (contact, "notify::avatar",
-                         G_CALLBACK (contact_list_store_contact_updated_cb),
-                         store);
-       g_signal_connect (contact, "notify::type",
-                         G_CALLBACK (contact_list_store_contact_updated_cb),
-                         store);
+}
 
+static void
+contact_list_store_groups_changed_cb (EmpathyContactList      *list_iface,
+                                     EmpathyContact          *contact,
+                                     gchar                   *group,
+                                     gboolean                 is_member,
+                                     EmpathyContactListStore *store)
+{
+       EmpathyContactListStorePriv *priv;
+       gboolean                     show_active;
+
+       priv = GET_PRIV (store);
+
+       empathy_debug (DEBUG_DOMAIN, "Updating groups for contact %s (%d)",
+                     empathy_contact_get_id (contact),
+                     empathy_contact_get_handle (contact));
+
+       /* We do this to make sure the groups are correct, if not, we
+        * would have to check the groups already set up for each
+        * contact and then see what has been updated.
+        */
+       show_active = priv->show_active;
+       priv->show_active = FALSE;
+       contact_list_store_remove_contact (store, contact);
        contact_list_store_add_contact (store, contact);
+       priv->show_active = show_active;
 }
 
 static void
@@ -780,14 +740,9 @@ contact_list_store_add_contact (EmpathyContactListStore *store,
                return;
        }
 
-       /* If no groups just add it at the top level. */
-       if (priv->get_contact_groups) {
-               groups = priv->get_contact_groups (contact,
-                                                  priv->get_contact_groups_data);
-       } else {
-               groups = empathy_contact_get_groups (contact);
-       }
+       groups = empathy_contact_list_get_groups (priv->list, contact);
 
+       /* If no groups just add it at the top level. */
        if (!groups) {
                gtk_tree_store_append (GTK_TREE_STORE (store), &iter, NULL);
                gtk_tree_store_set (GTK_TREE_STORE (store), &iter,
@@ -800,15 +755,9 @@ contact_list_store_add_contact (EmpathyContactListStore *store,
 
        /* Else add to each group. */
        for (l = groups; l; l = l->next) {
-               GtkTreeIter  iter_group;
-               const gchar *name;
-
-               name = l->data;
-               if (!name) {
-                       continue;
-               }
+               GtkTreeIter iter_group;
 
-               contact_list_store_get_group (store, name, &iter_group, NULL, NULL);
+               contact_list_store_get_group (store, l->data, &iter_group, NULL, NULL);
 
                gtk_tree_store_insert_after (GTK_TREE_STORE (store), &iter,
                                             &iter_group, NULL);
@@ -818,28 +767,12 @@ contact_list_store_add_contact (EmpathyContactListStore *store,
                                    COL_IS_GROUP, FALSE,
                                    COL_IS_SEPARATOR, FALSE,
                                    -1);
+               g_free (l->data);
        }
+       g_list_free (groups);
 
        contact_list_store_contact_update (store, contact);
-}
-
-static void
-contact_list_store_contact_removed_cb (EmpathyContactList     *list_iface,
-                                      EmpathyContact          *contact,
-                                      EmpathyContactListStore *store)
-{
-       empathy_debug (DEBUG_DOMAIN, "Contact:'%s' removed",
-                     empathy_contact_get_name (contact));
-
-       /* Disconnect signals */
-       g_signal_handlers_disconnect_by_func (contact, 
-                                             G_CALLBACK (contact_list_store_contact_groups_updated_cb),
-                                             store);
-       g_signal_handlers_disconnect_by_func (contact,
-                                             G_CALLBACK (contact_list_store_contact_updated_cb),
-                                             store);
 
-       contact_list_store_remove_contact (store, contact);
 }
 
 static void
@@ -1028,17 +961,9 @@ contact_list_store_contact_update (EmpathyContactListStore *store,
        g_list_free (iters);
 }
 
-static void
-contact_list_store_contact_groups_updated_cb (EmpathyContact          *contact,
-                                             GParamSpec             *param,
-                                             EmpathyContactListStore *store)
-{
-       empathy_contact_list_store_update_contact_groups (store, contact);
-}
-
 static void
 contact_list_store_contact_updated_cb (EmpathyContact          *contact,
-                                      GParamSpec             *param,
+                                      GParamSpec              *param,
                                       EmpathyContactListStore *store)
 {
        empathy_debug (DEBUG_DOMAIN,
@@ -1180,10 +1105,10 @@ contact_list_store_get_group (EmpathyContactListStore *store,
                              gboolean               *created)
 {
        EmpathyContactListStorePriv *priv;
-       GtkTreeModel               *model;
-       GtkTreeIter                 iter_group;
-       GtkTreeIter                 iter_separator;
-       FindGroup                   fg;
+       GtkTreeModel                *model;
+       GtkTreeIter                  iter_group;
+       GtkTreeIter                  iter_separator;
+       FindGroup                    fg;
 
        priv = GET_PRIV (store);
 
index d7c9635f5bf2c51440a86bf739b2c1bd6d37a1e8..d096daafd1d8d313a032ff71ba161b38788123f4 100644 (file)
@@ -106,11 +106,6 @@ gboolean                   empathy_contact_list_store_search_equal_func  (GtkTre
                                                                         const gchar                *key,
                                                                         GtkTreeIter                *iter,
                                                                         gpointer                    search_data);
-void                       empathy_contact_list_store_set_contact_groups_func (EmpathyContactListStore*store,
-                                                                        EmpathyContactGroupsFunc     func,
-                                                                        gpointer                    user_data);
-void                       empathy_contact_list_store_update_contact_groups (EmpathyContactListStore  *store,
-                                                                        EmpathyContact              *contact);
 
 G_END_DECLS
 
index 2a5cf3406c107d24edea38045ccbda31e2094cef..5b3f0de08283ff09512fdd5b6b0adb013de86592 100644 (file)
@@ -34,7 +34,7 @@
 #include <libmissioncontrol/mc-account.h>
 #include <libmissioncontrol/mission-control.h>
 
-#include <libempathy/empathy-contact-manager.h>
+#include <libempathy/empathy-contact-factory.h>
 #include <libempathy/empathy-contact-list.h>
 #include <libempathy/empathy-log-manager.h>
 #include <libempathy/empathy-debug.h>
 
 struct _EmpathyContactListViewPriv {
        EmpathyContactListStore *store;
-       GtkUIManager           *ui;
-       GtkTreeRowReference    *drag_row;
-       GtkTreeModel           *filter;
-       gchar                  *filter_text;
-
-       EmpathyContactListViewDragReceivedFunc drag_received;
-       gpointer                              drag_received_data;
+       GtkUIManager            *ui;
+       GtkTreeRowReference     *drag_row;
 };
 
 typedef struct {
@@ -103,11 +98,6 @@ static void        contact_list_view_row_has_child_toggled_cb  (GtkTreeModel
                                                                GtkTreePath                *path,
                                                                GtkTreeIter                *iter,
                                                                EmpathyContactListView      *view);
-static void        contact_list_view_contact_received          (EmpathyContactListView      *view,
-                                                               EmpathyContact              *contact,
-                                                               GdkDragAction               action,
-                                                               const gchar                *old_group,
-                                                               const gchar                *new_group);
 static void        contact_list_view_drag_data_received        (GtkWidget                  *widget,
                                                                GdkDragContext             *context,
                                                                gint                        x,
@@ -173,14 +163,6 @@ static void        contact_list_view_row_expand_or_collapse_cb (EmpathyContactLi
                                                                GtkTreeIter                *iter,
                                                                GtkTreePath                *path,
                                                                gpointer                    user_data);
-static gboolean    contact_list_view_filter_show_contact       (EmpathyContact              *contact,
-                                                               const gchar                *filter);
-static gboolean    contact_list_view_filter_show_group         (EmpathyContactListView      *view,
-                                                               const gchar                *group,
-                                                               const gchar                *filter);
-static gboolean    contact_list_view_filter_func               (GtkTreeModel               *model,
-                                                               GtkTreeIter                *iter,
-                                                               EmpathyContactListView      *view);
 static void        contact_list_view_action_cb                 (GtkAction                  *action,
                                                                EmpathyContactListView      *view);
 static void        contact_list_view_action_activated          (EmpathyContactListView      *view,
@@ -188,7 +170,6 @@ static void        contact_list_view_action_activated          (EmpathyContactLi
 
 enum {
        PROP_0,
-       PROP_FILTER,
 };
 
 static const GtkActionEntry entries[] = {
@@ -315,14 +296,6 @@ empathy_contact_list_view_class_init (EmpathyContactListViewClass *klass)
                              G_TYPE_NONE,
                              3, EMPATHY_TYPE_CONTACT, G_TYPE_STRING, G_TYPE_STRING);
 
-       g_object_class_install_property (object_class,
-                                        PROP_FILTER,
-                                        g_param_spec_string ("filter",
-                                                             "Filter",
-                                                             "The text to use to filter the contact list",
-                                                             NULL,
-                                                             G_PARAM_READWRITE));
-
        g_type_class_add_private (object_class, sizeof (EmpathyContactListViewPriv));
 }
 
@@ -389,10 +362,6 @@ contact_list_view_finalize (GObject *object)
        if (priv->store) {
                g_object_unref (priv->store);
        }
-       if (priv->filter) {
-               g_object_unref (priv->filter);
-       }
-       g_free (priv->filter_text);
 
        G_OBJECT_CLASS (empathy_contact_list_view_parent_class)->finalize (object);
 }
@@ -408,9 +377,6 @@ contact_list_view_get_property (GObject    *object,
        priv = GET_PRIV (object);
 
        switch (param_id) {
-       case PROP_FILTER:
-               g_value_set_string (value, priv->filter_text);
-               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
                break;
@@ -428,10 +394,6 @@ contact_list_view_set_property (GObject      *object,
        priv = GET_PRIV (object);
 
        switch (param_id) {
-       case PROP_FILTER:
-               empathy_contact_list_view_set_filter (EMPATHY_CONTACT_LIST_VIEW (object),
-                                               g_value_get_string (value));
-               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
                break;
@@ -547,47 +509,6 @@ empathy_contact_list_view_get_contact_menu (EmpathyContactListView *view,
                                                   can_show_log);
 }
 
-void
-empathy_contact_list_view_set_filter (EmpathyContactListView *view,
-                                    const gchar           *filter)
-{
-       EmpathyContactListViewPriv *priv;
-
-       g_return_if_fail (EMPATHY_IS_CONTACT_LIST_VIEW (view));
-
-       priv = GET_PRIV (view);
-
-       g_free (priv->filter_text);
-       if (filter) {
-               priv->filter_text = g_utf8_casefold (filter, -1);
-       } else {
-               priv->filter_text = NULL;
-       }
-
-       empathy_debug (DEBUG_DOMAIN, "Refiltering with filter:'%s' (case folded)", filter);
-       gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
-}
-
-void
-empathy_contact_list_view_set_drag_received_func (EmpathyContactListView                 *view,
-                                                EmpathyContactListViewDragReceivedFunc  func,
-                                                gpointer                               user_data)
-{
-       EmpathyContactListViewPriv *priv;
-
-       g_return_if_fail (EMPATHY_IS_CONTACT_LIST_VIEW (view));
-
-       priv = GET_PRIV (view);
-
-       if (func) {
-               priv->drag_received = func;
-               priv->drag_received_data = user_data;
-       } else {
-               priv->drag_received = NULL;
-               priv->drag_received_data = NULL;
-       }
-}
-
 static void
 contact_list_view_setup (EmpathyContactListView *view)
 {
@@ -598,21 +519,11 @@ contact_list_view_setup (EmpathyContactListView *view)
 
        priv = GET_PRIV (view);
 
-       /* Create filter */
-       priv->filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (priv->store), NULL);
-
-       gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (priv->filter),
-                                               (GtkTreeModelFilterVisibleFunc)
-                                               contact_list_view_filter_func,
-                                               view, NULL);
-       gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (view),
-                                            empathy_contact_list_store_search_equal_func,
-                                            view, NULL);
-       g_signal_connect (priv->filter, "row-has-child-toggled",
+       g_signal_connect (priv->store, "row-has-child-toggled",
                          G_CALLBACK (contact_list_view_row_has_child_toggled_cb),
                          view);
-       gtk_tree_view_set_model (GTK_TREE_VIEW (view), priv->filter);
-
+       gtk_tree_view_set_model (GTK_TREE_VIEW (view),
+                                GTK_TREE_MODEL (priv->store));
 
        /* Setup view */
        g_object_set (view,
@@ -697,13 +608,13 @@ contact_list_view_setup (EmpathyContactListView *view)
                             GDK_BUTTON1_MASK,
                             drag_types_source,
                             G_N_ELEMENTS (drag_types_source),
-                            GDK_ACTION_MOVE);
+                            GDK_ACTION_MOVE | GDK_ACTION_COPY);
 
        gtk_drag_dest_set (GTK_WIDGET (view),
                           GTK_DEST_DEFAULT_ALL,
                           drag_types_dest,
                           G_N_ELEMENTS (drag_types_dest),
-                          GDK_ACTION_MOVE | GDK_ACTION_LINK);
+                          GDK_ACTION_MOVE | GDK_ACTION_COPY);
 }
 
 static void
@@ -746,46 +657,6 @@ contact_list_view_row_has_child_toggled_cb (GtkTreeModel          *model,
        g_free (name);
 }
 
-static void
-contact_list_view_contact_received (EmpathyContactListView *view,
-                                   EmpathyContact         *contact,
-                                   GdkDragAction          action,
-                                   const gchar           *old_group,
-                                   const gchar           *new_group)
-{
-       EmpathyContactListViewPriv *priv;
-       GList                     *groups, *l;
-       GList                     *new_groups_list = NULL;
-
-       priv = GET_PRIV (view);
-
-       groups = empathy_contact_get_groups (contact);
-       for (l = groups; l; l = l->next) {
-               gchar *str;
-
-               str = l->data;
-
-               if (action == GDK_ACTION_MOVE &&
-                   old_group != NULL &&
-                   strcmp (str, old_group) == 0) {
-                       continue;
-               }
-
-               if (new_group && strcmp (str, new_group) == 0) {
-                       /* Otherwise we set it twice */
-                       continue;
-               }
-
-               new_groups_list = g_list_prepend (new_groups_list, g_strdup (str));
-       }
-
-       if (new_group) {
-               new_groups_list = g_list_prepend (new_groups_list, g_strdup (new_group));
-       }
-
-       empathy_contact_set_groups (contact, new_groups_list);
-}
-
 static void
 contact_list_view_drag_data_received (GtkWidget         *widget,
                                      GdkDragContext    *context,
@@ -796,15 +667,18 @@ contact_list_view_drag_data_received (GtkWidget         *widget,
                                      guint              time)
 {
        EmpathyContactListViewPriv *priv;
-       EmpathyContactList        *list;
-       GtkTreeModel              *model;
-       GtkTreePath               *path;
-       GtkTreeViewDropPosition    position;
-       EmpathyContact             *contact;
-       const gchar               *id;
-       gchar                     *new_group = NULL;
-       gchar                     *old_group = NULL;
-       gboolean                   is_row;
+       EmpathyContactList         *list;
+       EmpathyContactFactory      *factory;
+       McAccount                  *account;
+       GtkTreeModel               *model;
+       GtkTreePath                *path;
+       GtkTreeViewDropPosition     position;
+       EmpathyContact             *contact = NULL;
+       const gchar                *id;
+       gchar                     **strv;
+       gchar                      *new_group = NULL;
+       gchar                      *old_group = NULL;
+       gboolean                    is_row;
 
        priv = GET_PRIV (widget);
 
@@ -814,9 +688,18 @@ contact_list_view_drag_data_received (GtkWidget         *widget,
                      context->action == GDK_ACTION_COPY ? "copy" : "",
                      id);
 
-       /* FIXME: This is ambigous, an id can come from multiple accounts */
-       list = empathy_contact_list_store_get_list_iface (priv->store);
-       contact = empathy_contact_list_find (list, id);
+       strv = g_strsplit (id, "/", 2);
+       factory = empathy_contact_factory_new ();
+       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_object_unref (account);
+       g_strfreev (strv);
 
        if (!contact) {
                empathy_debug (DEBUG_DOMAIN, "No contact found associated with drag & drop");
@@ -847,22 +730,17 @@ contact_list_view_drag_data_received (GtkWidget         *widget,
        }
 
        empathy_debug (DEBUG_DOMAIN,
-                     "contact '%s' dragged from '%s' to '%s'",
-                     empathy_contact_get_name (contact),
+                     "contact %s (%d) dragged from '%s' to '%s'",
+                     empathy_contact_get_id (contact),
+                     empathy_contact_get_handle (contact),
                      old_group, new_group);
 
-       if (priv->drag_received) {
-               priv->drag_received (contact,
-                                    context->action,
-                                    old_group,
-                                    new_group,
-                                    priv->drag_received_data);
-       } else {
-               contact_list_view_contact_received (EMPATHY_CONTACT_LIST_VIEW (widget),
-                                                   contact,
-                                                   context->action,
-                                                   old_group,
-                                                   new_group);
+       list = empathy_contact_list_store_get_list_iface (priv->store);
+       if (new_group) {
+               empathy_contact_list_add_to_group (list, contact, new_group);
+       }
+       if (old_group && context->action == GDK_ACTION_MOVE) {  
+               empathy_contact_list_remove_from_group (list, contact, old_group);
        }
 
        g_free (old_group);
@@ -976,11 +854,15 @@ contact_list_view_drag_data_get (GtkWidget        *widget,
                                 guint             time)
 {
        EmpathyContactListViewPriv *priv;
-       GtkTreePath               *src_path;
-       GtkTreeIter                iter;
-       GtkTreeModel              *model;
+       GtkTreePath                *src_path;
+       GtkTreeIter                 iter;
+       GtkTreeModel               *model;
        EmpathyContact             *contact;
-       const gchar               *id;
+       McAccount                  *account;
+       const gchar                *contact_id;
+       const gchar                *account_id;
+       gchar                      *str;
+       
 
        priv = GET_PRIV (widget);
 
@@ -1006,18 +888,20 @@ contact_list_view_drag_data_get (GtkWidget        *widget,
                return;
        }
 
-       id = empathy_contact_get_id (contact);
+       account = empathy_contact_get_account (contact);
+       account_id = mc_account_get_unique_name (account);
+       contact_id = empathy_contact_get_id (contact);
        g_object_unref (contact);
+       str = g_strconcat (account_id, "/", contact_id, NULL);
 
        switch (info) {
        case DND_DRAG_TYPE_CONTACT_ID:
                gtk_selection_data_set (selection, drag_atoms_source[info], 8,
-                                       (guchar*)id, strlen (id) + 1);
+                                       (guchar*)str, strlen (str) + 1);
                break;
-
-       default:
-               return;
        }
+
+       g_free (str);
 }
 
 static void
@@ -1329,124 +1213,6 @@ contact_list_view_row_expand_or_collapse_cb (EmpathyContactListView *view,
        g_free (name);
 }
 
-static gboolean 
-contact_list_view_filter_show_contact (EmpathyContact *contact,
-                                      const gchar   *filter)
-{
-       gchar    *str;
-       gboolean  visible;
-
-       /* Check contact id */
-       str = g_utf8_casefold (empathy_contact_get_id (contact), -1);
-       visible = G_STR_EMPTY (str) || strstr (str, filter);
-       g_free (str);
-
-       if (visible) {
-               return TRUE;
-       }
-
-       /* Check contact name */
-       str = g_utf8_casefold (empathy_contact_get_name (contact), -1);
-       visible = G_STR_EMPTY (str) || strstr (str, filter);
-       g_free (str);
-       
-       return visible;
-}
-
-static gboolean
-contact_list_view_filter_show_group (EmpathyContactListView *view,
-                                    const gchar           *group,
-                                    const gchar           *filter)
-{
-       EmpathyContactListViewPriv *priv;
-       EmpathyContactList        *list;
-       GList                     *contacts, *l;
-       gchar                     *str;
-       gboolean                   show_group = FALSE;
-
-       priv = GET_PRIV (view);
-       
-       str = g_utf8_casefold (group, -1);
-       if (!str) {
-               return FALSE;
-       }
-
-       /* If the filter is the partially the group name, we show the
-        * whole group.
-        */
-       if (strstr (str, filter)) {
-               g_free (str);
-               return TRUE;
-       }
-
-       /* At this point, we need to check in advance if this
-        * group should be shown because a contact we want to
-        * show exists in it.
-        */
-       list = empathy_contact_list_store_get_list_iface (priv->store);
-       contacts = empathy_contact_list_get_members (list);
-       for (l = contacts; l && !show_group; l = l->next) {
-               if (!empathy_contact_is_in_group (l->data, group)) {
-                       g_object_unref (l->data);
-                       continue;
-               }
-
-               if (contact_list_view_filter_show_contact (l->data, filter)) {
-                       show_group = TRUE;
-               }
-               g_object_unref (l->data);
-       }
-       g_list_free (contacts);
-       g_free (str);
-
-       return show_group;
-}
-
-static gboolean
-contact_list_view_filter_func (GtkTreeModel          *model,
-                              GtkTreeIter           *iter,
-                              EmpathyContactListView *view)
-{
-       EmpathyContactListViewPriv *priv;
-       gboolean                   is_group;
-       gboolean                   is_separator;
-       gboolean                   visible = TRUE;
-
-       priv = GET_PRIV (view);
-
-       if (G_STR_EMPTY (priv->filter_text)) {
-               return TRUE;
-       }
-       
-       /* Check to see if iter matches any group names */
-       gtk_tree_model_get (model, iter,
-                           COL_IS_GROUP, &is_group,
-                           COL_IS_SEPARATOR, &is_separator,
-                           -1);
-
-       if (is_group) {
-               gchar *name;
-
-               gtk_tree_model_get (model, iter, COL_NAME, &name, -1);
-               visible &= contact_list_view_filter_show_group (view,
-                                                               name,
-                                                               priv->filter_text);
-               g_free (name);
-       } else if (is_separator) {
-               /* Do nothing here */
-       } else {
-               EmpathyContact *contact;
-
-               /* Check contact id */
-               gtk_tree_model_get (model, iter, COL_CONTACT, &contact, -1);
-               visible &= contact_list_view_filter_show_contact (contact, 
-                                                                 priv->filter_text);
-               g_object_unref (contact);
-       }
-
-       return visible;
-}
-
 static void
 contact_list_view_action_cb (GtkAction             *action,
                             EmpathyContactListView *view)
index 4d7cf1cb9ed956046224fcbb6d8a6e732f6d6197..b9de24357229cf6992c1df88f735f52eb20fc751 100644 (file)
@@ -53,24 +53,13 @@ struct _EmpathyContactListViewClass {
        GtkTreeViewClass       parent_class;
 };
 
-typedef void           (*EmpathyContactListViewDragReceivedFunc)        (EmpathyContact *contact,
-                                                                       GdkDragAction  action,
-                                                                       const gchar   *old_group,
-                                                                       const gchar   *new_group,
-                                                                       gpointer       user_data);
-
-GType                  empathy_contact_list_view_get_type               (void) G_GNUC_CONST;
-EmpathyContactListView *empathy_contact_list_view_new                    (EmpathyContactListStore                *store);
-EmpathyContact *        empathy_contact_list_view_get_selected           (EmpathyContactListView                 *view);
-gchar *                empathy_contact_list_view_get_selected_group     (EmpathyContactListView                 *view);
-GtkWidget *            empathy_contact_list_view_get_contact_menu       (EmpathyContactListView                 *view,
-                                                                       EmpathyContact                         *contact);
-GtkWidget *            empathy_contact_list_view_get_group_menu         (EmpathyContactListView                 *view);
-void                   empathy_contact_list_view_set_filter             (EmpathyContactListView                 *view,
-                                                                       const gchar                           *filter);
-void                   empathy_contact_list_view_set_drag_received_func (EmpathyContactListView                 *view,
-                                                                       EmpathyContactListViewDragReceivedFunc  func,
-                                                                       gpointer                               user_data);
+GType                   empathy_contact_list_view_get_type           (void) G_GNUC_CONST;
+EmpathyContactListView *empathy_contact_list_view_new                (EmpathyContactListStore *store);
+EmpathyContact *        empathy_contact_list_view_get_selected       (EmpathyContactListView  *view);
+gchar *                 empathy_contact_list_view_get_selected_group (EmpathyContactListView  *view);
+GtkWidget *             empathy_contact_list_view_get_contact_menu   (EmpathyContactListView  *view,
+                                                                     EmpathyContact          *contact);
+GtkWidget *             empathy_contact_list_view_get_group_menu     (EmpathyContactListView  *view);
 
 G_END_DECLS
 
index 5c8f6d3d881554fdbba6360d9882240ee3d3694a..b3081b13098d065668751d9d48ef1e20ee4e1e85 100644 (file)
@@ -31,7 +31,9 @@
 
 #include <libmissioncontrol/mc-account.h>
 
+#include <libempathy/empathy-contact-factory.h>
 #include <libempathy/empathy-contact-manager.h>
+#include <libempathy/empathy-contact-list.h>
 #include <libempathy/empathy-utils.h>
 
 #include "empathy-contact-widget.h"
 #define ID_CHANGED_TIMEOUT 500
 
 typedef struct {
-       EmpathyContact  *contact;
-       gboolean         is_user;
-       EmpathyContactWidgetType type;
-       GtkCellRenderer *renderer;
-       guint            widget_id_timeout;
+       EmpathyContactFactory    *factory;
+       EmpathyContactManager    *manager;
+       EmpathyContact           *contact;
+       gboolean                  is_user;
+       EmpathyContactWidgetType  type;
+       GtkCellRenderer          *renderer;
+       guint                     widget_id_timeout;
 
-       GtkWidget       *vbox_contact_widget;
+       GtkWidget                *vbox_contact_widget;
 
        /* Contact */
-       GtkWidget       *vbox_contact;
-       GtkWidget       *widget_avatar;
-       GtkWidget       *widget_account;
-       GtkWidget       *widget_id;
-       GtkWidget       *widget_alias;
-       GtkWidget       *label_alias;
-       GtkWidget       *entry_alias;
-       GtkWidget       *hbox_presence;
-       GtkWidget       *image_state;
-       GtkWidget       *label_status;
-       GtkWidget       *table_contact;
-       GtkWidget       *hbox_contact;
+       GtkWidget                *vbox_contact;
+       GtkWidget                *widget_avatar;
+       GtkWidget                *widget_account;
+       GtkWidget                *widget_id;
+       GtkWidget                *widget_alias;
+       GtkWidget                *label_alias;
+       GtkWidget                *entry_alias;
+       GtkWidget                *hbox_presence;
+       GtkWidget                *image_state;
+       GtkWidget                *label_status;
+       GtkWidget                *table_contact;
+       GtkWidget                *hbox_contact;
 
        /* Groups */
-       GtkWidget       *vbox_groups;
-       GtkWidget       *entry_group;
-       GtkWidget       *button_group;
-       GtkWidget       *treeview_groups;
+       GtkWidget                *vbox_groups;
+       GtkWidget                *entry_group;
+       GtkWidget                *button_group;
+       GtkWidget                *treeview_groups;
 
        /* Details */
-       GtkWidget       *vbox_details;
-       GtkWidget       *table_details;
-       GtkWidget       *hbox_details_requested;
+       GtkWidget                *vbox_details;
+       GtkWidget                *table_details;
+       GtkWidget                *hbox_details_requested;
 
        /* Client */
-       GtkWidget       *vbox_client;
-       GtkWidget       *table_client;
-       GtkWidget       *hbow_client_requested;
-
+       GtkWidget                *vbox_client;
+       GtkWidget                *table_client;
+       GtkWidget                *hbow_client_requested;
 } EmpathyContactWidget;
 
 typedef struct {
@@ -151,6 +154,7 @@ empathy_contact_widget_new (EmpathyContact           *contact,
 
        information = g_slice_new0 (EmpathyContactWidget);
        information->type = type;
+       information->factory = empathy_contact_factory_new ();
        if (contact) {
                information->is_user = empathy_contact_is_user (contact);
        } else {
@@ -231,6 +235,12 @@ contact_widget_destroy_cb (GtkWidget            *widget,
        if (information->widget_id_timeout != 0) {
                g_source_remove (information->widget_id_timeout);
        }
+       if (information->factory) {
+               g_object_unref (information->factory);
+       }               
+       if (information->manager) {
+               g_object_unref (information->manager);
+       }               
 
        g_slice_free (EmpathyContactWidget, information);
 }
@@ -467,17 +477,15 @@ contact_widget_update_contact (EmpathyContactWidget *information)
        id = gtk_entry_get_text (GTK_ENTRY (information->widget_id));
 
        if (account && !G_STR_EMPTY (id)) {
-               EmpathyContactManager *manager;
-               EmpathyContact         *contact;
+               EmpathyContact *contact;
 
-               manager = empathy_contact_manager_new ();
-               contact = empathy_contact_manager_create (manager, account, id);
+               contact = empathy_contact_factory_get_from_id (information->factory,
+                                                              account, id);
                contact_widget_set_contact (information, contact);
 
                if (contact) {
                        g_object_unref (contact);
                }
-               g_object_unref (manager);
        }
 
        return FALSE;
@@ -508,7 +516,9 @@ contact_widget_entry_alias_focus_event_cb (GtkEditable          *editable,
                const gchar *name;
 
                name = gtk_entry_get_text (GTK_ENTRY (editable));
-               empathy_contact_set_name (information->contact, name);
+               empathy_contact_factory_set_name (information->factory,
+                                                 information->contact,
+                                                 name);
        }
 
        return FALSE;
@@ -559,6 +569,7 @@ static void
 contact_widget_groups_setup (EmpathyContactWidget *information)
 {
        if (information->type > CONTACT_WIDGET_TYPE_SHOW) {
+               information->manager = empathy_contact_manager_new ();
                contact_widget_model_setup (information);
        }
 }
@@ -657,21 +668,19 @@ contact_widget_model_populate_columns (EmpathyContactWidget *information)
 static void
 contact_widget_groups_populate_data (EmpathyContactWidget *information)
 {
-       EmpathyContactManager *manager;
-       GtkTreeView           *view;
-       GtkListStore          *store;
-       GtkTreeIter            iter;
-       GList                 *my_groups, *l;
-       GList                 *all_groups;
+       GtkTreeView  *view;
+       GtkListStore *store;
+       GtkTreeIter   iter;
+       GList        *my_groups, *l;
+       GList        *all_groups;
 
        view = GTK_TREE_VIEW (information->treeview_groups);
        store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
        gtk_list_store_clear (store);
 
-       manager = empathy_contact_manager_new ();
-       all_groups = empathy_contact_manager_get_groups (manager);
-       my_groups = empathy_contact_get_groups (information->contact);
-       g_object_unref (manager);
+       all_groups = empathy_contact_list_get_all_groups (EMPATHY_CONTACT_LIST (information->manager));
+       my_groups = empathy_contact_list_get_groups (EMPATHY_CONTACT_LIST (information->manager),
+                                                    information->contact);
 
        for (l = all_groups; l; l = l->next) {
                const gchar *group_str;
@@ -691,7 +700,10 @@ contact_widget_groups_populate_data (EmpathyContactWidget *information)
                                    -1);
        }
 
+       g_list_foreach (all_groups, (GFunc) g_free, NULL);
+       g_list_foreach (my_groups, (GFunc) g_free, NULL);
        g_list_free (all_groups);
+       g_list_free (my_groups);
 }
 
 static void
@@ -792,9 +804,13 @@ contact_widget_cell_toggled (GtkCellRendererToggle *cell,
 
        if (group) {
                if (enabled) {
-                       empathy_contact_remove_group (information->contact, group);
+                       empathy_contact_list_remove_from_group (EMPATHY_CONTACT_LIST (information->manager),
+                                                               information->contact,
+                                                               group);
                } else {
-                       empathy_contact_add_group (information->contact, group);        
+                       empathy_contact_list_add_to_group (EMPATHY_CONTACT_LIST (information->manager),
+                                                          information->contact,
+                                                          group);
                }
 
                g_free (group);
@@ -846,7 +862,9 @@ contact_widget_button_group_clicked_cb (GtkButton             *button,
                            COL_ENABLED, TRUE,
                            -1);
 
-       empathy_contact_add_group (information->contact, group);
+       empathy_contact_list_add_to_group (EMPATHY_CONTACT_LIST (information->manager),
+                                          information->contact,
+                                          group);
 }
 
 static void
index ca046a3d76848b4025ad2c0518188051c91f3157..48439302d30cd8725d044a5a9dbf5999e6cae1a3 100644 (file)
@@ -78,11 +78,12 @@ static void          group_chat_finalize                 (GObject           *obj
 static void          group_chat_create_ui                (EmpathyGroupChat  *chat);
 static void          group_chat_widget_destroy_cb        (GtkWidget         *widget,
                                                          EmpathyGroupChat  *chat);
-static void          group_chat_contact_added_cb         (EmpathyTpChatroom *tp_chat,
-                                                         EmpathyContact    *contact,
-                                                         EmpathyGroupChat  *chat);
-static void          group_chat_contact_removed_cb       (EmpathyTpChatroom *tp_chat,
+static void          group_chat_members_changed_cb       (EmpathyTpChatroom *tp_chat,
                                                          EmpathyContact    *contact,
+                                                         EmpathyContact    *actor,
+                                                         guint              reason,
+                                                         gchar             *message,
+                                                         gboolean           is_member,
                                                          EmpathyGroupChat  *chat);
 static void          group_chat_topic_entry_activate_cb  (GtkWidget         *entry,
                                                          GtkDialog         *dialog);
@@ -348,33 +349,26 @@ group_chat_widget_destroy_cb (GtkWidget       *widget,
 }
 
 static void
-group_chat_contact_added_cb (EmpathyTpChatroom *tp_chat,
-                            EmpathyContact     *contact,
-                            EmpathyGroupChat   *chat)
-{
-       EmpathyGroupChatPriv *priv;
-       gchar               *str;
-
-       priv = GET_PRIV (chat);
-
-       str = g_strdup_printf (_("%s has joined the room"),
-                              empathy_contact_get_name (contact));
-       empathy_chat_view_append_event (EMPATHY_CHAT (chat)->view, str);
-       g_free (str);
-}
-
-static void
-group_chat_contact_removed_cb (EmpathyTpChatroom *tp_chat,
+group_chat_members_changed_cb (EmpathyTpChatroom *tp_chat,
                               EmpathyContact     *contact,
+                              EmpathyContact     *actor,
+                              guint               reason,
+                              gchar              *message,
+                              gboolean            is_member,
                               EmpathyGroupChat   *chat)
 {
        EmpathyGroupChatPriv *priv;
-       gchar               *str;
+       gchar                *str;
 
        priv = GET_PRIV (chat);
 
-       str = g_strdup_printf (_("%s has left the room"),
-                              empathy_contact_get_name (contact));
+       if (is_member) {
+               str = g_strdup_printf (_("%s has joined the room"),
+                                      empathy_contact_get_name (contact));
+       } else {
+               str = g_strdup_printf (_("%s has left the room"),
+                                      empathy_contact_get_name (contact));
+       }
        empathy_chat_view_append_event (EMPATHY_CHAT (chat)->view, str);
        g_free (str);
 }
@@ -540,11 +534,8 @@ group_chat_set_tp_chat (EmpathyChat    *chat,
        gtk_widget_show (GTK_WIDGET (priv->view));
 
        /* Connect signals */
-       g_signal_connect (priv->tp_chat, "contact-added",
-                         G_CALLBACK (group_chat_contact_added_cb),
-                         chat);
-       g_signal_connect (priv->tp_chat, "contact-removed",
-                         G_CALLBACK (group_chat_contact_removed_cb),
+       g_signal_connect (priv->tp_chat, "members-changed",
+                         G_CALLBACK (group_chat_members_changed_cb),
                          chat);
        g_signal_connect (priv->tp_chat, "notify::subject",
                          G_CALLBACK (group_chat_subject_notify_cb),
index 227ebe599ae723d46e16f28d184db8baa1187046..ad6d43b28656a9b14e2090ee772e99bd5bf4e37f 100644 (file)
@@ -31,7 +31,7 @@ G_BEGIN_DECLS
 #define EMPATHY_IMAGE_BUSY                "empathy-busy"
 #define EMPATHY_IMAGE_AWAY                "empathy-away"
 #define EMPATHY_IMAGE_EXT_AWAY            "empathy-extended-away"
-#define EMPATHY_IMAGE_PENDING             "empathy-pending"
+#define EMPATHY_IMAGE_UNKNOWN             "empathy-pending"
 
 #define EMPATHY_IMAGE_MESSAGE             "empathy-message"
 #define EMPATHY_IMAGE_NEW_MESSAGE         "empathy-new-message"
index 13c578d890141339828ac16205a1fcec83c4cb23..4b89c4e67632d023cc635519c3e2413e730639a0 100644 (file)
@@ -288,7 +288,6 @@ empathy_main_window_show (void)
        empathy_status_presets_get_all ();
 
        list_iface = EMPATHY_CONTACT_LIST (empathy_contact_manager_new ());
-       empathy_contact_list_setup (list_iface);
        window->list_store = empathy_contact_list_store_new (list_iface);
        window->list_view = empathy_contact_list_view_new (window->list_store);
        g_object_unref (list_iface);
index 81f93c02147548f36dc08d5c568cc8239211e598..b187e98cdb2c1665813fc038dff06a196eb2c685 100644 (file)
@@ -36,7 +36,7 @@
 #include <libempathy/empathy-debug.h>
 #include <libempathy/empathy-tp-chat.h>
 #include <libempathy/empathy-tp-contact-list.h>
-#include <libempathy/empathy-contact-manager.h>
+#include <libempathy/empathy-contact-factory.h>
 
 #include "empathy-private-chat.h"
 #include "empathy-chat-view.h"
 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_PRIVATE_CHAT, EmpathyPrivateChatPriv))
 
 struct _EmpathyPrivateChatPriv {   
-       EmpathyContact *contact;
-       gchar          *name;
-       gboolean        is_online;
-       GtkWidget      *widget;
-       GtkWidget      *text_view_sw;
+       EmpathyContactFactory *factory;
+       EmpathyContact        *contact;
+       gchar                 *name;
+       gboolean               is_online;
+       GtkWidget             *widget;
+       GtkWidget             *text_view_sw;
 };
 
 static void           empathy_private_chat_class_init            (EmpathyPrivateChatClass *klass);
@@ -125,7 +126,9 @@ private_chat_finalize (GObject *object)
        if (priv->contact) {
                g_object_unref (priv->contact);
        }
-
+       if (priv->factory) {
+               g_object_unref (priv->factory);
+       }
        g_free (priv->name);
 
        G_OBJECT_CLASS (empathy_private_chat_parent_class)->finalize (object);
@@ -327,27 +330,30 @@ EmpathyPrivateChat *
 empathy_private_chat_new (McAccount *account,
                          TpChan    *tp_chan)
 {
-       EmpathyPrivateChat    *chat;
-       EmpathyTpChat         *tp_chat;
-       EmpathyContactManager *manager;
-       EmpathyTpContactList  *list;
-       EmpathyContact        *contact;
+       EmpathyPrivateChat     *chat;
+       EmpathyPrivateChatPriv *priv;
+       EmpathyTpChat          *tp_chat;
+       EmpathyContactFactory  *factory;
+       EmpathyContact         *contact;
 
        g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
        g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL);
 
-       manager = empathy_contact_manager_new ();
-       list = empathy_contact_manager_get_list (manager, account);
-       contact = empathy_tp_contact_list_get_from_handle (list, tp_chan->handle);
+       factory = empathy_contact_factory_new ();
+       contact = empathy_contact_factory_get_from_handle (factory,
+                                                          account,
+                                                          tp_chan->handle);
 
        chat = g_object_new (EMPATHY_TYPE_PRIVATE_CHAT, NULL);
-       tp_chat = empathy_tp_chat_new (account, tp_chan);
+       priv = GET_PRIV (chat);
 
+       priv->factory = factory;
+       tp_chat = empathy_tp_chat_new (account, tp_chan);
        private_chat_setup (chat, contact, tp_chat);
 
        g_object_unref (tp_chat);
        g_object_unref (contact);
-       g_object_unref (manager);
+       g_object_unref (factory);
 
        return chat;
 }
index 1ec1a21a5a1655dd63375b7737b36bc7a5798c95..1fdc0095309fdfdcd9485d6a1145e74e0ca483f6 100644 (file)
@@ -117,9 +117,12 @@ static void       status_icon_quit_cb             (GtkWidget              *windo
                                                   EmpathyStatusIcon      *icon);
 static void       status_icon_show_hide_window_cb (GtkWidget              *widget,
                                                   EmpathyStatusIcon      *icon);
-static void       status_icon_local_pending_cb    (EmpathyContactManager  *manager,
-                                                  EmpathyContact          *contact,
+static void       status_icon_pendings_changed_cb (EmpathyContactManager  *manager,
+                                                  EmpathyContact         *contact,
+                                                  EmpathyContact         *actor,
+                                                  guint                   reason,
                                                   gchar                  *message,
+                                                  gboolean                is_pending,
                                                   EmpathyStatusIcon      *icon);
 static void       status_icon_event_subscribe_cb  (StatusIconEvent        *event);
 static void       status_icon_event_flash_state_cb (StatusIconEvent       *event);
@@ -148,7 +151,7 @@ static void
 empathy_status_icon_init (EmpathyStatusIcon *icon)
 {
        EmpathyStatusIconPriv *priv;
-       GList                 *pending, *l;
+       GList                 *pendings, *l;
 
        priv = GET_PRIV (icon);
 
@@ -177,21 +180,25 @@ empathy_status_icon_init (EmpathyStatusIcon *icon)
        g_signal_connect (priv->icon, "popup-menu",
                          G_CALLBACK (status_icon_popup_menu_cb),
                          icon);
-       g_signal_connect (priv->manager, "local-pending",
-                         G_CALLBACK (status_icon_local_pending_cb),
+       g_signal_connect (priv->manager, "pendings-changed",
+                         G_CALLBACK (status_icon_pendings_changed_cb),
                          icon);
 
-       pending = empathy_contact_list_get_local_pending (EMPATHY_CONTACT_LIST (priv->manager));
-       for (l = pending; l; l = l->next) {
-               EmpathyContactListInfo *info;
+       pendings = empathy_contact_list_get_pendings (EMPATHY_CONTACT_LIST (priv->manager));
+       for (l = pendings; l; l = l->next) {
+               EmpathyPendingInfo *info;
 
                info = l->data;
-               status_icon_local_pending_cb (priv->manager,
-                                             info->contact,
-                                             info->message,
-                                             icon);
+               status_icon_pendings_changed_cb (priv->manager,
+                                                info->member,
+                                                info->actor,
+                                                0,
+                                                info->message,
+                                                TRUE,
+                                                icon);
+               empathy_pending_info_free (info);
        }
-       g_list_free (pending);
+       g_list_free (pendings);
 }
 
 static void
@@ -533,10 +540,13 @@ status_icon_show_hide_window_cb (GtkWidget         *widget,
 }
 
 static void
-status_icon_local_pending_cb (EmpathyContactManager *manager,
-                             EmpathyContact         *contact,
-                             gchar                 *message,
-                             EmpathyStatusIcon     *icon)
+status_icon_pendings_changed_cb (EmpathyContactManager *manager,
+                                EmpathyContact        *contact,
+                                EmpathyContact        *actor,
+                                guint                  reason,
+                                gchar                 *message,
+                                gboolean               is_pending,
+                                EmpathyStatusIcon     *icon)
 {
        EmpathyStatusIconPriv *priv;
        StatusIconEvent       *event;
@@ -545,6 +555,11 @@ status_icon_local_pending_cb (EmpathyContactManager *manager,
 
        priv = GET_PRIV (icon);
 
+       if (!is_pending) {
+               /* FIXME: We should remove the event */
+               return;
+       }
+
        for (l = priv->events; l; l = l->next) {
                if (empathy_contact_equal (contact, ((StatusIconEvent*)l->data)->user_data)) {
                        return;
index fb491cc5ef0da93a0e2672b4f37e4e67ebc7cc0d..aedacb08be5b45190b1041e54675962a8c988580 100644 (file)
@@ -378,8 +378,7 @@ empathy_icon_name_for_presence (EmpathyPresence *presence)
 const gchar *
 empathy_icon_name_for_contact (EmpathyContact *contact)
 {
-       EmpathyPresence     *presence;
-       EmpathySubscription  subscription;
+       EmpathyPresence *presence;
 
        g_return_val_if_fail (EMPATHY_IS_CONTACT (contact),
                              EMPATHY_IMAGE_OFFLINE);
@@ -389,12 +388,7 @@ empathy_icon_name_for_contact (EmpathyContact *contact)
                return empathy_icon_name_for_presence (presence);
        }
 
-       subscription = empathy_contact_get_subscription (contact);
-       if (!(subscription & EMPATHY_SUBSCRIPTION_FROM)) {
-               return EMPATHY_IMAGE_PENDING;
-       }
-
-       return EMPATHY_IMAGE_OFFLINE;
+       return EMPATHY_IMAGE_UNKNOWN;
 }
 
 static void
index 39dfa9b62af3bfc2f2bbbd16620d88eb6efb8019..c24a16f211d88188e51d2d9f124eefbc34854ddf 100644 (file)
@@ -17,7 +17,6 @@ lib_LTLIBRARIES = libempathy.la
 
 libempathy_la_SOURCES =                                        \
        empathy-conf.c                                  \
-       empathy-contact.c                               \
        empathy-avatar.c                                \
        empathy-time.c                                  \
        empathy-presence.c                              \
@@ -26,8 +25,10 @@ libempathy_la_SOURCES =                                      \
        empathy-message.c                               \
        empathy-chatroom-manager.c                      \
        empathy-chatroom.c                              \
+       empathy-contact.c                               \
        empathy-contact-list.c                          \
        empathy-contact-manager.c                       \
+       empathy-contact-factory.c                       \
        empathy-tp-group.c                              \
        empathy-tp-contact-list.c                       \
        empathy-tp-chat.c                               \
@@ -50,7 +51,6 @@ libempathy_la_LDFLAGS =               \
 
 libempathy_headers =                           \
        empathy-conf.h                          \
-       empathy-contact.h                       \
        empathy-avatar.h                        \
        empathy-time.h                          \
        empathy-presence.h                      \
@@ -59,8 +59,10 @@ libempathy_headers =                         \
        empathy-message.h                       \
        empathy-chatroom-manager.h              \
        empathy-chatroom.h                      \
+       empathy-contact.h                       \
        empathy-contact-list.h                  \
        empathy-contact-manager.h               \
+       empathy-contact-factory.h               \
        empathy-tp-group.h                      \
        empathy-tp-contact-list.h               \
        empathy-tp-chat.h                       \
index e5a2a73a97aef06950c43ac15c525e9df7ea477d..425f23f5530c3a68ce1b25e683efc42453ac0f57 100644 (file)
@@ -28,7 +28,7 @@
 #define DEBUG_DOMAIN "Avatar"
 
 GType
-empathy_avatar_get_gtype (void)
+empathy_avatar_get_type (void)
 {
        static GType type_id = 0;
 
index 73d69cf794a5fed23561dd787eae4063de3e69a1..6b28e8e7a6b700c881cad2764417632095d85e70 100644 (file)
@@ -25,7 +25,7 @@
 
 G_BEGIN_DECLS
 
-#define EMPATHY_TYPE_AVATAR (empathy_avatar_get_gtype ())
+#define EMPATHY_TYPE_AVATAR (empathy_avatar_get_type ())
 
 typedef struct _EmpathyAvatar EmpathyAvatar;
 
@@ -36,7 +36,7 @@ struct _EmpathyAvatar {
        guint   refcount;
 };
 
-GType          empathy_avatar_get_gtype (void) G_GNUC_CONST;
+GType          empathy_avatar_get_type (void) G_GNUC_CONST;
 EmpathyAvatar * empathy_avatar_new       (guchar       *avatar,
                                        gsize         len,
                                        gchar        *format);
diff --git a/libempathy/empathy-contact-factory.c b/libempathy/empathy-contact-factory.c
new file mode 100644 (file)
index 0000000..1c91a65
--- /dev/null
@@ -0,0 +1,1102 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 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: Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <libtelepathy/tp-conn.h>
+#include <libtelepathy/tp-conn-iface-aliasing-gen.h>
+#include <libtelepathy/tp-conn-iface-presence-gen.h>
+#include <libtelepathy/tp-conn-iface-avatars-gen.h>
+#include <libmissioncontrol/mission-control.h>
+
+#include "empathy-contact-factory.h"
+#include "empathy-utils.h"
+#include "empathy-debug.h"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
+                      EMPATHY_TYPE_CONTACT_FACTORY, EmpathyContactFactoryPriv))
+
+#define DEBUG_DOMAIN "ContactFactory"
+
+struct _EmpathyContactFactoryPriv {
+       MissionControl *mc;
+       GHashTable     *accounts;
+};
+
+typedef struct {
+       EmpathyContactFactory *factory;
+       McAccount             *account;
+       guint                  nb_pending_calls;
+
+       TpConn                *tp_conn;
+       DBusGProxy            *aliasing_iface;
+       DBusGProxy            *avatars_iface;
+       DBusGProxy            *presence_iface;
+
+       GList                 *contacts;
+       guint                  self_handle;
+} ContactFactoryAccountData;
+
+typedef struct {
+       ContactFactoryAccountData *account_data;
+       GList                     *contacts;
+} RequestHandlesData;
+
+typedef struct {
+       ContactFactoryAccountData *account_data;
+       guint                     *handles;
+} RequestAliasesData;
+
+typedef struct {
+       ContactFactoryAccountData *account_data;
+       EmpathyContact            *contact;
+} RequestAvatarData;
+
+static void empathy_contact_factory_class_init (EmpathyContactFactoryClass *klass);
+static void empathy_contact_factory_init       (EmpathyContactFactory      *factory);
+
+G_DEFINE_TYPE (EmpathyContactFactory, empathy_contact_factory, G_TYPE_OBJECT);
+
+static gint
+contact_factory_find_by_handle (gconstpointer a,
+                               gconstpointer b)
+{
+       EmpathyContact *contact;
+       guint           handle; 
+
+       contact = EMPATHY_CONTACT (a);
+       handle = GPOINTER_TO_UINT (b);
+
+       return handle - empathy_contact_get_handle (contact);
+}
+
+static EmpathyContact *
+contact_factory_account_data_find_by_handle (ContactFactoryAccountData *account_data,
+                                            guint                      handle)
+{
+       GList *l;
+
+       l = g_list_find_custom (account_data->contacts,
+                               GUINT_TO_POINTER (handle),
+                               contact_factory_find_by_handle);
+
+       return l ? l->data : NULL;
+}
+
+static gint
+contact_factory_find_by_id (gconstpointer a,
+                           gconstpointer b)
+{
+       EmpathyContact *contact;
+       const gchar    *id = b;
+
+       contact = EMPATHY_CONTACT (a);
+
+       return strcmp (id, empathy_contact_get_id (contact));
+}
+
+static EmpathyContact *
+contact_factory_account_data_find_by_id (ContactFactoryAccountData *account_data,
+                                        const gchar               *id)
+{
+       GList *l;
+
+       l = g_list_find_custom (account_data->contacts,
+                               id,
+                               contact_factory_find_by_id);
+
+       return l ? l->data : NULL;
+}
+
+static void contact_factory_account_data_free (gpointer data);
+
+static void
+contact_factory_account_data_return_call (ContactFactoryAccountData *account_data)
+{
+       if (--account_data->nb_pending_calls == 0 &&
+           account_data->contacts == NULL) {
+               contact_factory_account_data_free (account_data);
+       }
+}
+
+static void
+contact_factory_presences_table_foreach (const gchar      *state_str,
+                                        GHashTable       *presences_table,
+                                        EmpathyPresence **presence)
+{
+       McPresence    state;
+       const GValue *message;
+
+       state = empathy_presence_state_from_str (state_str);
+       if (state == MC_PRESENCE_UNSET) {
+               return;
+       }
+
+       if (*presence) {
+               g_object_unref (*presence);
+               *presence = NULL;
+       }
+
+       *presence = empathy_presence_new ();
+       empathy_presence_set_state (*presence, state);
+
+       message = g_hash_table_lookup (presences_table, "message");
+       if (message != NULL) {
+               empathy_presence_set_status (*presence,
+                                            g_value_get_string (message));
+       }
+}
+
+static void
+contact_factory_parse_presence_foreach (guint                      handle,
+                                       GValueArray               *presence_struct,
+                                       ContactFactoryAccountData *account_data)
+{
+       GHashTable      *presences_table;
+       EmpathyContact  *contact;
+       EmpathyPresence *presence = NULL;
+
+       contact = contact_factory_account_data_find_by_handle (account_data,
+                                                              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) contact_factory_presences_table_foreach,
+                             &presence);
+
+       empathy_debug (DEBUG_DOMAIN, "Changing presence for contact %s (%d) to %s (%d)",
+                     empathy_contact_get_id (contact),
+                     handle,
+                     presence ? empathy_presence_get_status (presence) : "unset",
+                     presence ? empathy_presence_get_state (presence) : MC_PRESENCE_UNSET);
+
+       empathy_contact_set_presence (contact, presence);
+}
+
+static void
+contact_factory_get_presence_cb (DBusGProxy *proxy,
+                                GHashTable *handle_table,
+                                GError     *error,
+                                gpointer    user_data)
+{
+       ContactFactoryAccountData *account_data = user_data;
+
+       if (error) {
+               empathy_debug (DEBUG_DOMAIN, "Error requesting aliases: %s",
+                             error->message);
+               goto OUT;
+       }
+
+       g_hash_table_foreach (handle_table,
+                             (GHFunc) contact_factory_parse_presence_foreach,
+                             account_data);
+OUT:
+       contact_factory_account_data_return_call (account_data);
+}
+
+static void
+contact_factory_presence_update_cb (DBusGProxy                *proxy,
+                                   GHashTable                *handle_table,
+                                   ContactFactoryAccountData *account_data)
+{
+       g_hash_table_foreach (handle_table,
+                             (GHFunc) contact_factory_parse_presence_foreach,
+                             account_data);
+}
+
+static void
+contact_factory_set_aliases_cb (DBusGProxy *proxy,
+                               GError *error,
+                               gpointer user_data)
+{
+       ContactFactoryAccountData *account_data = user_data;
+
+       if (error) {
+               empathy_debug (DEBUG_DOMAIN, "Error setting alias: %s",
+                              error->message);
+       }
+
+       contact_factory_account_data_return_call (account_data);
+}
+
+static void
+contact_factory_request_aliases_cb (DBusGProxy  *proxy,
+                                   gchar      **contact_names,
+                                   GError      *error,
+                                   gpointer     user_data)
+{
+       RequestAliasesData  *data = user_data;
+       guint                i = 0;
+       gchar              **name;
+
+       if (error) {
+               empathy_debug (DEBUG_DOMAIN, "Error requesting aliases: %s",
+                             error->message);
+               goto OUT;
+       }
+
+       for (name = contact_names; *name; name++) {
+               EmpathyContact *contact;
+
+               contact = contact_factory_account_data_find_by_handle (data->account_data,
+                                                                      data->handles[i]);
+               if (!contact) {
+                       continue;
+               }
+
+               empathy_debug (DEBUG_DOMAIN, "Renaming contact %s (%d) to %s (request cb)",
+                              empathy_contact_get_id (contact),
+                              data->handles[i], *name);
+
+               empathy_contact_set_name  (contact, *name);
+
+               i++;
+       }
+
+OUT:
+       contact_factory_account_data_return_call (data->account_data);
+       g_free (data->handles);
+       g_slice_free (RequestAliasesData, data);
+}
+
+static void
+contact_factory_aliases_changed_cb (DBusGProxy *proxy,
+                                   GPtrArray  *renamed_handlers,
+                                   gpointer    user_data)
+{
+       ContactFactoryAccountData *account_data = user_data;
+       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 = contact_factory_account_data_find_by_handle (account_data, handle);
+
+               if (!contact) {
+                       /* We don't know this contact, skip */
+                       continue;
+               }
+
+               if (G_STR_EMPTY (alias)) {
+                       alias = NULL;
+               }
+
+               empathy_debug (DEBUG_DOMAIN, "Renaming contact %s (%d) to %s (changed cb)",
+                              empathy_contact_get_id (contact),
+                              handle, alias);
+
+               empathy_contact_set_name (contact, alias);
+       }
+}
+
+static void
+contact_factory_request_avatars_cb (DBusGProxy *proxy,
+                                   GError     *error,
+                                   gpointer    user_data)
+{
+       ContactFactoryAccountData *account_data = user_data;
+
+       if (error) {
+               empathy_debug (DEBUG_DOMAIN, "Error requesting avatars: %s",
+                              error->message);
+       }
+
+       contact_factory_account_data_return_call (account_data);
+}
+
+static void
+contact_factory_request_avatar_cb (DBusGProxy *proxy,
+                                  GArray     *avatar_data,
+                                  gchar      *mime_type,
+                                  GError     *error,
+                                  gpointer    user_data)
+{
+       RequestAvatarData *data = user_data;
+       EmpathyAvatar     *avatar;
+
+       if (error) {
+               empathy_debug (DEBUG_DOMAIN, "Error requesting avatar: %s",
+                              error->message);
+               goto OUT;
+       }
+
+       empathy_debug (DEBUG_DOMAIN, "Avatar received for %s (%d)",
+                      empathy_contact_get_id (data->contact),
+                      empathy_contact_get_handle (data->contact));
+
+       avatar = empathy_avatar_new (avatar_data->data,
+                                    avatar_data->len,
+                                    mime_type);
+       empathy_contact_set_avatar (data->contact, avatar);
+       empathy_avatar_unref (avatar);
+
+OUT:
+       g_object_unref (data->contact);
+       contact_factory_account_data_return_call (data->account_data);
+       g_slice_free (RequestAvatarData, data);
+}
+
+static void
+contact_factory_avatar_updated_cb (DBusGProxy *proxy,
+                                  guint       handle,
+                                  gchar      *new_token,
+                                  gpointer    user_data)
+{
+       ContactFactoryAccountData *account_data = user_data;
+       RequestAvatarData         *data;
+       EmpathyContact            *contact;
+
+       contact = contact_factory_account_data_find_by_handle (account_data,
+                                                              handle);
+       if (!contact) {
+               return;
+       }
+
+       account_data->nb_pending_calls++;
+       data = g_slice_new0 (RequestAvatarData);
+       data->account_data = account_data;
+       data->contact = g_object_ref (contact);
+       tp_conn_iface_avatars_request_avatar_async (account_data->avatars_iface,
+                                                   handle,
+                                                   contact_factory_request_avatar_cb,
+                                                   data);
+}
+
+static void
+contact_factory_avatar_retrieved_cb (DBusGProxy *proxy,
+                                    guint       handle,
+                                    gchar      *token,
+                                    GArray     *avatar_data,
+                                    gchar      *mime_type,
+                                    gpointer    user_data)
+{
+       ContactFactoryAccountData *account_data = user_data;
+       EmpathyContact            *contact;
+       EmpathyAvatar             *avatar;
+
+       contact = contact_factory_account_data_find_by_handle (account_data,
+                                                              handle);
+       if (!contact) {
+               return;
+       }
+
+       avatar = empathy_avatar_new (avatar_data->data,
+                                    avatar_data->len,
+                                    mime_type);
+       empathy_contact_set_avatar (contact, avatar);
+       empathy_avatar_unref (avatar);
+}
+
+static void
+contact_factory_request_everything (ContactFactoryAccountData *account_data,
+                                   GArray                    *handles)
+{
+       if (account_data->presence_iface) {
+               account_data->nb_pending_calls++;
+               tp_conn_iface_presence_get_presence_async (account_data->presence_iface,
+                                                          handles,
+                                                          contact_factory_get_presence_cb,
+                                                          account_data);
+       }
+
+       if (account_data->aliasing_iface) {
+               RequestAliasesData *data;
+
+               account_data->nb_pending_calls++;
+               data = g_slice_new (RequestAliasesData);
+               data->account_data = account_data;
+               data->handles = g_memdup (handles->data, handles->len * sizeof (guint));
+
+               tp_conn_iface_aliasing_request_aliases_async (account_data->aliasing_iface,
+                                                             handles,
+                                                             contact_factory_request_aliases_cb,
+                                                             data);
+       }
+
+       if (account_data->avatars_iface) {
+               account_data->nb_pending_calls++;
+               tp_conn_iface_avatars_request_avatars_async (account_data->avatars_iface,
+                                                            handles,
+                                                            contact_factory_request_avatars_cb,
+                                                            account_data);
+       }
+}
+
+static void
+contact_factory_request_handles_cb (DBusGProxy *proxy,
+                                   GArray     *handles,
+                                   GError     *error,
+                                   gpointer    user_data)
+{
+       RequestHandlesData *data = user_data;
+       GList              *l;
+       guint               i = 0;
+
+       if (error) {
+               empathy_debug (DEBUG_DOMAIN, "Failed to request handles: %s",
+                              error->message);
+               goto OUT;
+       }
+
+       for (l = data->contacts; l; l = l->next) {
+               guint handle;
+
+               handle = g_array_index (handles, guint, i);
+               empathy_contact_set_handle (l->data, handle);
+               if (handle == data->account_data->self_handle) {
+                       empathy_contact_set_is_user (l->data, TRUE);
+               }
+
+               i++;
+       }
+
+       contact_factory_request_everything (data->account_data, handles);
+
+OUT:
+       g_list_foreach (data->contacts, (GFunc) g_object_unref, NULL);
+       g_list_free (data->contacts);
+       contact_factory_account_data_return_call (data->account_data);
+       g_slice_free (RequestHandlesData, data);
+}
+
+static void
+contact_factory_disconnect_contact_foreach (gpointer data,
+                                           gpointer user_data)
+{
+       EmpathyContact *contact = data;
+       
+       empathy_contact_set_presence (contact, NULL);
+       empathy_contact_set_handle (contact, 0);
+}
+
+static void
+contact_factory_destroy_cb (TpConn                    *tp_conn,
+                           ContactFactoryAccountData *account_data)
+{
+       empathy_debug (DEBUG_DOMAIN, "Account disconnected or CM crashed");
+
+       g_object_unref (account_data->tp_conn);
+       account_data->tp_conn = NULL;
+       account_data->aliasing_iface = NULL;
+       account_data->avatars_iface = NULL;
+       account_data->presence_iface = NULL;
+
+       g_list_foreach (account_data->contacts,
+                       contact_factory_disconnect_contact_foreach,
+                       account_data);
+}
+
+static void
+contact_factory_account_data_disconnect (ContactFactoryAccountData *account_data)
+{
+       if (account_data->aliasing_iface) {
+               dbus_g_proxy_disconnect_signal (account_data->aliasing_iface,
+                                               "AliasesChanged",
+                                               G_CALLBACK (contact_factory_aliases_changed_cb),
+                                               account_data);
+       }
+       if (account_data->avatars_iface) {
+               dbus_g_proxy_disconnect_signal (account_data->avatars_iface,
+                                               "AvatarUpdated",
+                                               G_CALLBACK (contact_factory_avatar_updated_cb),
+                                               account_data);
+               dbus_g_proxy_disconnect_signal (account_data->avatars_iface,
+                                               "AvatarRetrieved",
+                                               G_CALLBACK (contact_factory_avatar_retrieved_cb),
+                                               account_data);
+       }
+       if (account_data->presence_iface) {
+               dbus_g_proxy_disconnect_signal (account_data->presence_iface,
+                                               "PresenceUpdate",
+                                               G_CALLBACK (contact_factory_presence_update_cb),
+                                               account_data);
+       }
+       if (account_data->tp_conn) {
+               g_signal_handlers_disconnect_by_func (account_data->tp_conn,
+                                                     contact_factory_destroy_cb,
+                                                     account_data);
+       }
+}
+
+static void
+contact_factory_account_data_update (ContactFactoryAccountData *account_data)
+{
+       EmpathyContactFactory     *factory = account_data->factory;
+       EmpathyContactFactoryPriv *priv = GET_PRIV (factory);
+       McAccount                 *account = account_data->account;
+       TpConn                    *tp_conn = NULL;
+       RequestHandlesData        *data;
+       const gchar              **contact_ids;
+       guint                      i;
+       GList                     *l;
+       GError                    *error;
+
+       if (account_data->account) {
+               guint status;
+
+               /* status == 0 means the status is CONNECTED */
+               status = mission_control_get_connection_status (priv->mc,
+                                                               account, NULL);
+               if (status == 0) {
+                       tp_conn = mission_control_get_connection (priv->mc,
+                                                                 account, NULL);
+               }
+       }
+
+       if (!tp_conn) {
+               /* We are not connected anymore, remove the old connection */
+               contact_factory_account_data_disconnect (account_data);
+               if (account_data->tp_conn) {
+                       contact_factory_destroy_cb (account_data->tp_conn,
+                                                   account_data);
+               }
+               return;
+       }
+       else if (account_data->tp_conn) {
+               /* We were connected and we still are connected, nothing
+                * changed so nothing to do. */
+               g_object_unref (tp_conn);
+               return;
+       }
+
+       /* We got a new connection */
+       account_data->tp_conn = tp_conn;
+       account_data->aliasing_iface = tp_conn_get_interface (tp_conn,
+                                                             TELEPATHY_CONN_IFACE_ALIASING_QUARK);
+       account_data->avatars_iface = tp_conn_get_interface (tp_conn,
+                                                            TELEPATHY_CONN_IFACE_AVATARS_QUARK);
+       account_data->presence_iface = tp_conn_get_interface (tp_conn,
+                                                             TELEPATHY_CONN_IFACE_PRESENCE_QUARK);
+
+       /* Connect signals */
+       if (account_data->aliasing_iface) {
+               dbus_g_proxy_connect_signal (account_data->aliasing_iface,
+                                            "AliasesChanged",
+                                            G_CALLBACK (contact_factory_aliases_changed_cb),
+                                            account_data, NULL);
+       }
+       if (account_data->avatars_iface) {
+               dbus_g_proxy_connect_signal (account_data->avatars_iface,
+                                            "AvatarUpdated",
+                                            G_CALLBACK (contact_factory_avatar_updated_cb),
+                                            account_data, NULL);
+               dbus_g_proxy_connect_signal (account_data->avatars_iface,
+                                            "AvatarRetrieved",
+                                            G_CALLBACK (contact_factory_avatar_retrieved_cb),
+                                            account_data, NULL);
+       }
+       if (account_data->presence_iface) {
+               dbus_g_proxy_connect_signal (account_data->presence_iface,
+                                            "PresenceUpdate",
+                                            G_CALLBACK (contact_factory_presence_update_cb),
+                                            account_data, NULL);
+       }
+       g_signal_connect (tp_conn, "destroy",
+                         G_CALLBACK (contact_factory_destroy_cb),
+                         account_data);
+
+       /* Get our own handle */
+       if (!tp_conn_get_self_handle (DBUS_G_PROXY (account_data->tp_conn),
+                                     &account_data->self_handle,
+                                     &error)) {
+               empathy_debug (DEBUG_DOMAIN, "GetSelfHandle Error: %s",
+                             error ? error->message : "No error given");
+               g_clear_error (&error);
+       }
+
+       /* Request new handles for all contacts */
+       if (account_data->contacts) {
+               data = g_slice_new (RequestHandlesData);
+               data->account_data = account_data;
+               data->contacts = g_list_copy (account_data->contacts);
+               g_list_foreach (data->contacts, (GFunc) g_object_ref, NULL);
+
+               i = g_list_length (data->contacts);
+               contact_ids = g_new0 (const gchar*, i + 1);
+               i = 0;
+               for (l = data->contacts; l; l = l->next) {
+                       contact_ids[i] = empathy_contact_get_id (l->data);
+                       i++;
+               }
+
+               account_data->nb_pending_calls++;
+               tp_conn_request_handles_async (DBUS_G_PROXY (account_data->tp_conn),
+                                              TP_HANDLE_TYPE_CONTACT,
+                                              contact_ids,
+                                              contact_factory_request_handles_cb,
+                                              data);
+               g_free (contact_ids);
+       }
+}
+
+static void
+contact_factory_weak_notify (gpointer data,
+                            GObject *where_the_object_was)
+{
+       ContactFactoryAccountData *account_data = data;
+
+       empathy_debug (DEBUG_DOMAIN, "Remove finalized contact %p",
+                      where_the_object_was);
+
+       account_data->contacts = g_list_remove (account_data->contacts,
+                                               where_the_object_was);
+       if (!account_data->contacts) {
+               EmpathyContactFactoryPriv *priv;
+
+               priv = GET_PRIV (account_data->factory);
+
+               g_hash_table_remove (priv->accounts, account_data->account);
+       }
+}
+
+static void
+contact_factory_remove_foreach (gpointer data,
+                               gpointer user_data)
+{
+       ContactFactoryAccountData *account_data = user_data;
+       EmpathyContact            *contact = data;
+
+       g_object_weak_unref (G_OBJECT (contact),
+                            contact_factory_weak_notify,
+                            account_data);
+}
+
+static ContactFactoryAccountData *
+contact_factory_account_data_new (EmpathyContactFactory *factory,
+                                 McAccount             *account)
+{
+       ContactFactoryAccountData *account_data;
+
+       account_data = g_slice_new0 (ContactFactoryAccountData);
+       account_data->factory = factory;
+       account_data->account = g_object_ref (account);
+
+       contact_factory_account_data_update (account_data);
+
+       return account_data;
+}
+
+static void
+contact_factory_account_data_free (gpointer data)
+{
+       ContactFactoryAccountData *account_data = data;
+
+       contact_factory_account_data_disconnect (account_data);
+
+       if (account_data->contacts) {
+               g_list_foreach (account_data->contacts,
+                               contact_factory_remove_foreach,
+                               account_data);
+               g_list_free (account_data->contacts);
+               account_data->contacts = NULL;
+       }
+
+       if (account_data->account) {
+               g_object_unref (account_data->account);
+               account_data->account = NULL;
+       }
+
+       if (account_data->tp_conn) {
+               g_object_unref (account_data->tp_conn);
+               account_data->tp_conn = NULL;
+               account_data->aliasing_iface = NULL;
+               account_data->avatars_iface = NULL;
+               account_data->presence_iface = NULL;
+       }
+
+       /* Keep the struct alive if we have calls in flight, it will be
+        * destroyed once all calls returned. */
+       if (account_data->nb_pending_calls == 0) {
+               g_slice_free (ContactFactoryAccountData, account_data);
+       }
+}
+
+static void
+contact_factory_status_changed_cb (MissionControl                  *mc,
+                                  TelepathyConnectionStatus        status,
+                                  McPresence                       presence,
+                                  TelepathyConnectionStatusReason  reason,
+                                  const gchar                     *unique_name,
+                                  EmpathyContactFactory           *factory)
+{
+       EmpathyContactFactoryPriv *priv = GET_PRIV (factory);
+       ContactFactoryAccountData *account_data;
+       McAccount                 *account;
+
+       account = mc_account_lookup (unique_name);
+       account_data = g_hash_table_lookup (priv->accounts, account);
+       if (account_data) {
+               contact_factory_account_data_update (account_data);
+       }
+       g_object_unref (account);
+}
+
+static ContactFactoryAccountData *
+contact_factory_account_data_get (EmpathyContactFactory *factory,
+                                 McAccount             *account)
+{
+       EmpathyContactFactoryPriv *priv = GET_PRIV (factory);
+       ContactFactoryAccountData *account_data;
+
+       account_data = g_hash_table_lookup (priv->accounts, account);
+       if (!account_data) {
+               account_data = contact_factory_account_data_new (factory, account);
+               g_hash_table_insert (priv->accounts,
+                                    g_object_ref (account),
+                                    account_data);
+       }
+
+       return account_data;
+}
+
+static void
+contact_factory_account_data_add_contact (ContactFactoryAccountData *account_data,
+                                         EmpathyContact            *contact)
+{
+       g_object_weak_ref (G_OBJECT (contact),
+                          contact_factory_weak_notify,
+                          account_data);
+       account_data->contacts = g_list_prepend (account_data->contacts, contact);
+
+       if (!account_data->presence_iface) {
+               EmpathyPresence *presence;
+
+               /* We have no presence iface, set default presence
+                * to available */
+               presence = empathy_presence_new_full (MC_PRESENCE_AVAILABLE,
+                                                    NULL);
+
+               empathy_contact_set_presence (contact, presence);
+               g_object_unref (presence);
+       }
+
+       empathy_debug (DEBUG_DOMAIN, "Contact added: %s (%d)",
+                      empathy_contact_get_id (contact),
+                      empathy_contact_get_handle (contact));
+}
+
+static void
+contact_factory_hold_handles_cb (DBusGProxy *proxy,
+                                GError     *error,
+                                gpointer    userdata)
+{
+       if (error) {
+               empathy_debug (DEBUG_DOMAIN, "Failed to hold handles: %s",
+                              error->message);
+       }
+}
+
+EmpathyContact *
+empathy_contact_factory_get_user (EmpathyContactFactory *factory,
+                                 McAccount             *account)
+{
+       ContactFactoryAccountData *account_data;
+
+       g_return_val_if_fail (EMPATHY_IS_CONTACT_FACTORY (factory), NULL);
+       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+
+       account_data = contact_factory_account_data_get (factory, account);
+
+       return empathy_contact_factory_get_from_handle (factory, account,
+                                                       account_data->self_handle);
+}
+
+EmpathyContact *
+empathy_contact_factory_get_from_id (EmpathyContactFactory *factory,
+                                    McAccount             *account,
+                                    const gchar           *id)
+{
+       ContactFactoryAccountData *account_data;
+       EmpathyContact            *contact;
+
+       g_return_val_if_fail (EMPATHY_IS_CONTACT_FACTORY (factory), NULL);
+       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+       g_return_val_if_fail (id != NULL, NULL);
+
+       /* Check if the contact already exists */
+       account_data = contact_factory_account_data_get (factory, account);
+       contact = contact_factory_account_data_find_by_id (account_data, id);
+       if (contact) {
+               return g_object_ref (contact);
+       }
+
+       /* Create new contact */
+       contact = g_object_new (EMPATHY_TYPE_CONTACT,
+                               "account", account,
+                               "id", id,
+                               NULL);
+       contact_factory_account_data_add_contact (account_data, contact);
+
+       /* If the account is connected, request contact's handle */
+       if (account_data->tp_conn) {
+               RequestHandlesData *data;
+               const gchar        *contact_ids[] = {id, NULL};
+               
+               account_data->nb_pending_calls++;
+               data = g_slice_new (RequestHandlesData);
+               data->account_data = account_data;
+               data->contacts = g_list_prepend (NULL, g_object_ref (contact));
+               tp_conn_request_handles_async (DBUS_G_PROXY (account_data->tp_conn),
+                                              TP_HANDLE_TYPE_CONTACT,
+                                              contact_ids,
+                                              contact_factory_request_handles_cb,
+                                              data);
+       }
+
+       return contact;
+}
+
+EmpathyContact *
+empathy_contact_factory_get_from_handle (EmpathyContactFactory *factory,
+                                        McAccount             *account,
+                                        guint                  handle)
+{
+       EmpathyContact *contact;
+       GArray         *handles;
+       GList          *contacts;
+
+       g_return_val_if_fail (EMPATHY_IS_CONTACT_FACTORY (factory), NULL);
+       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+
+       handles = g_array_new (FALSE, FALSE, sizeof (guint));
+       g_array_append_val (handles, handle);
+
+       contacts = empathy_contact_factory_get_from_handles (factory, account, handles);
+       g_array_free (handles, TRUE);
+
+       contact = contacts ? contacts->data : NULL;
+       g_list_free (contacts);
+
+       return contact;
+}
+
+GList *
+empathy_contact_factory_get_from_handles (EmpathyContactFactory *factory,
+                                         McAccount             *account,
+                                         GArray                *handles)
+{
+       ContactFactoryAccountData *account_data;
+       GList                     *contacts = NULL;
+       GArray                    *new_handles;
+       gchar                    **handles_names;
+       guint                      i;
+       GError                    *error = NULL;
+
+       g_return_val_if_fail (EMPATHY_IS_CONTACT_FACTORY (factory), NULL);
+       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+       g_return_val_if_fail (handles != NULL, NULL);
+
+       /* Search all contacts we already have */
+       account_data = contact_factory_account_data_get (factory, account);
+       new_handles = g_array_new (FALSE, FALSE, sizeof (guint));
+       for (i = 0; i < handles->len; i++) {
+               EmpathyContact *contact;
+               guint           handle;
+
+               handle = g_array_index (handles, guint, i);
+               if (handle == 0) {
+                       continue;
+               }
+
+               contact = contact_factory_account_data_find_by_handle (account_data, handle);
+               if (contact) {
+                       contacts = g_list_prepend (contacts, g_object_ref (contact));
+               } else {
+                       g_array_append_val (new_handles, handle);
+               }
+       }
+
+       if (new_handles->len == 0) {
+               g_array_free (new_handles, TRUE);
+               return contacts;
+       }
+
+       /* Get the IDs of all new handles */
+       if (!tp_conn_inspect_handles (DBUS_G_PROXY (account_data->tp_conn),
+                                     TP_HANDLE_TYPE_CONTACT,
+                                     new_handles,
+                                     &handles_names,
+                                     &error)) {
+               empathy_debug (DEBUG_DOMAIN, 
+                             "Couldn't inspect contact: %s",
+                             error ? error->message : "No error given");
+               g_clear_error (&error);
+               g_array_free (new_handles, TRUE);
+               return contacts;
+       }
+
+       /* Create new contacts */
+       for (i = 0; i < new_handles->len; i++) {
+               EmpathyContact *contact;
+               gchar          *id;
+               guint           handle;
+               gboolean        is_user;
+
+               id = handles_names[i];
+               handle = g_array_index (new_handles, guint, i);
+
+               is_user = (handle == account_data->self_handle);
+               contact = g_object_new (EMPATHY_TYPE_CONTACT,
+                                       "account", account,
+                                       "handle", handle,
+                                       "id", id,
+                                       "is-user", is_user,
+                                       NULL);
+               contact_factory_account_data_add_contact (account_data,
+                                                         contact);
+               contacts = g_list_prepend (contacts, contact);
+               g_free (id);
+       }
+       g_free (handles_names);
+
+       /* Hold all new handles. */
+       tp_conn_hold_handles_async (DBUS_G_PROXY (account_data->tp_conn),
+                                   TP_HANDLE_TYPE_CONTACT,
+                                   new_handles,
+                                   contact_factory_hold_handles_cb,
+                                   NULL);
+
+       contact_factory_request_everything (account_data, new_handles);
+
+       g_array_free (new_handles, TRUE);
+
+       return contacts;
+}
+
+void
+empathy_contact_factory_set_name (EmpathyContactFactory *factory,
+                                 EmpathyContact        *contact,
+                                 const gchar           *name)
+{
+       ContactFactoryAccountData *account_data;
+       McAccount                 *account;
+       GHashTable                *new_alias;
+       guint                      handle;
+
+       g_return_if_fail (EMPATHY_IS_CONTACT_FACTORY (factory));
+       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+       account = empathy_contact_get_account (contact);
+       account_data = contact_factory_account_data_get (factory, account);
+
+       if (!account_data->aliasing_iface) {
+               return;
+       }
+
+       handle = empathy_contact_get_handle (contact);
+
+       empathy_debug (DEBUG_DOMAIN, "Setting alias for contact %s (%d) to %s",
+                      empathy_contact_get_id (contact),
+                      handle, name);
+
+       new_alias = g_hash_table_new_full (g_direct_hash,
+                                          g_direct_equal,
+                                          NULL,
+                                          g_free);
+
+       g_hash_table_insert (new_alias,
+                            GUINT_TO_POINTER (handle),
+                            g_strdup (name));
+
+       account_data->nb_pending_calls++;
+       tp_conn_iface_aliasing_set_aliases_async (account_data->aliasing_iface,
+                                                 new_alias,
+                                                 contact_factory_set_aliases_cb,
+                                                 account_data);
+
+       g_hash_table_destroy (new_alias);
+}
+
+static void
+contact_factory_finalize (GObject *object)
+{
+       EmpathyContactFactoryPriv *priv;
+
+       priv = GET_PRIV (object);
+
+       dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc),
+                                       "AccountStatusChanged",
+                                       G_CALLBACK (contact_factory_status_changed_cb),
+                                       object);
+
+       g_hash_table_destroy (priv->accounts);
+       g_object_unref (priv->mc);
+
+       G_OBJECT_CLASS (empathy_contact_factory_parent_class)->finalize (object);
+}
+
+static void
+empathy_contact_factory_class_init (EmpathyContactFactoryClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = contact_factory_finalize;
+
+       g_type_class_add_private (object_class, sizeof (EmpathyContactFactoryPriv));
+}
+
+static void
+empathy_contact_factory_init (EmpathyContactFactory *factory)
+{
+       EmpathyContactFactoryPriv *priv;
+
+       priv = GET_PRIV (factory);
+
+       priv->mc = empathy_mission_control_new ();
+       priv->accounts = g_hash_table_new_full (empathy_account_hash,
+                                               empathy_account_equal,
+                                               g_object_unref,
+                                               contact_factory_account_data_free);
+
+       dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc),
+                                    "AccountStatusChanged",
+                                    G_CALLBACK (contact_factory_status_changed_cb),
+                                    factory, NULL);
+}
+
+EmpathyContactFactory *
+empathy_contact_factory_new (void)
+{
+       static EmpathyContactFactory *factory = NULL;
+
+       if (!factory) {
+               factory = g_object_new (EMPATHY_TYPE_CONTACT_FACTORY, NULL);
+               g_object_add_weak_pointer (G_OBJECT (factory), (gpointer) &factory);
+       } else {
+               g_object_ref (factory);
+       }
+
+       return factory;
+}
+
diff --git a/libempathy/empathy-contact-factory.h b/libempathy/empathy-contact-factory.h
new file mode 100644 (file)
index 0000000..1379371
--- /dev/null
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 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: 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"
+
+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;
+typedef struct _EmpathyContactFactoryPriv  EmpathyContactFactoryPriv;
+
+struct _EmpathyContactFactory {
+       GObject parent;
+};
+
+struct _EmpathyContactFactoryClass {
+       GObjectClass parent_class;
+};
+
+GType                  empathy_contact_factory_get_type         (void) G_GNUC_CONST;
+EmpathyContactFactory *empathy_contact_factory_new              (void);
+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,
+                                                                GArray                *handles);
+void                   empathy_contact_factory_set_name         (EmpathyContactFactory *factory,
+                                                                EmpathyContact        *contact,
+                                                                const gchar           *name);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_CONTACT_FACTORY_H__ */
index cc388d7ec4f145a099d027ff2bfe19db48b9e292..80308314eb129a203105860fb60f3426762db3ea 100644 (file)
@@ -53,149 +53,154 @@ contact_list_base_init (gpointer klass)
        static gboolean initialized = FALSE;
 
        if (!initialized) {
-               g_signal_new ("contact-added",
+               g_signal_new ("members-changed",
                              G_TYPE_FROM_CLASS (klass),
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
-                             g_cclosure_marshal_VOID__OBJECT,
+                             empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING_BOOLEAN,
                              G_TYPE_NONE,
-                             1, EMPATHY_TYPE_CONTACT);
+                             5, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT,
+                             G_TYPE_UINT, G_TYPE_STRING, G_TYPE_BOOLEAN);
 
-               g_signal_new ("contact-removed",
+               g_signal_new ("pendings-changed",
                              G_TYPE_FROM_CLASS (klass),
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
-                             g_cclosure_marshal_VOID__OBJECT,
+                             empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING_BOOLEAN,
                              G_TYPE_NONE,
-                             1, EMPATHY_TYPE_CONTACT);
+                             5, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT,
+                             G_TYPE_UINT, G_TYPE_STRING, G_TYPE_BOOLEAN);
 
-               g_signal_new ("local-pending",
+               g_signal_new ("groups-changed",
                              G_TYPE_FROM_CLASS (klass),
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
-                             empathy_marshal_VOID__OBJECT_STRING,
+                             empathy_marshal_VOID__OBJECT_STRING_BOOLEAN,
                              G_TYPE_NONE,
-                             2, EMPATHY_TYPE_CONTACT, G_TYPE_STRING);
+                             3, EMPATHY_TYPE_CONTACT, G_TYPE_STRING, G_TYPE_BOOLEAN);
 
                initialized = TRUE;
        }
 }
 
-EmpathyContactListInfo *
-empathy_contact_list_info_new (EmpathyContact *contact,
-                              const gchar   *message)
-{
-       EmpathyContactListInfo *info;
-
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
-
-       info = g_slice_new0 (EmpathyContactListInfo);
-       info->contact = g_object_ref (contact);
-       info->message = g_strdup (message);
-
-       return info;
-}                             
-
 void
-empathy_contact_list_info_free (EmpathyContactListInfo *info)
+empathy_contact_list_add (EmpathyContactList *list,
+                         EmpathyContact     *contact,
+                         const gchar        *message)
 {
-       if (!info) {
-               return;
-       }
+       g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
 
-       if (info->contact) {
-               g_object_unref (info->contact);
+       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->add) {
+               EMPATHY_CONTACT_LIST_GET_IFACE (list)->add (list, contact, message);
        }
-       g_free (info->message);
-
-       g_slice_free (EmpathyContactListInfo, info);
 }
 
 void
-empathy_contact_list_setup (EmpathyContactList *list)
+empathy_contact_list_remove (EmpathyContactList *list,
+                            EmpathyContact     *contact,
+                            const gchar        *message)
 {
        g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
 
-       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->setup) {
-               EMPATHY_CONTACT_LIST_GET_IFACE (list)->setup (list);
+       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->remove) {
+               EMPATHY_CONTACT_LIST_GET_IFACE (list)->remove (list, contact, message);
        }
 }
 
-EmpathyContact *
-empathy_contact_list_find (EmpathyContactList *list,
-                          const gchar        *id)
+GList *
+empathy_contact_list_get_members (EmpathyContactList *list)
 {
        g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
 
-       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->find) {
-               return EMPATHY_CONTACT_LIST_GET_IFACE (list)->find (list, id);
+       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members) {
+               return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members (list);
        }
 
        return NULL;
 }
 
-void
-empathy_contact_list_add (EmpathyContactList *list,
-                         EmpathyContact      *contact,
-                         const gchar        *message)
+GList *
+empathy_contact_list_get_pendings (EmpathyContactList *list)
 {
-       g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+       g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
 
-       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->add) {
-               EMPATHY_CONTACT_LIST_GET_IFACE (list)->add (list, contact, message);
+       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_pendings) {
+               return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_pendings (list);
        }
+
+       return NULL;
 }
 
-void
-empathy_contact_list_remove (EmpathyContactList *list,
-                            EmpathyContact      *contact,
-                            const gchar        *message)
+GList *
+empathy_contact_list_get_all_groups (EmpathyContactList *list)
 {
-       g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+       g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
 
-       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->remove) {
-               EMPATHY_CONTACT_LIST_GET_IFACE (list)->remove (list, contact, message);
+       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_all_groups) {
+               return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_all_groups (list);
        }
+
+       return NULL;
 }
 
 GList *
-empathy_contact_list_get_members (EmpathyContactList *list)
+empathy_contact_list_get_groups (EmpathyContactList *list,
+                                EmpathyContact     *contact)
 {
        g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
+       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
 
-       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members) {
-               return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members (list);
+       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_groups) {
+               return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_groups (list, contact);
        }
 
        return NULL;
 }
 
-GList *
-empathy_contact_list_get_local_pending (EmpathyContactList *list)
+void
+empathy_contact_list_add_to_group (EmpathyContactList *list,
+                                  EmpathyContact     *contact,
+                                  const gchar        *group)
 {
-       g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
+       g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+       g_return_if_fail (group != NULL);
 
-       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_local_pending) {
-               return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_local_pending (list);
+       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->add_to_group) {
+               EMPATHY_CONTACT_LIST_GET_IFACE (list)->add_to_group (list, contact, group);
        }
+}
 
-       return NULL;
+void
+empathy_contact_list_remove_from_group (EmpathyContactList *list,
+                                       EmpathyContact     *contact,
+                                       const gchar        *group)
+{
+       g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+       g_return_if_fail (group != NULL);
+
+       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->remove_from_group) {
+               EMPATHY_CONTACT_LIST_GET_IFACE (list)->remove_from_group (list, contact, group);
+       }
 }
 
 void
-empathy_contact_list_process_pending (EmpathyContactList *list,
-                                     EmpathyContact      *contact,
-                                     gboolean            accept)
+empathy_contact_list_rename_group (EmpathyContactList *list,
+                                  const gchar        *old_group,
+                                  const gchar        *new_group)
 {
        g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+       g_return_if_fail (old_group != NULL);
+       g_return_if_fail (new_group != NULL);
 
-       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->process_pending) {
-               EMPATHY_CONTACT_LIST_GET_IFACE (list)->process_pending (list,
-                                                                       contact,
-                                                                       accept);
+       if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->rename_group) {
+               EMPATHY_CONTACT_LIST_GET_IFACE (list)->rename_group (list, old_group, new_group);
        }
 }
 
index 959f5c51faecfd2546b94d311e0e554f9b0087e1..4b027f083e0903ad9e3fb9b72b8a3a56dd314255 100644 (file)
@@ -26,6 +26,7 @@
 #include <glib-object.h>
 
 #include "empathy-contact.h"
+#include "empathy-tp-group.h"
 
 G_BEGIN_DECLS
 
@@ -37,49 +38,53 @@ G_BEGIN_DECLS
 typedef struct _EmpathyContactList      EmpathyContactList;
 typedef struct _EmpathyContactListIface EmpathyContactListIface;
 
-typedef struct {
-       EmpathyContact *contact;
-       gchar         *message;
-} EmpathyContactListInfo;
-
 struct _EmpathyContactListIface {
        GTypeInterface   base_iface;
 
        /* VTabled */
-       void            (*setup)             (EmpathyContactList *list);
-       EmpathyContact * (*find)              (EmpathyContactList *list,
-                                             const gchar        *id);
-       void            (*add)               (EmpathyContactList *list,
-                                             EmpathyContact      *contact,
-                                             const gchar        *message);
-       void            (*remove)            (EmpathyContactList *list,
-                                             EmpathyContact      *contact,
-                                             const gchar        *message);
-       GList *         (*get_members)       (EmpathyContactList *list);
-       GList *         (*get_local_pending) (EmpathyContactList *list);
-       void            (*process_pending)   (EmpathyContactList *list,
-                                             EmpathyContact      *contact,
-                                             gboolean            accept);
+       void             (*add)               (EmpathyContactList *list,
+                                              EmpathyContact     *contact,
+                                              const gchar        *message);
+       void             (*remove)            (EmpathyContactList *list,
+                                              EmpathyContact     *contact,
+                                              const gchar        *message);
+       GList *          (*get_members)       (EmpathyContactList *list);
+       GList *          (*get_pendings)      (EmpathyContactList *list);
+       GList *          (*get_all_groups)    (EmpathyContactList *list);
+       GList *          (*get_groups)        (EmpathyContactList *list,
+                                              EmpathyContact     *contact);
+       void             (*add_to_group)      (EmpathyContactList *list,
+                                              EmpathyContact     *contact,
+                                              const gchar        *group);
+       void             (*remove_from_group) (EmpathyContactList *list,
+                                              EmpathyContact     *contact,
+                                              const gchar        *group);
+       void             (*rename_group)      (EmpathyContactList *list,
+                                              const gchar        *old_group,
+                                              const gchar        *new_group);
 };
 
-GType                   empathy_contact_list_get_type          (void) G_GNUC_CONST;
-EmpathyContactListInfo *empathy_contact_list_info_new          (EmpathyContact          *contact,
-                                                               const gchar            *message);
-void                    empathy_contact_list_info_free         (EmpathyContactListInfo *info);
-void                    empathy_contact_list_setup             (EmpathyContactList     *list);
-EmpathyContact *         empathy_contact_list_find              (EmpathyContactList     *list,
-                                                               const gchar            *id);
-void                    empathy_contact_list_add               (EmpathyContactList     *list,
-                                                               EmpathyContact          *contact,
-                                                               const gchar            *message);
-void                    empathy_contact_list_remove            (EmpathyContactList     *list,
-                                                               EmpathyContact          *contact,
-                                                               const gchar            *message);
-GList *                 empathy_contact_list_get_members       (EmpathyContactList     *list);
-GList *                 empathy_contact_list_get_local_pending (EmpathyContactList     *list);
-void                    empathy_contact_list_process_pending   (EmpathyContactList     *list,
-                                                               EmpathyContact          *contact,
-                                                               gboolean                accept);
+GType    empathy_contact_list_get_type          (void) G_GNUC_CONST;
+void     empathy_contact_list_add               (EmpathyContactList *list,
+                                                EmpathyContact     *contact,
+                                                const gchar        *message);
+void     empathy_contact_list_remove            (EmpathyContactList *list,
+                                                EmpathyContact     *contact,
+                                                const gchar        *message);
+GList *  empathy_contact_list_get_members       (EmpathyContactList *list);
+GList *  empathy_contact_list_get_pendings      (EmpathyContactList *list);
+GList *  empathy_contact_list_get_all_groups    (EmpathyContactList *list);
+GList *  empathy_contact_list_get_groups        (EmpathyContactList *list,
+                                                EmpathyContact     *contact);
+void     empathy_contact_list_add_to_group      (EmpathyContactList *list,
+                                                EmpathyContact     *contact,
+                                                const gchar        *group);
+void     empathy_contact_list_remove_from_group (EmpathyContactList *list,
+                                                EmpathyContact     *contact,
+                                                const gchar        *group);
+void     empathy_contact_list_rename_group      (EmpathyContactList *list,
+                                                const gchar        *old_group,
+                                                const gchar        *new_group);
 
 G_END_DECLS
 
index cc00108c856a2e2dc38745d7ce3789f357f31587..575814fab8218dc4c8df4f00a8fa6385ead136b8 100644 (file)
 struct _EmpathyContactManagerPriv {
        GHashTable     *lists;
        MissionControl *mc;
-       gboolean        setup;
 };
 
-typedef struct {
-       const gchar *old_group;
-       const gchar *new_group;
-} ContactManagerRenameGroupData;
-
-typedef struct {
-       EmpathyContact *contact;
-       const gchar   *id;
-} ContactManagerFindData;
-
-static void           empathy_contact_manager_class_init   (EmpathyContactManagerClass      *klass);
-static void           contact_manager_iface_init           (EmpathyContactListIface         *iface);
-static void           empathy_contact_manager_init         (EmpathyContactManager           *manager);
-static void           contact_manager_finalize             (GObject                         *object);
-static void           contact_manager_setup                (EmpathyContactList              *manager);
-static EmpathyContact *contact_manager_find                 (EmpathyContactList              *manager,
-                                                           const gchar                     *id);
-static void           contact_manager_add                  (EmpathyContactList              *manager,
-                                                           EmpathyContact                   *contact,
-                                                           const gchar                     *message);
-static void           contact_manager_remove               (EmpathyContactList              *manager,
-                                                           EmpathyContact                   *contact,
-                                                           const gchar                     *message);
-static GList *        contact_manager_get_members          (EmpathyContactList              *manager);
-static GList *        contact_manager_get_local_pending    (EmpathyContactList              *manager);
-static void           contact_manager_process_pending      (EmpathyContactList              *manager,
-                                                           EmpathyContact                   *contact,
-                                                           gboolean                         accept);
-static void           contact_manager_setup_foreach        (McAccount                       *account,
-                                                           EmpathyTpContactList            *list,
-                                                           EmpathyContactManager           *manager);
-static gboolean       contact_manager_find_foreach         (McAccount                       *account,
-                                                           EmpathyTpContactList            *list,
-                                                           ContactManagerFindData          *data);
-static void           contact_manager_add_account          (EmpathyContactManager           *manager,
-                                                           McAccount                       *account);
-static void           contact_manager_added_cb             (EmpathyTpContactList            *list,
-                                                           EmpathyContact                   *contact,
-                                                           EmpathyContactManager           *manager);
-static void           contact_manager_removed_cb           (EmpathyTpContactList            *list,
-                                                           EmpathyContact                   *contact,
-                                                           EmpathyContactManager           *manager);
-static void           contact_manager_local_pending_cb     (EmpathyTpContactList            *list,
-                                                           EmpathyContact                   *contact,
-                                                           const gchar                     *message,
-                                                           EmpathyContactManager           *manager);
-static void           contact_manager_destroy_cb           (EmpathyTpContactList            *list,
-                                                           EmpathyContactManager           *manager);
-static void           contact_manager_rename_group_foreach (McAccount                       *account,
-                                                           EmpathyTpContactList            *list,
-                                                           ContactManagerRenameGroupData   *data);
-static void           contact_manager_get_groups_foreach   (McAccount                       *account,
-                                                           EmpathyTpContactList            *list,
-                                                           GList                          **all_groups);
-static void           contact_manager_get_members_foreach  (McAccount                       *account,
-                                                           EmpathyTpContactList            *list,
-                                                           GList                          **contacts);
-static void           contact_manager_get_local_pending_foreach (McAccount                  *account,
-                                                           EmpathyTpContactList            *list,
-                                                           GList                          **contacts);
-static void           contact_manager_status_changed_cb    (MissionControl                  *mc,
-                                                           TelepathyConnectionStatus        status,
-                                                           McPresence                       presence,
-                                                           TelepathyConnectionStatusReason  reason,
-                                                           const gchar                     *unique_name,
-                                                           EmpathyContactManager           *manager);
+static void empathy_contact_manager_class_init (EmpathyContactManagerClass *klass);
+static void empathy_contact_manager_init       (EmpathyContactManager      *manager);
+static void contact_manager_iface_init         (EmpathyContactListIface    *iface);
 
 G_DEFINE_TYPE_WITH_CODE (EmpathyContactManager, empathy_contact_manager, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CONTACT_LIST,
                                                contact_manager_iface_init));
 
 static void
-empathy_contact_manager_class_init (EmpathyContactManagerClass *klass)
+contact_manager_members_changed_cb (EmpathyTpContactList  *list,
+                                   EmpathyContact        *contact,
+                                   EmpathyContact        *actor,
+                                   guint                  reason,
+                                   gchar                 *message,
+                                   gboolean               is_member,
+                                   EmpathyContactManager *manager)
 {
-       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       g_signal_emit_by_name (manager, "members-changed",
+                              contact, actor, reason, message, is_member);
+}
 
-       object_class->finalize = contact_manager_finalize;
+static void
+contact_manager_pendings_changed_cb (EmpathyTpContactList  *list,
+                                    EmpathyContact        *contact,
+                                    EmpathyContact        *actor,
+                                    guint                  reason,
+                                    gchar                 *message,
+                                    gboolean               is_pending,
+                                    EmpathyContactManager *manager)
+{
+       g_signal_emit_by_name (manager, "pendings-changed",
+                              contact, actor, reason, message, is_pending);
+}
 
-       g_type_class_add_private (object_class, sizeof (EmpathyContactManagerPriv));
+static void
+contact_manager_groups_changed_cb (EmpathyTpContactList  *list,
+                                  EmpathyContact        *contact,
+                                  gchar                 *group,
+                                  gboolean               is_member,
+                                  EmpathyContactManager *manager)
+{
+       g_signal_emit_by_name (manager, "groups-changed",
+                              contact, group, is_member);
 }
 
+static void contact_manager_destroy_cb (EmpathyTpContactList  *list,
+                                       EmpathyContactManager *manager);
+
 static void
-contact_manager_iface_init (EmpathyContactListIface *iface)
+contact_manager_disconnect_foreach (gpointer key,
+                                   gpointer value,
+                                   gpointer user_data)
 {
-       iface->setup             = contact_manager_setup;
-       iface->find              = contact_manager_find;
-       iface->add               = contact_manager_add;
-       iface->remove            = contact_manager_remove;
-       iface->get_members       = contact_manager_get_members;
-       iface->get_local_pending = contact_manager_get_local_pending;
-       iface->process_pending   = contact_manager_process_pending;
+       EmpathyTpContactList  *list = value;
+       EmpathyContactManager *manager = user_data;
+
+       /* Disconnect signals from the list */
+       g_signal_handlers_disconnect_by_func (list,
+                                             contact_manager_members_changed_cb,
+                                             manager);
+       g_signal_handlers_disconnect_by_func (list,
+                                             contact_manager_pendings_changed_cb,
+                                             manager);
+       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)
+{
+       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+       McAccount                 *account;
+
+       account = empathy_tp_contact_list_get_account (list);
+
+       empathy_debug (DEBUG_DOMAIN, "Removing account: %s",
+                      mc_account_get_display_name (account));
+
+       contact_manager_disconnect_foreach (account, list, manager);
+       g_hash_table_remove (priv->lists, account);
+}
+
+static void
+contact_manager_add_account (EmpathyContactManager *manager,
+                            McAccount             *account)
+{
+       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+       EmpathyTpContactList      *list;
+
+       if (g_hash_table_lookup (priv->lists, account)) {
+               return;
+       }
+
+       empathy_debug (DEBUG_DOMAIN, "Adding new account: %s",
+                      mc_account_get_display_name (account));
+
+       list = empathy_tp_contact_list_new (account);
+       if (!list) {
+               return;
+       }
+
+       g_hash_table_insert (priv->lists, g_object_ref (account), list);
+
+       /* Connect signals */
+       g_signal_connect (list, "members-changed",
+                         G_CALLBACK (contact_manager_members_changed_cb),
+                         manager);
+       g_signal_connect (list, "pendings-changed",
+                         G_CALLBACK (contact_manager_pendings_changed_cb),
+                         manager);
+       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_status_changed_cb (MissionControl                  *mc,
+                                  TelepathyConnectionStatus        status,
+                                  McPresence                       presence,
+                                  TelepathyConnectionStatusReason  reason,
+                                  const gchar                     *unique_name,
+                                  EmpathyContactManager           *manager)
+{
+       McAccount *account;
+
+       if (status != TP_CONN_STATUS_CONNECTED) {
+               /* We only care about newly connected accounts */
+               return;
+       }
+
+       account = mc_account_lookup (unique_name);
+       contact_manager_add_account (manager, account);
+       g_object_unref (account);
+}
+
+static void
+contact_manager_finalize (GObject *object)
+{
+       EmpathyContactManagerPriv *priv = GET_PRIV (object);
+
+       g_hash_table_foreach (priv->lists,
+                             contact_manager_disconnect_foreach,
+                             object);
+       g_hash_table_destroy (priv->lists);
+       g_object_unref (priv->mc);
+}
+
+static void
+empathy_contact_manager_class_init (EmpathyContactManagerClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = contact_manager_finalize;
+
+       g_type_class_add_private (object_class, sizeof (EmpathyContactManagerPriv));
 }
 
 static void
@@ -158,27 +229,12 @@ empathy_contact_manager_init (EmpathyContactManager *manager)
        /* Get ContactList for existing connections */
        accounts = mission_control_get_online_connections (priv->mc, NULL);
        for (l = accounts; l; l = l->next) {
-               McAccount *account;
-
-               account = l->data;
-               contact_manager_add_account (manager, account);
-               
-               g_object_unref (account);
+               contact_manager_add_account (manager, l->data);
+               g_object_unref (l->data);
        }
        g_slist_free (accounts);
 }
 
-static void
-contact_manager_finalize (GObject *object)
-{
-       EmpathyContactManagerPriv *priv;
-
-       priv = GET_PRIV (object);
-
-       g_hash_table_destroy (priv->lists);
-       g_object_unref (priv->mc);
-}
-
 EmpathyContactManager *
 empathy_contact_manager_new (void)
 {
@@ -194,62 +250,28 @@ empathy_contact_manager_new (void)
        return manager;
 }
 
-static void
-contact_manager_setup (EmpathyContactList *manager)
-{
-       EmpathyContactManagerPriv *priv;
-
-       g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
-
-       priv = GET_PRIV (manager);
-
-       if (priv->setup) {
-               /* Already done */
-               return;
-       }
-
-       g_hash_table_foreach (priv->lists,
-                             (GHFunc) contact_manager_setup_foreach,
-                             manager);
-
-       priv->setup = TRUE;
-}
-
-static EmpathyContact *
-contact_manager_find (EmpathyContactList *manager,
-                     const gchar        *id)
+EmpathyTpContactList *
+empathy_contact_manager_get_list (EmpathyContactManager *manager,
+                                 McAccount             *account)
 {
-       EmpathyContactManagerPriv *priv;
-       ContactManagerFindData     data;
+       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
 
        g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
-       g_return_val_if_fail (id != NULL, NULL);
-
-       priv = GET_PRIV (manager);
-
-       data.contact = NULL;
-       data.id = id;
-
-       g_hash_table_find (priv->lists,
-                          (GHRFunc) contact_manager_find_foreach,
-                          &data);
+       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
 
-       return data.contact;
+       return g_hash_table_lookup (priv->lists, account);
 }
 
 static void
 contact_manager_add (EmpathyContactList *manager,
-                    EmpathyContact      *contact,
+                    EmpathyContact     *contact,
                     const gchar        *message)
 {
-       EmpathyContactManagerPriv *priv;
+       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
        EmpathyContactList        *list;
        McAccount                 *account;
 
        g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
-       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
-       priv = GET_PRIV (manager);
 
        account = empathy_contact_get_account (contact);
        list = g_hash_table_lookup (priv->lists, account);
@@ -264,14 +286,11 @@ contact_manager_remove (EmpathyContactList *manager,
                        EmpathyContact      *contact,
                        const gchar        *message)
 {
-       EmpathyContactManagerPriv *priv;
+       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
        EmpathyContactList        *list;
        McAccount                 *account;
 
        g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
-       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
-       priv = GET_PRIV (manager);
 
        account = empathy_contact_get_account (contact);
        list = g_hash_table_lookup (priv->lists, account);
@@ -281,16 +300,25 @@ contact_manager_remove (EmpathyContactList *manager,
        }
 }
 
+static void
+contact_manager_get_members_foreach (McAccount             *account,
+                                    EmpathyTpContactList  *list,
+                                    GList                **contacts)
+{
+       GList *l;
+
+       l = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (list));
+       *contacts = g_list_concat (*contacts, l);
+}
+
 static GList *
 contact_manager_get_members (EmpathyContactList *manager)
 {
-       EmpathyContactManagerPriv *priv;
+       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
        GList                     *contacts = NULL;
 
        g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
 
-       priv = GET_PRIV (manager);
-
        g_hash_table_foreach (priv->lists,
                              (GHFunc) contact_manager_get_members_foreach,
                              &contacts);
@@ -298,337 +326,169 @@ contact_manager_get_members (EmpathyContactList *manager)
        return contacts;
 }
 
-static GList *
-contact_manager_get_local_pending (EmpathyContactList *manager)
-{
-       EmpathyContactManagerPriv *priv;
-       GList                     *pending = NULL;
-
-       g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
-
-       priv = GET_PRIV (manager);
-
-       g_hash_table_foreach (priv->lists,
-                             (GHFunc) contact_manager_get_local_pending_foreach,
-                             &pending);
-
-       return pending;
-}
-
 static void
-contact_manager_process_pending (EmpathyContactList *manager,
-                                EmpathyContact      *contact,
-                                gboolean            accept)
+contact_manager_get_pendings_foreach (McAccount             *account,
+                                     EmpathyTpContactList  *list,
+                                     GList                **contacts)
 {
-       EmpathyContactManagerPriv *priv;
-       EmpathyContactList        *list;
-       McAccount                 *account;
-
-       g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
-       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
-       priv = GET_PRIV (manager);
-
-       account = empathy_contact_get_account (contact);
-       list = g_hash_table_lookup (priv->lists, account);
-
-       if (list) {
-               empathy_contact_list_process_pending (list, contact, accept);
-       }
-}
-
-EmpathyTpContactList *
-empathy_contact_manager_get_list (EmpathyContactManager *manager,
-                                 McAccount             *account)
-{
-       EmpathyContactManagerPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
-       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
-
-       priv = GET_PRIV (manager);
+       GList *l;
 
-       return g_hash_table_lookup (priv->lists, account);
+       l = empathy_contact_list_get_pendings (EMPATHY_CONTACT_LIST (list));
+       *contacts = g_list_concat (*contacts, l);
 }
 
-EmpathyContact *
-empathy_contact_manager_get_user (EmpathyContactManager *manager,
-                                 McAccount             *account)
+static GList *
+contact_manager_get_pendings (EmpathyContactList *manager)
 {
-       EmpathyContactManagerPriv *priv;
-       EmpathyTpContactList        *list;
+       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+       GList                     *contacts = NULL;
 
        g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
-       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
-
-       priv = GET_PRIV (manager);
 
-       list = g_hash_table_lookup (priv->lists, account);
-       
-       if (!list) {
-               return NULL;
-       }
+       g_hash_table_foreach (priv->lists,
+                             (GHFunc) contact_manager_get_pendings_foreach,
+                             &contacts);
 
-       return empathy_tp_contact_list_get_user (list);
+       return contacts;
 }
 
-EmpathyContact *
-empathy_contact_manager_create (EmpathyContactManager *manager,
-                               McAccount             *account,
-                               const gchar           *id)
+static void
+contact_manager_get_all_groups_foreach (McAccount             *account,
+                                       EmpathyTpContactList  *list,
+                                       GList                **all_groups)
 {
-       EmpathyContactManagerPriv *priv;
-       EmpathyTpContactList      *list;
-
-       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 (id != NULL, NULL);
-
-       priv = GET_PRIV (manager);
+       GList *groups, *l;
 
-       list = g_hash_table_lookup (priv->lists, account);
-       
-       if (!list) {
-               return NULL;
+       groups = empathy_contact_list_get_all_groups (EMPATHY_CONTACT_LIST (list));
+       for (l = groups; l; l = l->next) {
+               if (!g_list_find_custom (*all_groups,
+                                        l->data,
+                                        (GCompareFunc) strcmp)) {
+                       *all_groups = g_list_prepend (*all_groups, l->data);
+               } else {
+                       g_free (l->data);
+               }
        }
 
-       return empathy_tp_contact_list_get_from_id (list, id);
-}
-
-void
-empathy_contact_manager_rename_group (EmpathyContactManager *manager,
-                                     const gchar           *old_group,
-                                     const gchar           *new_group)
-{
-       EmpathyContactManagerPriv   *priv;
-       ContactManagerRenameGroupData  data;
-
-       g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
-       g_return_if_fail (old_group != NULL);
-       g_return_if_fail (new_group != NULL);
-
-       priv = GET_PRIV (manager);
-
-       data.old_group = old_group;
-       data.new_group = new_group;
-
-       g_hash_table_foreach (priv->lists,
-                             (GHFunc) contact_manager_rename_group_foreach,
-                             &data);
+       g_list_free (groups);
 }
 
-GList *
-empathy_contact_manager_get_groups (EmpathyContactManager *manager)
+static GList *
+contact_manager_get_all_groups (EmpathyContactList *manager)
 {
-       EmpathyContactManagerPriv *priv;
+       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
        GList                     *groups = NULL;
 
        g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
 
-       priv = GET_PRIV (manager);
-
        g_hash_table_foreach (priv->lists,
-                             (GHFunc) contact_manager_get_groups_foreach,
+                             (GHFunc) contact_manager_get_all_groups_foreach,
                              &groups);
 
        return groups;
 }
 
-static void
-contact_manager_setup_foreach (McAccount             *account,
-                              EmpathyTpContactList  *list,
-                              EmpathyContactManager *manager)
+static GList *
+contact_manager_get_groups (EmpathyContactList *manager,
+                           EmpathyContact     *contact)
 {
-       empathy_contact_list_setup (EMPATHY_CONTACT_LIST (list));
-}
+       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+       EmpathyContactList        *list;
+       McAccount                 *account;
 
-static gboolean
-contact_manager_find_foreach (McAccount              *account,
-                             EmpathyTpContactList   *list,
-                              ContactManagerFindData *data)
-{
-       data->contact = empathy_contact_list_find (EMPATHY_CONTACT_LIST (list),
-                                                  data->id);
+       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);
 
-       if (data->contact) {
-               return TRUE;
+       if (list) {
+               return empathy_contact_list_get_groups (list, contact);
        }
 
-       return FALSE;
+       return NULL;
 }
 
 static void
-contact_manager_add_account (EmpathyContactManager *manager,
-                            McAccount             *account)
+contact_manager_add_to_group (EmpathyContactList *manager,
+                             EmpathyContact     *contact,
+                             const gchar        *group)
 {
-       EmpathyContactManagerPriv *priv;
-       EmpathyTpContactList        *list;
-
-       priv = GET_PRIV (manager);
-
-       if (g_hash_table_lookup (priv->lists, account)) {
-               return;
-       }
-
-       empathy_debug (DEBUG_DOMAIN, "Adding new account: %s",
-                     mc_account_get_display_name (account));
-
-       list = empathy_tp_contact_list_new (account);
-       if (!list) {
-               return;
-       }
+       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+       EmpathyContactList        *list;
+       McAccount                 *account;
 
-       g_hash_table_insert (priv->lists, g_object_ref (account), list);
+       g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
 
-       /* Connect signals */
-       g_signal_connect (list, "contact-added",
-                         G_CALLBACK (contact_manager_added_cb),
-                         manager);
-       g_signal_connect (list, "contact-removed",
-                         G_CALLBACK (contact_manager_removed_cb),
-                         manager);
-       g_signal_connect (list, "local-pending",
-                         G_CALLBACK (contact_manager_local_pending_cb),
-                         manager);
-       g_signal_connect (list, "destroy",
-                         G_CALLBACK (contact_manager_destroy_cb),
-                         manager);
+       account = empathy_contact_get_account (contact);
+       list = g_hash_table_lookup (priv->lists, account);
 
-       if (priv->setup) {
-               empathy_contact_list_setup (EMPATHY_CONTACT_LIST (list));
+       if (list) {
+               empathy_contact_list_add_to_group (list, contact, group);
        }
 }
 
 static void
-contact_manager_added_cb (EmpathyTpContactList  *list,
-                         EmpathyContact         *contact,
-                         EmpathyContactManager *manager)
+contact_manager_remove_from_group (EmpathyContactList *manager,
+                                  EmpathyContact     *contact,
+                                  const gchar        *group)
 {
-       g_signal_emit_by_name (manager, "contact-added", contact);
-}
-
-static void
-contact_manager_removed_cb (EmpathyTpContactList  *list,
-                           EmpathyContact         *contact,
-                           EmpathyContactManager *manager)
-{
-       g_signal_emit_by_name (manager, "contact-removed", contact);
-}
-
-static void
-contact_manager_local_pending_cb (EmpathyTpContactList  *list,
-                                 EmpathyContact         *contact,
-                                 const gchar           *message,
-                                 EmpathyContactManager *manager)
-{
-       g_signal_emit_by_name (manager, "local-pending", contact, message);
-}
-
-static void
-contact_manager_destroy_cb (EmpathyTpContactList  *list,
-                           EmpathyContactManager *manager)
-{
-       EmpathyContactManagerPriv *priv;
+       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+       EmpathyContactList        *list;
        McAccount                 *account;
 
-       priv = GET_PRIV (manager);
-
-       account = empathy_tp_contact_list_get_account (list);
-
-       empathy_debug (DEBUG_DOMAIN, "Removing account: %s",
-                     mc_account_get_display_name (account));
+       g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
 
-       /* Disconnect signals from the list */
-       g_signal_handlers_disconnect_by_func (list,
-                                             contact_manager_added_cb,
-                                             manager);
-       g_signal_handlers_disconnect_by_func (list,
-                                             contact_manager_removed_cb,
-                                             manager);
-       g_signal_handlers_disconnect_by_func (list,
-                                             contact_manager_local_pending_cb,
-                                             manager);
-       g_signal_handlers_disconnect_by_func (list,
-                                             contact_manager_destroy_cb,
-                                             manager);
+       account = empathy_contact_get_account (contact);
+       list = g_hash_table_lookup (priv->lists, account);
 
-       g_hash_table_remove (priv->lists, account);
+       if (list) {
+               empathy_contact_list_remove_from_group (list, contact, group);
+       }
 }
 
-static void
-contact_manager_rename_group_foreach (McAccount                     *account,
-                                     EmpathyTpContactList          *list,
-                                     ContactManagerRenameGroupData *data)
-{
-       empathy_tp_contact_list_rename_group (list,
-                                             data->old_group,
-                                             data->new_group);
-}
+typedef struct {
+       const gchar *old_group;
+       const gchar *new_group;
+} RenameGroupData;
 
 static void
-contact_manager_get_groups_foreach (McAccount             *account,
-                                   EmpathyTpContactList  *list,
-                                   GList                **all_groups)
+contact_manager_rename_group_foreach (McAccount            *account,
+                                     EmpathyTpContactList *list,
+                                     RenameGroupData      *data)
 {
-       GList *groups, *l;
-
-       groups = empathy_tp_contact_list_get_groups (list);
-       for (l = groups; l; l = l->next) {
-               if (!g_list_find_custom (*all_groups,
-                                        l->data,
-                                        (GCompareFunc) strcmp)) {
-                       *all_groups = g_list_append (*all_groups,
-                                                    g_strdup (l->data));
-               }
-               g_free (l->data);
-       }
-
-       g_list_free (groups);
+       empathy_contact_list_rename_group (EMPATHY_CONTACT_LIST (list),
+                                          data->old_group,
+                                          data->new_group);
 }
 
 static void
-contact_manager_get_members_foreach (McAccount             *account,
-                                    EmpathyTpContactList  *list,
-                                    GList                **contacts)
+contact_manager_rename_group (EmpathyContactList *manager,
+                             const gchar        *old_group,
+                             const gchar        *new_group)
 {
-       GList *l;
-
-       l = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (list));
-       *contacts = g_list_concat (*contacts, l);
-}
+       EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+       RenameGroupData            data;
 
-static void
-contact_manager_get_local_pending_foreach (McAccount             *account,
-                                          EmpathyTpContactList  *list,
-                                          GList                **contacts)
-{
-       GList *l;
+       g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
 
-       l = empathy_contact_list_get_local_pending (EMPATHY_CONTACT_LIST (list));
-       *contacts = g_list_concat (*contacts, l);
+       data.old_group = old_group;
+       data.new_group = new_group;
+       g_hash_table_foreach (priv->lists,
+                             (GHFunc) contact_manager_rename_group_foreach,
+                             &data);
 }
 
 static void
-contact_manager_status_changed_cb (MissionControl                  *mc,
-                                  TelepathyConnectionStatus        status,
-                                  McPresence                       presence,
-                                  TelepathyConnectionStatusReason  reason,
-                                  const gchar                     *unique_name,
-                                  EmpathyContactManager           *manager)
+contact_manager_iface_init (EmpathyContactListIface *iface)
 {
-       EmpathyContactManagerPriv *priv;
-       McAccount                 *account;
-
-       priv = GET_PRIV (manager);
-
-       if (status != TP_CONN_STATUS_CONNECTED) {
-               /* We only care about newly connected accounts */
-               return;
-       }
-
-       account = mc_account_lookup (unique_name);
-       contact_manager_add_account (manager, account);
-
-       g_object_unref (account);
+       iface->add               = contact_manager_add;
+       iface->remove            = contact_manager_remove;
+       iface->get_members       = contact_manager_get_members;
+       iface->get_pendings      = contact_manager_get_pendings;
+       iface->get_all_groups    = contact_manager_get_all_groups;
+       iface->get_groups        = contact_manager_get_groups;
+       iface->add_to_group      = contact_manager_add_to_group;
+       iface->remove_from_group = contact_manager_remove_from_group;
+       iface->rename_group      = contact_manager_rename_group;
 }
 
index 768301ae72aad05fd202901acefcc395c6c9f3f0..41144cf43cfd2685425e2f4c7e05edc02380136a 100644 (file)
@@ -51,19 +51,10 @@ struct _EmpathyContactManagerClass {
        GObjectClass parent_class;
 };
 
-GType                  empathy_contact_manager_get_type     (void) G_GNUC_CONST;
-EmpathyContactManager *empathy_contact_manager_new          (void);
-EmpathyTpContactList * empathy_contact_manager_get_list     (EmpathyContactManager *manager,
-                                                            McAccount             *account);
-EmpathyContact *        empathy_contact_manager_get_user     (EmpathyContactManager *manager,
-                                                            McAccount             *account);
-EmpathyContact *        empathy_contact_manager_create       (EmpathyContactManager *manager,
-                                                            McAccount             *account,
-                                                            const gchar           *id);
-void                   empathy_contact_manager_rename_group (EmpathyContactManager *manager,
-                                                            const gchar           *old_group,
-                                                            const gchar           *new_group);
-GList *                empathy_contact_manager_get_groups   (EmpathyContactManager *manager);
+GType                  empathy_contact_manager_get_type (void) G_GNUC_CONST;
+EmpathyContactManager *empathy_contact_manager_new      (void);
+EmpathyTpContactList * empathy_contact_manager_get_list (EmpathyContactManager *manager,
+                                                        McAccount             *account);
 
 G_END_DECLS
 
index d3935ad6c80d43d6da075fe64b0de0d799054288..505e190c0d92da363739ab2c5252ae0a85840752 100644 (file)
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * Copyright (C) 2004-2007 Imendio AB
+ * Copyright (C) 2004 Imendio AB
+ * Copyright (C) 2007 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
@@ -19,6 +20,7 @@
  *
  * Authors: Mikael Hallendal <micke@imendio.com>
  *          Martyn Russell <martyn@imendio.com>
+ *          Xavier Claessens <xclaesse@gmail.com>
  */
 
 #include "config.h"
@@ -41,26 +43,26 @@ typedef struct _EmpathyContactPriv EmpathyContactPriv;
 struct _EmpathyContactPriv {
        gchar              *id;
        gchar              *name;
-       EmpathyAvatar       *avatar;
+       EmpathyAvatar      *avatar;
        McAccount          *account;
-       EmpathyPresence     *presence;
-       GList              *groups;
-       EmpathySubscription  subscription;
+       EmpathyPresence    *presence;
        guint               handle;
        gboolean            is_user;
 };
 
-static void contact_class_init    (EmpathyContactClass *class);
-static void contact_init          (EmpathyContact      *contact);
-static void contact_finalize      (GObject            *object);
-static void contact_get_property  (GObject            *object,
-                                  guint               param_id,
-                                  GValue             *value,
-                                  GParamSpec         *pspec);
-static void contact_set_property  (GObject            *object,
-                                  guint               param_id,
-                                  const GValue       *value,
-                                  GParamSpec         *pspec);
+static void empathy_contact_class_init (EmpathyContactClass *class);
+static void empathy_contact_init       (EmpathyContact      *contact);
+static void contact_finalize           (GObject             *object);
+static void contact_get_property       (GObject             *object,
+                                       guint                param_id,
+                                       GValue              *value,
+                                       GParamSpec          *pspec);
+static void contact_set_property       (GObject             *object,
+                                       guint                param_id,
+                                       const GValue        *value,
+                                       GParamSpec          *pspec);
+
+G_DEFINE_TYPE (EmpathyContact, empathy_contact, G_TYPE_OBJECT);
 
 enum {
        PROP_0,
@@ -75,41 +77,12 @@ enum {
        PROP_IS_USER
 };
 
-static gpointer parent_class = NULL;
-
-GType
-empathy_contact_get_gtype (void)
-{
-       static GType type = 0;
-
-       if (!type) {
-               static const GTypeInfo info = {
-                       sizeof (EmpathyContactClass),
-                       NULL, /* base_init */
-                       NULL, /* base_finalize */
-                       (GClassInitFunc) contact_class_init,
-                       NULL, /* class_finalize */
-                       NULL, /* class_data */
-                       sizeof (EmpathyContact),
-                       0,    /* n_preallocs */
-                       (GInstanceInitFunc) contact_init
-               };
-
-               type = g_type_register_static (G_TYPE_OBJECT,
-                                              "EmpathyContact",
-                                              &info, 0);
-       }
-
-       return type;
-}
-
 static void
-contact_class_init (EmpathyContactClass *class)
+empathy_contact_class_init (EmpathyContactClass *class)
 {
        GObjectClass *object_class;
 
        object_class = G_OBJECT_CLASS (class);
-       parent_class = g_type_class_peek_parent (class);
 
        object_class->finalize     = contact_finalize;
        object_class->get_property = contact_get_property;
@@ -155,23 +128,6 @@ contact_class_init (EmpathyContactClass *class)
                                                              EMPATHY_TYPE_PRESENCE,
                                                              G_PARAM_READWRITE));
 
-       g_object_class_install_property (object_class,
-                                        PROP_GROUPS,
-                                        g_param_spec_pointer ("groups",
-                                                              "Contact groups",
-                                                              "Groups of contact",
-                                                              G_PARAM_READWRITE));
-
-       g_object_class_install_property (object_class,
-                                        PROP_SUBSCRIPTION,
-                                        g_param_spec_flags ("subscription",
-                                                            "Contact Subscription",
-                                                            "The subscription status of the contact",
-                                                            EMPATHY_TYPE_SUBSCRIPTION,
-                                                            EMPATHY_SUBSCRIPTION_NONE,
-                                                            G_PARAM_READWRITE));
-
-
        g_object_class_install_property (object_class,
                                         PROP_HANDLE,
                                         g_param_spec_uint ("handle",
@@ -193,7 +149,7 @@ contact_class_init (EmpathyContactClass *class)
 }
 
 static void
-contact_init (EmpathyContact *contact)
+empathy_contact_init (EmpathyContact *contact)
 {
 }
 
@@ -217,16 +173,11 @@ contact_finalize (GObject *object)
                g_object_unref (priv->presence);
        }
 
-       if (priv->groups) {
-               g_list_foreach (priv->groups, (GFunc) g_free, NULL);
-               g_list_free (priv->groups);
-       }
-
        if (priv->account) {
                g_object_unref (priv->account);
        }
 
-       (G_OBJECT_CLASS (parent_class)->finalize) (object);
+       G_OBJECT_CLASS (empathy_contact_parent_class)->finalize (object);
 }
 
 static void
@@ -257,12 +208,6 @@ contact_get_property (GObject    *object,
        case PROP_PRESENCE:
                g_value_set_object (value, priv->presence);
                break;
-       case PROP_GROUPS:
-               g_value_set_pointer (value, priv->groups);
-               break;
-       case PROP_SUBSCRIPTION:
-               g_value_set_flags (value, priv->subscription);
-               break;
        case PROP_HANDLE:
                g_value_set_uint (value, priv->handle);
                break;
@@ -306,14 +251,6 @@ contact_set_property (GObject      *object,
                empathy_contact_set_presence (EMPATHY_CONTACT (object),
                                             EMPATHY_PRESENCE (g_value_get_object (value)));
                break;
-       case PROP_GROUPS:
-               empathy_contact_set_groups (EMPATHY_CONTACT (object),
-                                          g_value_get_pointer (value));
-               break;
-       case PROP_SUBSCRIPTION:
-               empathy_contact_set_subscription (EMPATHY_CONTACT (object),
-                                                 g_value_get_flags (value));
-               break;
        case PROP_HANDLE:
                empathy_contact_set_handle (EMPATHY_CONTACT (object),
                                           g_value_get_uint (value));
@@ -338,8 +275,8 @@ empathy_contact_new (McAccount *account)
 
 EmpathyContact *
 empathy_contact_new_full (McAccount   *account,
-                        const gchar *id,
-                        const gchar *name)
+                         const gchar *id,
+                         const gchar *name)
 {
        return g_object_new (EMPATHY_TYPE_CONTACT,
                             "account", account,
@@ -364,107 +301,6 @@ empathy_contact_get_id (EmpathyContact *contact)
        return "";
 }
 
-const gchar *
-empathy_contact_get_name (EmpathyContact *contact)
-{
-       EmpathyContactPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), "");
-
-       priv = GET_PRIV (contact);
-
-       if (G_STR_EMPTY (priv->name)) {
-               return empathy_contact_get_id (contact);
-       }
-
-       return priv->name;
-}
-
-EmpathyAvatar *
-empathy_contact_get_avatar (EmpathyContact *contact)
-{
-       EmpathyContactPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
-
-       priv = GET_PRIV (contact);
-
-       return priv->avatar;
-}
-
-McAccount *
-empathy_contact_get_account (EmpathyContact *contact)
-{
-       EmpathyContactPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
-
-       priv = GET_PRIV (contact);
-
-       return priv->account;
-}
-
-EmpathyPresence *
-empathy_contact_get_presence (EmpathyContact *contact)
-{
-       EmpathyContactPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
-
-       priv = GET_PRIV (contact);
-
-       return priv->presence;
-}
-
-GList *
-empathy_contact_get_groups (EmpathyContact *contact)
-{
-       EmpathyContactPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
-
-       priv = GET_PRIV (contact);
-
-       return priv->groups;
-}
-
-EmpathySubscription
-empathy_contact_get_subscription (EmpathyContact *contact)
-{
-       EmpathyContactPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact),
-                             EMPATHY_SUBSCRIPTION_NONE);
-
-       priv = GET_PRIV (contact);
-
-       return priv->subscription;
-}
-
-guint
-empathy_contact_get_handle (EmpathyContact *contact)
-{
-       EmpathyContactPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), 0);
-
-       priv = GET_PRIV (contact);
-
-       return priv->handle;
-}
-
-gboolean
-empathy_contact_is_user (EmpathyContact *contact)
-{
-       EmpathyContactPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
-
-       priv = GET_PRIV (contact);
-
-       return priv->is_user;
-}
-
 void
 empathy_contact_set_id (EmpathyContact *contact,
                       const gchar   *id)
@@ -486,6 +322,22 @@ empathy_contact_set_id (EmpathyContact *contact,
        g_object_notify (G_OBJECT (contact), "id");
 }
 
+const gchar *
+empathy_contact_get_name (EmpathyContact *contact)
+{
+       EmpathyContactPriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), "");
+
+       priv = GET_PRIV (contact);
+
+       if (G_STR_EMPTY (priv->name)) {
+               return empathy_contact_get_id (contact);
+       }
+
+       return priv->name;
+}
+
 void
 empathy_contact_set_name (EmpathyContact *contact,
                         const gchar   *name)
@@ -507,6 +359,18 @@ empathy_contact_set_name (EmpathyContact *contact,
        g_object_notify (G_OBJECT (contact), "name");
 }
 
+EmpathyAvatar *
+empathy_contact_get_avatar (EmpathyContact *contact)
+{
+       EmpathyContactPriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+       priv = GET_PRIV (contact);
+
+       return priv->avatar;
+}
+
 void
 empathy_contact_set_avatar (EmpathyContact *contact,
                           EmpathyAvatar  *avatar)
@@ -533,9 +397,21 @@ empathy_contact_set_avatar (EmpathyContact *contact,
        g_object_notify (G_OBJECT (contact), "avatar");
 }
 
+McAccount *
+empathy_contact_get_account (EmpathyContact *contact)
+{
+       EmpathyContactPriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+       priv = GET_PRIV (contact);
+
+       return priv->account;
+}
+
 void
 empathy_contact_set_account (EmpathyContact *contact,
-                           McAccount     *account)
+                            McAccount      *account)
 {
        EmpathyContactPriv *priv;
 
@@ -556,9 +432,21 @@ empathy_contact_set_account (EmpathyContact *contact,
        g_object_notify (G_OBJECT (contact), "account");
 }
 
+EmpathyPresence *
+empathy_contact_get_presence (EmpathyContact *contact)
+{
+       EmpathyContactPriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+       priv = GET_PRIV (contact);
+
+       return priv->presence;
+}
+
 void
 empathy_contact_set_presence (EmpathyContact  *contact,
-                            EmpathyPresence *presence)
+                             EmpathyPresence *presence)
 {
        EmpathyContactPriv *priv;
 
@@ -582,34 +470,21 @@ empathy_contact_set_presence (EmpathyContact  *contact,
        g_object_notify (G_OBJECT (contact), "presence");
 }
 
-void
-empathy_contact_set_groups (EmpathyContact *contact,
-                          GList         *groups)
+guint
+empathy_contact_get_handle (EmpathyContact *contact)
 {
        EmpathyContactPriv *priv;
-       GList             *old_groups, *l;
 
-       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), 0);
 
        priv = GET_PRIV (contact);
 
-       old_groups = priv->groups;
-       priv->groups = NULL;
-
-       for (l = groups; l; l = l->next) {
-               priv->groups = g_list_append (priv->groups,
-                                             g_strdup (l->data));
-       }
-
-       g_list_foreach (old_groups, (GFunc) g_free, NULL);
-       g_list_free (old_groups);
-
-       g_object_notify (G_OBJECT (contact), "groups");
+       return priv->handle;
 }
 
 void
-empathy_contact_set_subscription (EmpathyContact      *contact,
-                                EmpathySubscription  subscription)
+empathy_contact_set_handle (EmpathyContact *contact,
+                          guint          handle)
 {
        EmpathyContactPriv *priv;
 
@@ -617,32 +492,25 @@ empathy_contact_set_subscription (EmpathyContact      *contact,
 
        priv = GET_PRIV (contact);
 
-       if (priv->subscription == subscription) {
+       if (priv->handle == handle) {
                return;
        }
 
-       priv->subscription = subscription;
+       priv->handle = handle;
 
-       g_object_notify (G_OBJECT (contact), "subscription");
+       g_object_notify (G_OBJECT (contact), "handle");
 }
 
-void
-empathy_contact_set_handle (EmpathyContact *contact,
-                          guint          handle)
+gboolean
+empathy_contact_is_user (EmpathyContact *contact)
 {
        EmpathyContactPriv *priv;
 
-       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
 
        priv = GET_PRIV (contact);
 
-       if (priv->handle == handle) {
-               return;
-       }
-
-       priv->handle = handle;
-
-       g_object_notify (G_OBJECT (contact), "handle");
+       return priv->is_user;
 }
 
 void
@@ -664,43 +532,6 @@ empathy_contact_set_is_user (EmpathyContact *contact,
        g_object_notify (G_OBJECT (contact), "is-user");
 }
 
-void
-empathy_contact_add_group (EmpathyContact *contact,
-                         const gchar   *group)
-{
-       EmpathyContactPriv *priv;
-
-       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-       g_return_if_fail (group != NULL);
-
-       priv = GET_PRIV (contact);
-
-       if (!g_list_find_custom (priv->groups, group, (GCompareFunc) strcmp)) {
-               priv->groups = g_list_prepend (priv->groups, g_strdup (group));
-               g_object_notify (G_OBJECT (contact), "groups");
-       }
-}
-
-void
-empathy_contact_remove_group (EmpathyContact *contact,
-                            const gchar   *group)
-{
-       EmpathyContactPriv *priv;
-       GList             *l;
-
-       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-       g_return_if_fail (group != NULL);
-
-       priv = GET_PRIV (contact);
-
-       l = g_list_find_custom (priv->groups, group, (GCompareFunc) strcmp);
-       if (l) {
-               g_free (l->data);
-               priv->groups = g_list_delete_link (priv->groups, l);
-               g_object_notify (G_OBJECT (contact), "groups");
-       }
-}
-
 gboolean
 empathy_contact_is_online (EmpathyContact *contact)
 {
@@ -717,24 +548,6 @@ empathy_contact_is_online (EmpathyContact *contact)
        return (empathy_presence_get_state (priv->presence) > MC_PRESENCE_OFFLINE);
 }
 
-gboolean
-empathy_contact_is_in_group (EmpathyContact *contact,
-                           const gchar   *group)
-{
-       EmpathyContactPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
-       g_return_val_if_fail (!G_STR_EMPTY (group), FALSE);
-
-       priv = GET_PRIV (contact);
-
-       if (g_list_find_custom (priv->groups, group, (GCompareFunc) strcmp)) {
-               return TRUE;
-       }
-
-       return FALSE;
-}
-
 const gchar *
 empathy_contact_get_status (EmpathyContact *contact)
 {
index b32d451bbd5cb2444eb1209243d194f07b1b2dba..87a26f0dd9de793f827d0994db662402c112019f 100644 (file)
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2004 Imendio AB
+ * Copyright (C) 2007 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
  * 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: Mikael Hallendal <micke@imendio.com>
+ *          Martyn Russell <martyn@imendio.com>
+ *          Xavier Claessens <xclaesse@gmail.com>
  */
 
 #ifndef __EMPATHY_CONTACT_H__
@@ -30,7 +35,7 @@
 
 G_BEGIN_DECLS
 
-#define EMPATHY_TYPE_CONTACT         (empathy_contact_get_gtype ())
+#define EMPATHY_TYPE_CONTACT         (empathy_contact_get_type ())
 #define EMPATHY_CONTACT(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_CONTACT, EmpathyContact))
 #define EMPATHY_CONTACT_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_CONTACT, EmpathyContactClass))
 #define EMPATHY_IS_CONTACT(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_CONTACT))
@@ -48,57 +53,37 @@ struct _EmpathyContactClass {
        GObjectClass parent_class;
 };
 
-typedef enum {
-       EMPATHY_SUBSCRIPTION_NONE = 0,
-       EMPATHY_SUBSCRIPTION_TO   = 1 << 0,     /* We send our presence to that contact */
-       EMPATHY_SUBSCRIPTION_FROM = 1 << 1,     /* That contact sends his presence to us */
-       EMPATHY_SUBSCRIPTION_BOTH = EMPATHY_SUBSCRIPTION_TO | EMPATHY_SUBSCRIPTION_FROM
-} EmpathySubscription;
-
-GType              empathy_contact_get_gtype                 (void) G_GNUC_CONST;
-
-EmpathyContact *    empathy_contact_new                       (McAccount          *account);
-EmpathyContact *    empathy_contact_new_full                  (McAccount          *account,
-                                                            const gchar        *id,
-                                                            const gchar        *name);
-const gchar *      empathy_contact_get_id                    (EmpathyContact      *contact);
-const gchar *      empathy_contact_get_name                  (EmpathyContact      *contact);
-EmpathyAvatar *     empathy_contact_get_avatar                (EmpathyContact      *contact);
-McAccount *        empathy_contact_get_account               (EmpathyContact      *contact);
-EmpathyPresence *   empathy_contact_get_presence              (EmpathyContact      *contact);
-GList *            empathy_contact_get_groups                (EmpathyContact      *contact);
-EmpathySubscription empathy_contact_get_subscription          (EmpathyContact      *contact);
-guint              empathy_contact_get_handle                (EmpathyContact      *contact);
-gboolean           empathy_contact_is_user                   (EmpathyContact      *contact);
-void               empathy_contact_set_id                    (EmpathyContact      *contact,
-                                                            const gchar        *id);
-void               empathy_contact_set_name                  (EmpathyContact      *contact,
-                                                            const gchar        *name);
-void               empathy_contact_set_avatar                (EmpathyContact      *contact,
-                                                            EmpathyAvatar       *avatar);
-void               empathy_contact_set_account               (EmpathyContact      *contact,
-                                                            McAccount          *account);
-void               empathy_contact_set_presence              (EmpathyContact      *contact,
-                                                            EmpathyPresence     *presence);
-void               empathy_contact_set_groups                (EmpathyContact      *contact,
-                                                            GList              *categories);
-void               empathy_contact_set_subscription          (EmpathyContact      *contact,
-                                                            EmpathySubscription  subscription);
-void               empathy_contact_set_handle                (EmpathyContact      *contact,
-                                                            guint               handle);
-void               empathy_contact_set_is_user               (EmpathyContact      *contact,
-                                                            gboolean            is_user);
-void               empathy_contact_add_group                 (EmpathyContact      *contact,
-                                                            const gchar        *group);
-void               empathy_contact_remove_group              (EmpathyContact      *contact,
-                                                            const gchar        *group);
-gboolean           empathy_contact_is_online                 (EmpathyContact      *contact);
-gboolean           empathy_contact_is_in_group               (EmpathyContact      *contact,
-                                                            const gchar        *group);
-const gchar *      empathy_contact_get_status                (EmpathyContact      *contact);
-gboolean           empathy_contact_equal                     (gconstpointer       v1,
-                                                            gconstpointer       v2);
-guint              empathy_contact_hash                      (gconstpointer       key);
+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);
+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);
+void              empathy_contact_set_name     (EmpathyContact  *contact,
+                                               const gchar     *name);
+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);
+EmpathyPresence * empathy_contact_get_presence (EmpathyContact  *contact);
+void              empathy_contact_set_presence (EmpathyContact  *contact,
+                                               EmpathyPresence *presence);
+guint             empathy_contact_get_handle   (EmpathyContact  *contact);
+void              empathy_contact_set_handle   (EmpathyContact  *contact,
+                                               guint            handle);
+gboolean          empathy_contact_is_user      (EmpathyContact  *contact);
+void              empathy_contact_set_is_user  (EmpathyContact  *contact,
+                                               gboolean         is_user);
+gboolean          empathy_contact_is_online    (EmpathyContact  *contact);
+const gchar *     empathy_contact_get_status   (EmpathyContact  *contact);
+gboolean          empathy_contact_equal        (gconstpointer    v1,
+                                               gconstpointer    v2);
+guint             empathy_contact_hash         (gconstpointer    key);
 
 G_END_DECLS
 
index e234ec521c383531af83f1ce17230cd1d6b4e38b..e47f50fb83ac6c6345781a5257b00cc6940aa9ad 100644 (file)
@@ -634,24 +634,22 @@ log_manager_get_dir (EmpathyLogManager *manager,
 {
        const gchar *account_id;
        gchar       *basedir;
-       gchar       *str;
 
        account_id = mc_account_get_unique_name (account);
-       basedir = 
-       str = g_build_path (G_DIR_SEPARATOR_S,
-                           log_manager_get_basedir (manager),
-                           account_id,
-                           chat_id,
-                           NULL);
 
        if (chatroom) {
                basedir = g_build_path (G_DIR_SEPARATOR_S,
-                                       str,
+                                       log_manager_get_basedir (manager),
+                                       account_id,
                                        LOG_DIR_CHATROOMS,
+                                       chat_id,
                                        NULL);
-               g_free (str);
        } else {
-               basedir = str;
+               basedir = g_build_path (G_DIR_SEPARATOR_S,
+                                       log_manager_get_basedir (manager),
+                                       account_id,
+                                       chat_id,
+                                       NULL);
        }
 
        return basedir;
index 3b36b7be08a1495829b7816f3d552f156331c651..383bfbbedd0b98f6ca3f6a20957eb09801ee7b7b 100644 (file)
@@ -1,10 +1,14 @@
 VOID:OBJECT,UINT
-VOID:OBJECT,OBJECT
-VOID:OBJECT,OBJECT,UINT
 VOID:OBJECT,BOOLEAN
-VOID:OBJECT,STRING,STRING
+VOID:OBJECT,POINTER
 VOID:OBJECT,STRING
-VOID:POINTER,UINT,UINT,STRING
+VOID:OBJECT,STRING,STRING
+VOID:OBJECT,STRING,BOOLEAN
+VOID:OBJECT,OBJECT
+VOID:OBJECT,OBJECT,UINT
+VOID:OBJECT,OBJECT,UINT,STRING
+VOID:OBJECT,OBJECT,UINT,STRING,BOOLEAN
+VOID:OBJECT,OBJECT,STRING
 VOID:INT,STRING
 VOID:UINT,BOOLEAN
 
index 077afe36e31dc8f5e14f9845282bfbdaf81575c8..fc943f0c610b23494ffd97a22f582ae1ab63da2a 100644 (file)
@@ -31,8 +31,7 @@
 #include <libtelepathy/tp-props-iface.h>
 
 #include "empathy-tp-chat.h"
-#include "empathy-contact-manager.h"
-#include "empathy-tp-contact-list.h"
+#include "empathy-contact-factory.h"
 #include "empathy-marshal.h"
 #include "empathy-debug.h"
 #include "empathy-time.h"
@@ -44,8 +43,8 @@
 #define DEBUG_DOMAIN "TpChat"
 
 struct _EmpathyTpChatPriv {
-       EmpathyTpContactList  *list;
-       EmpathyContactManager *manager;
+       EmpathyContactFactory *factory;
+       EmpathyContact        *user;
        McAccount             *account;
        gchar                 *id;
        MissionControl        *mc;
@@ -363,11 +362,11 @@ tp_chat_finalize (GObject *object)
                g_object_unref (priv->tp_chan);
        }
 
-       if (priv->manager) {
-               g_object_unref (priv->manager);
+       if (priv->factory) {
+               g_object_unref (priv->factory);
        }
-       if (priv->list) {
-               g_object_unref (priv->list);
+       if (priv->user) {
+               g_object_unref (priv->user);
        }
        if (priv->account) {
                g_object_unref (priv->account);
@@ -392,10 +391,9 @@ tp_chat_constructor (GType                  type,
 
        priv = GET_PRIV (chat);
 
-       priv->manager = empathy_contact_manager_new ();
-       priv->list = empathy_contact_manager_get_list (priv->manager, priv->account);
+       priv->factory = empathy_contact_factory_new ();
+       priv->user = empathy_contact_factory_get_user (priv->factory, priv->account);
        priv->mc = empathy_mission_control_new ();
-       g_object_ref (priv->list);
 
        priv->text_iface = tp_chan_get_interface (priv->tp_chan,
                                                  TELEPATHY_CHAN_IFACE_TEXT_QUARK);
@@ -750,12 +748,10 @@ empathy_tp_chat_get_id (EmpathyTpChat *chat)
 
        priv = GET_PRIV (chat);
 
-       if (priv->id) {
-               return priv->id;
+       if (!priv->id) {
+               priv->id = empathy_inspect_channel (priv->account, priv->tp_chan);
        }
 
-       priv->id = empathy_inspect_channel (priv->account, priv->tp_chan);
-
        return priv->id;
 }
 
@@ -885,7 +881,9 @@ tp_chat_state_changed_cb (DBusGProxy                *chat_state_iface,
 
        priv = GET_PRIV (chat);
 
-       contact = empathy_tp_contact_list_get_from_handle (priv->list, handle);
+       contact = empathy_contact_factory_get_from_handle (priv->factory,
+                                                          priv->account,
+                                                          handle);
 
        empathy_debug (DEBUG_DOMAIN, "Chat state changed for %s (%d): %d",
                      empathy_contact_get_name (contact),
@@ -906,22 +904,21 @@ tp_chat_build_message (EmpathyTpChat *chat,
        EmpathyTpChatPriv *priv;
        EmpathyMessage    *message;
        EmpathyContact    *sender;
-       EmpathyContact    *receiver;
 
        priv = GET_PRIV (chat);
 
-       receiver = empathy_tp_contact_list_get_user (priv->list);
        if (from_handle == 0) {
-               sender = g_object_ref (receiver);
+               sender = g_object_ref (priv->user);
        } else {
-               sender = empathy_tp_contact_list_get_from_handle (priv->list,
+               sender = empathy_contact_factory_get_from_handle (priv->factory,
+                                                                 priv->account,
                                                                  from_handle);
        }
 
        message = empathy_message_new (message_body);
        empathy_message_set_type (message, type);
        empathy_message_set_sender (message, sender);
-       empathy_message_set_receiver (message, receiver);
+       empathy_message_set_receiver (message, priv->user);
        empathy_message_set_timestamp (message, (EmpathyTime) timestamp);
 
        g_object_unref (sender);
index 32716865d046ea67d5cf5967332f2d9b07ee7e31..72f0839422416c09c8634e63e7135790ffe185f9 100644 (file)
@@ -23,9 +23,8 @@
 #include <config.h>
 
 #include "empathy-tp-chatroom.h"
-#include "empathy-tp-contact-list.h"
 #include "empathy-contact-list.h"
-#include "empathy-contact-manager.h"
+#include "empathy-contact-factory.h"
 #include "empathy-tp-group.h"
 #include "empathy-utils.h"
 #include "empathy-debug.h"
@@ -36,8 +35,7 @@
 #define DEBUG_DOMAIN "TpChatroom"
 
 struct _EmpathyTpChatroomPriv {
-       EmpathyContactManager *manager;
-       EmpathyTpContactList  *list;
+       EmpathyContactFactory *factory;
        EmpathyTpGroup        *group;
 
        gboolean               is_invited;
@@ -49,21 +47,18 @@ static void            empathy_tp_chatroom_class_init (EmpathyTpChatroomClass  *
 static void            tp_chatroom_iface_init         (EmpathyContactListIface *iface);
 static void            empathy_tp_chatroom_init       (EmpathyTpChatroom       *chatroom);
 static void            tp_chatroom_finalize           (GObject                 *object);
-static void            tp_chatroom_members_added_cb   (EmpathyTpGroup          *group,
-                                                      GArray                  *handles,
-                                                      guint                    actor_handle,
+static void            tp_chatroom_member_added_cb    (EmpathyTpGroup          *group,
+                                                      EmpathyContact          *contact,
+                                                      EmpathyContact          *actor,
                                                       guint                    reason,
                                                       const gchar             *message,
-                                                      EmpathyTpChatroom       *list);
-static void            tp_chatroom_members_removed_cb (EmpathyTpGroup          *group,
-                                                      GArray                  *handles,
-                                                      guint                    actor_handle,
+                                                      EmpathyTpChatroom       *chatroom);
+static void            tp_chatroom_member_removed_cb  (EmpathyTpGroup          *group,
+                                                      EmpathyContact          *contact,
+                                                      EmpathyContact          *actor,
                                                       guint                    reason,
                                                       const gchar             *message,
-                                                      EmpathyTpChatroom       *list);
-static void            tp_chatroom_setup              (EmpathyContactList      *list);
-static EmpathyContact * tp_chatroom_find               (EmpathyContactList      *list,
-                                                      const gchar             *id);
+                                                      EmpathyTpChatroom       *chatroom);
 static void            tp_chatroom_add                (EmpathyContactList      *list,
                                                       EmpathyContact           *contact,
                                                       const gchar             *message);
@@ -89,8 +84,6 @@ empathy_tp_chatroom_class_init (EmpathyTpChatroomClass *klass)
 static void
 tp_chatroom_iface_init (EmpathyContactListIface *iface)
 {
-       iface->setup       = tp_chatroom_setup;
-       iface->find        = tp_chatroom_find;
        iface->add         = tp_chatroom_add;
        iface->remove      = tp_chatroom_remove;
        iface->get_members = tp_chatroom_get_members;
@@ -111,7 +104,7 @@ tp_chatroom_finalize (GObject *object)
        priv = GET_PRIV (chatroom);
 
        g_object_unref (priv->group);
-       g_object_unref (priv->manager);
+       g_object_unref (priv->factory);
 
        if (priv->invitor) {
                g_object_unref (priv->invitor);
@@ -129,7 +122,7 @@ empathy_tp_chatroom_new (McAccount *account,
        EmpathyTpChatroomPriv *priv;
        EmpathyTpChatroom     *chatroom;
        GList                 *members, *l;
-       guint                  self_handle;
+       EmpathyContact        *user;
 
        g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
        g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL);
@@ -141,40 +134,41 @@ empathy_tp_chatroom_new (McAccount *account,
 
        priv = GET_PRIV (chatroom);
 
-       priv->manager = empathy_contact_manager_new ();
-       priv->list = empathy_contact_manager_get_list (priv->manager, account);
+       priv->factory = empathy_contact_factory_new ();
        priv->group = empathy_tp_group_new (account, tp_chan);
 
-       g_signal_connect (priv->group, "members-added",
-                         G_CALLBACK (tp_chatroom_members_added_cb),
+       g_signal_connect (priv->group, "member-added",
+                         G_CALLBACK (tp_chatroom_member_added_cb),
                          chatroom);
-       g_signal_connect (priv->group, "members-removed",
-                         G_CALLBACK (tp_chatroom_members_removed_cb),
+       g_signal_connect (priv->group, "member-removed",
+                         G_CALLBACK (tp_chatroom_member_removed_cb),
                          chatroom);
 
        /* Check if we are invited to join the chat */
-       self_handle = empathy_tp_group_get_self_handle (priv->group);
-       members = empathy_tp_group_get_local_pending_members_with_info (priv->group);
+       user = empathy_tp_group_get_self_contact (priv->group);
+       members = empathy_tp_group_get_local_pendings (priv->group);
        for (l = members; l; l = l->next) {
-               EmpathyTpGroupInfo *info;
+               EmpathyPendingInfo *info;
 
                info = l->data;
 
-               if (info->member != self_handle) {
+               if (!empathy_contact_equal (user, info->member)) {
                        continue;
                }
 
-               priv->invitor = empathy_tp_contact_list_get_from_handle (priv->list,
-                                                                        info->actor);
+               priv->invitor = g_object_ref (info->actor);
                priv->invit_message = g_strdup (info->message);
                priv->is_invited = TRUE;
 
-               empathy_debug (DEBUG_DOMAIN, "We are invited to join by %s: %s",
-                             empathy_contact_get_name (priv->invitor),
-                             priv->invit_message);
+               empathy_debug (DEBUG_DOMAIN, "We are invited to join by %s (%d): %s",
+                              empathy_contact_get_id (priv->invitor),
+                              empathy_contact_get_handle (priv->invitor),
+                              priv->invit_message);
        }
 
-       empathy_tp_group_info_list_free (members);
+       g_list_foreach (members, (GFunc) empathy_pending_info_free, NULL);
+       g_list_free (members);
+       g_object_unref (user);
 
        return chatroom;
 }
@@ -204,7 +198,7 @@ void
 empathy_tp_chatroom_accept_invitation (EmpathyTpChatroom *chatroom)
 {
        EmpathyTpChatroomPriv *priv;
-       guint                  self_handle;
+       EmpathyContact        *user;
 
        g_return_if_fail (EMPATHY_IS_TP_CHATROOM (chatroom));
 
@@ -220,80 +214,42 @@ empathy_tp_chatroom_accept_invitation (EmpathyTpChatroom *chatroom)
        priv->invit_message = NULL;
 
        /* Add ourself in the members of the room */
-       self_handle = empathy_tp_group_get_self_handle (priv->group);
-       empathy_tp_group_add_member (priv->group, self_handle,
-                                          "Just for fun");
+       user = empathy_tp_group_get_self_contact (priv->group);
+       empathy_tp_group_add_member (priv->group, user, "");
+       g_object_unref (user);
 }
 
 void
 empathy_tp_chatroom_set_topic (EmpathyTpChatroom *chatroom,
                               const gchar       *topic)
 {
+       /* FIXME: not implemented */
 }
 
 static void
-tp_chatroom_members_added_cb (EmpathyTpGroup    *group,
-                             GArray            *handles,
-                             guint              actor_handle,
-                             guint              reason,
-                             const gchar       *message,
-                             EmpathyTpChatroom *chatroom)
+tp_chatroom_member_added_cb (EmpathyTpGroup    *group,
+                            EmpathyContact    *contact,
+                            EmpathyContact    *actor,
+                            guint              reason,
+                            const gchar       *message,
+                            EmpathyTpChatroom *chatroom)
 {
-       EmpathyTpChatroomPriv *priv;
-       GList                 *contacts, *l;
-
-       priv = GET_PRIV (chatroom);
-
-       contacts = empathy_tp_contact_list_get_from_handles (priv->list, handles);
-       for (l = contacts; l; l = l->next) {
-               EmpathyContact *contact;
-
-               contact = l->data;
-
-               g_signal_emit_by_name (chatroom, "contact-added", contact);
-
-               g_object_unref (contact);
-       }
-       g_list_free (contacts);
-}
-
-static void
-tp_chatroom_members_removed_cb (EmpathyTpGroup    *group,
-                               GArray            *handles,
-                               guint              actor_handle,
-                               guint              reason,
-                               const gchar       *message,
-                               EmpathyTpChatroom *chatroom)
-{
-       EmpathyTpChatroomPriv *priv;
-       GList                 *contacts, *l;
-
-       priv = GET_PRIV (chatroom);
-
-       contacts = empathy_tp_contact_list_get_from_handles (priv->list, handles);
-       for (l = contacts; l; l = l->next) {
-               EmpathyContact *contact;
-
-               contact = l->data;
-
-               g_signal_emit_by_name (chatroom, "contact-removed", contact);
-
-               g_object_unref (contact);
-       }
-       g_list_free (contacts);
+       g_signal_emit_by_name (chatroom, "members-changed",
+                              contact, actor, reason, message,
+                              TRUE);
 }
 
 static void
-tp_chatroom_setup (EmpathyContactList *list)
-{
-       /* Nothing to do */
-}
-
-static EmpathyContact *
-tp_chatroom_find (EmpathyContactList *list,
-                 const gchar        *id)
+tp_chatroom_member_removed_cb (EmpathyTpGroup    *group,
+                              EmpathyContact    *contact,
+                              EmpathyContact    *actor,
+                              guint              reason,
+                              const gchar       *message,
+                              EmpathyTpChatroom *chatroom)
 {
-       return NULL;
+       g_signal_emit_by_name (chatroom, "members-changed",
+                              contact, actor, reason, message,
+                              FALSE);
 }
 
 static void
@@ -308,9 +264,7 @@ tp_chatroom_add (EmpathyContactList *list,
 
        priv = GET_PRIV (list);
 
-       empathy_tp_group_add_member (priv->group,
-                                    empathy_contact_get_handle (contact),
-                                    message);
+       empathy_tp_group_add_member (priv->group, contact, message);
 }
 
 static void
@@ -325,26 +279,18 @@ tp_chatroom_remove (EmpathyContactList *list,
 
        priv = GET_PRIV (list);
 
-       empathy_tp_group_remove_member (priv->group,
-                                       empathy_contact_get_handle (contact),
-                                       message);
+       empathy_tp_group_remove_member (priv->group, contact, message);
 }
 
 static GList *
 tp_chatroom_get_members (EmpathyContactList *list)
 {
        EmpathyTpChatroomPriv *priv;
-       GArray                *members;
-       GList                 *contacts;
 
        g_return_val_if_fail (EMPATHY_IS_TP_CHATROOM (list), NULL);
 
        priv = GET_PRIV (list);
 
-       members = empathy_tp_group_get_members (priv->group);
-       contacts = empathy_tp_contact_list_get_from_handles (priv->list, members);
-       g_array_free (members, TRUE);
-
-       return contacts;
+       return empathy_tp_group_get_members (priv->group);
 }
 
index a5c54b74e6158ef4b0076a15d8a3313dd0e50059..16ecad80774dd46823e5fcff442151ae19bd411b 100644 (file)
@@ -30,9 +30,6 @@
 #include <libtelepathy/tp-conn.h>
 #include <libtelepathy/tp-chan.h>
 #include <libtelepathy/tp-chan-type-contact-list-gen.h>
-#include <libtelepathy/tp-conn-iface-aliasing-gen.h>
-#include <libtelepathy/tp-conn-iface-presence-gen.h>
-#include <libtelepathy/tp-conn-iface-avatars-gen.h>
 
 #include "empathy-tp-contact-list.h"
 #include "empathy-contact-list.h"
                       EMPATHY_TYPE_TP_CONTACT_LIST, EmpathyTpContactListPriv))
 
 #define DEBUG_DOMAIN "TpContactList"
-#define MAX_AVATAR_REQUESTS 10
 
 struct _EmpathyTpContactListPriv {
        TpConn         *tp_conn;
        McAccount      *account;
        MissionControl *mc;
-       EmpathyContact *user_contact;
-       gboolean        setup;
        const gchar    *protocol_group;
 
        EmpathyTpGroup *publish;
        EmpathyTpGroup *subscribe;
-
-       GHashTable     *groups;
-       GHashTable     *contacts;
        GList          *members;
-       GList          *local_pending;
+       GList          *pendings;
 
-       DBusGProxy     *aliasing_iface;
-       DBusGProxy     *avatars_iface;
-       DBusGProxy     *presence_iface;
+       GList          *groups;
+       GHashTable     *contacts_groups;
 };
 
 typedef enum {
        TP_CONTACT_LIST_TYPE_PUBLISH,
        TP_CONTACT_LIST_TYPE_SUBSCRIBE,
-       TP_CONTACT_LIST_TYPE_UNKNOWN,
-       TP_CONTACT_LIST_TYPE_COUNT
+       TP_CONTACT_LIST_TYPE_UNKNOWN
 } TpContactListType;
 
-typedef struct {
-       guint  handle;
-       GList *new_groups;
-} TpContactListData;
-
-typedef struct {
-       EmpathyTpContactList *list;
-       guint                 handle;
-} TpContactListAvatarRequestData;
-
-typedef struct {
-       EmpathyTpContactList *list;
-       guint                *handles;
-} TpContactListAliasesRequestData;
-
-static void               empathy_tp_contact_list_class_init       (EmpathyTpContactListClass       *klass);
-static void               tp_contact_list_iface_init               (EmpathyContactListIface         *iface);
-static void               empathy_tp_contact_list_init             (EmpathyTpContactList            *list);
-static void               tp_contact_list_finalize                 (GObject                         *object);
-static void               tp_contact_list_finalize_proxies         (EmpathyTpContactList            *list);
-static void               tp_contact_list_setup                    (EmpathyContactList              *list);
-static EmpathyContact *   tp_contact_list_find                     (EmpathyContactList              *list,
-                                                                   const gchar                     *id);
-static void               tp_contact_list_add                      (EmpathyContactList              *list,
-                                                                   EmpathyContact                  *contact,
-                                                                   const gchar                     *message);
-static void               tp_contact_list_remove                   (EmpathyContactList              *list,
-                                                                   EmpathyContact                  *contact,
-                                                                   const gchar                     *message);
-static GList *            tp_contact_list_get_members              (EmpathyContactList              *list);
-static GList *            tp_contact_list_get_local_pending        (EmpathyContactList              *list);
-static void               tp_contact_list_process_pending          (EmpathyContactList              *list,
-                                                                   EmpathyContact                  *contact,
-                                                                   gboolean                         accept);
-static void               tp_contact_list_remove_local_pending     (EmpathyTpContactList            *list,
-                                                                   EmpathyContact                  *contact);
-static void               tp_contact_list_contact_removed_foreach  (guint                            handle,
-                                                                   EmpathyContact                  *contact,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_destroy_cb               (DBusGProxy                      *proxy,
-                                                                   EmpathyTpContactList            *list);
-static gboolean           tp_contact_list_find_foreach             (guint                            handle,
-                                                                   EmpathyContact                  *contact,
-                                                                   gchar                           *id);
-static void               tp_contact_list_newchannel_cb            (DBusGProxy                      *proxy,
-                                                                   const gchar                     *object_path,
-                                                                   const gchar                     *channel_type,
-                                                                   TelepathyHandleType              handle_type,
-                                                                   guint                            channel_handle,
-                                                                   gboolean                         suppress_handle,
-                                                                   EmpathyTpContactList            *list);
-static TpContactListType  tp_contact_list_get_type                 (EmpathyTpContactList            *list,
-                                                                   EmpathyTpGroup                  *group);
-static void               tp_contact_list_added_cb                 (EmpathyTpGroup                  *group,
-                                                                   GArray                          *handles,
-                                                                   guint                            actor_handle,
-                                                                   guint                            reason,
-                                                                   const gchar                     *message,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_removed_cb               (EmpathyTpGroup                  *group,
-                                                                   GArray                          *handles,
-                                                                   guint                            actor_handle,
-                                                                   guint                            reason,
-                                                                   const gchar                     *message,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_pending_cb               (EmpathyTpGroup                  *group,
-                                                                   GArray                          *handles,
-                                                                   guint                            actor_handle,
-                                                                   guint                            reason,
-                                                                   const gchar                     *message,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_groups_updated_cb        (EmpathyContact                  *contact,
-                                                                   GParamSpec                      *param,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_name_updated_cb          (EmpathyContact                  *contact,
-                                                                   GParamSpec                      *param,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_update_groups_foreach    (gchar                           *object_path,
-                                                                   EmpathyTpGroup                  *group,
-                                                                   TpContactListData               *data);
-static EmpathyTpGroup *   tp_contact_list_get_group                (EmpathyTpContactList            *list,
-                                                                   const gchar                     *name);
-static gboolean           tp_contact_list_find_group               (gchar                           *key,
-                                                                   EmpathyTpGroup                  *group,
-                                                                   gchar                           *group_name);
-static void               tp_contact_list_get_groups_foreach       (gchar                           *key,
-                                                                   EmpathyTpGroup                  *group,
-                                                                   GList                          **groups);
-static void               tp_contact_list_group_channel_closed_cb  (TpChan                          *channel,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_group_members_added_cb   (EmpathyTpGroup                  *group,
-                                                                   GArray                          *members,
-                                                                   guint                            actor_handle,
-                                                                   guint                            reason,
-                                                                   const gchar                     *message,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_group_members_removed_cb (EmpathyTpGroup                  *group,
-                                                                   GArray                          *members,
-                                                                   guint                            actor_handle,
-                                                                   guint                            reason,
-                                                                   const gchar                     *message,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_get_info                 (EmpathyTpContactList            *list,
-                                                                   GArray                          *handles);
-static void               tp_contact_list_request_avatar           (EmpathyTpContactList            *list,
-                                                                   guint                            handle);
-static void               tp_contact_list_start_avatar_requests    (void);
-static void               tp_contact_list_avatar_update_cb         (DBusGProxy                      *proxy,
-                                                                   guint                            handle,
-                                                                   gchar                           *new_token,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_request_avatar_cb        (DBusGProxy                      *proxy,
-                                                                   GArray                          *avatar_data,
-                                                                   gchar                           *mime_type,
-                                                                   GError                          *error,
-                                                                   TpContactListAvatarRequestData  *data);
-static void               tp_contact_list_aliases_update_cb        (DBusGProxy                      *proxy,
-                                                                   GPtrArray                       *handlers,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_request_aliases_cb       (DBusGProxy                      *proxy,
-                                                                   gchar                          **contact_names,
-                                                                   GError                          *error,
-                                                                   TpContactListAliasesRequestData *data);
-static void               tp_contact_list_presence_update_cb       (DBusGProxy                      *proxy,
-                                                                   GHashTable                      *handle_table,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_parse_presence_foreach   (guint                            handle,
-                                                                   GValueArray                     *presence_struct,
-                                                                   EmpathyTpContactList            *list);
-static void               tp_contact_list_presences_table_foreach  (const gchar                     *state_str,
-                                                                   GHashTable                      *presences_table,
-                                                                   EmpathyPresence                 **presence);
-static void               tp_contact_list_status_changed_cb        (MissionControl                  *mc,
-                                                                   TelepathyConnectionStatus        status,
-                                                                   McPresence                       presence,
-                                                                   TelepathyConnectionStatusReason  reason,
-                                                                   const gchar                     *unique_name,
-                                                                   EmpathyTpContactList            *list);
-
-enum {
-       DESTROY,
-       LAST_SIGNAL
-};
-
-static guint  signals[LAST_SIGNAL];
-GList        *avatar_requests_queue = NULL;
-guint         n_avatar_requests = 0;
-
-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
-empathy_tp_contact_list_class_init (EmpathyTpContactListClass *klass)
-{
-       GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-       object_class->finalize = tp_contact_list_finalize;
-
-       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_iface_init (EmpathyContactListIface *iface)
-{
-       iface->setup             = tp_contact_list_setup;
-       iface->find              = tp_contact_list_find;
-       iface->add               = tp_contact_list_add;
-       iface->remove            = tp_contact_list_remove;
-       iface->get_members       = tp_contact_list_get_members;
-       iface->get_local_pending = tp_contact_list_get_local_pending;
-       iface->process_pending   = tp_contact_list_process_pending;
-}
-
-static void
-empathy_tp_contact_list_init (EmpathyTpContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-
-       priv = GET_PRIV (list);
-
-       priv->groups = g_hash_table_new_full (g_str_hash,
-                                             g_str_equal,
-                                             (GDestroyNotify) g_free,
-                                             (GDestroyNotify) g_object_unref);
-       priv->contacts = g_hash_table_new_full (g_direct_hash,
-                                               g_direct_equal,
-                                               NULL,
-                                               (GDestroyNotify) g_object_unref);
-}
-
-static void
-tp_contact_list_finalize (GObject *object)
-{
-       EmpathyTpContactListPriv *priv;
-       EmpathyTpContactList     *list;
-
-       list = EMPATHY_TP_CONTACT_LIST (object);
-       priv = GET_PRIV (list);
-
-       empathy_debug (DEBUG_DOMAIN, "finalize: %p", object);
-
-       dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc),
-                                       "AccountStatusChanged",
-                                       G_CALLBACK (tp_contact_list_status_changed_cb),
-                                       list);
-
-       tp_contact_list_finalize_proxies (list);
-
-       if (priv->tp_conn) {
-               g_object_unref (priv->tp_conn);
-       }
-       if (priv->subscribe) {
-               g_object_unref (priv->subscribe);
-       }
-       if (priv->publish) {
-               g_object_unref (priv->publish);
-       }
-
-       g_object_unref (priv->account);
-       g_object_unref (priv->user_contact);
-       g_object_unref (priv->mc);
-       g_hash_table_destroy (priv->groups);
-       g_hash_table_destroy (priv->contacts);
-
-       g_list_foreach (priv->local_pending, (GFunc) empathy_contact_list_info_free, NULL);
-       g_list_free (priv->local_pending);
-
-       g_list_foreach (priv->members, (GFunc) g_object_unref, NULL);
-       g_list_free (priv->members);
-
-       G_OBJECT_CLASS (empathy_tp_contact_list_parent_class)->finalize (object);
-}
-
-EmpathyTpContactList *
-empathy_tp_contact_list_new (McAccount *account)
-{
-       EmpathyTpContactListPriv *priv;
-       EmpathyTpContactList     *list;
-       MissionControl           *mc;
-       McProfile                *profile;
-       const gchar              *protocol_name;
-       guint                     handle;
-       GError                   *error = NULL;
-
-       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
-
-       mc = empathy_mission_control_new ();
-
-       if (mission_control_get_connection_status (mc, account, NULL) != 0) {
-               /* The account is not connected, nothing to do. */
-               return NULL;
-       }
-
-       list = g_object_new (EMPATHY_TYPE_TP_CONTACT_LIST, NULL);
-       priv = GET_PRIV (list);
-
-       priv->tp_conn = mission_control_get_connection (mc, account, NULL);
-       priv->account = g_object_ref (account);
-       priv->mc = mc;
-
-       /* 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 (account);
-       protocol_name = mc_profile_get_protocol_name (profile);
-       if (strcmp (protocol_name, "local-xmpp") == 0) {
-               priv->protocol_group = _("People nearby");
-       }
-       g_object_unref (profile);
-
-       g_signal_connect (priv->tp_conn, "destroy",
-                         G_CALLBACK (tp_contact_list_destroy_cb),
-                         list);
-       dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc),
-                                    "AccountStatusChanged",
-                                    G_CALLBACK (tp_contact_list_status_changed_cb),
-                                    list, NULL);
-
-       priv->aliasing_iface = tp_conn_get_interface (priv->tp_conn,
-                                                     TELEPATHY_CONN_IFACE_ALIASING_QUARK);
-       priv->avatars_iface = tp_conn_get_interface (priv->tp_conn,
-                                                    TELEPATHY_CONN_IFACE_AVATARS_QUARK);
-       priv->presence_iface = tp_conn_get_interface (priv->tp_conn,
-                                                     TELEPATHY_CONN_IFACE_PRESENCE_QUARK);
-
-       if (priv->aliasing_iface) {
-               dbus_g_proxy_connect_signal (priv->aliasing_iface,
-                                            "AliasesChanged",
-                                            G_CALLBACK (tp_contact_list_aliases_update_cb),
-                                            list, NULL);
-       }
-
-       if (priv->avatars_iface) {
-               dbus_g_proxy_connect_signal (priv->avatars_iface,
-                                            "AvatarUpdated",
-                                            G_CALLBACK (tp_contact_list_avatar_update_cb),
-                                            list, NULL);
-       }
-
-       if (priv->presence_iface) {
-               dbus_g_proxy_connect_signal (priv->presence_iface,
-                                            "PresenceUpdate",
-                                            G_CALLBACK (tp_contact_list_presence_update_cb),
-                                            list, NULL);
-       }
-
-       /* Get our own handle and contact */
-       if (!tp_conn_get_self_handle (DBUS_G_PROXY (priv->tp_conn),
-                                     &handle, &error)) {
-               empathy_debug (DEBUG_DOMAIN, "GetSelfHandle Error: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-       } else {
-               priv->user_contact = empathy_tp_contact_list_get_from_handle (list, handle);
-               empathy_contact_set_is_user (priv->user_contact, TRUE);
-       }
-
-       return list;
-}
-
-static void
-tp_contact_list_setup (EmpathyContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-       GPtrArray                *channels;
-       GError                   *error = NULL;
-       guint                     i;
-
-       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
-
-       priv = GET_PRIV (list);
-
-       empathy_debug (DEBUG_DOMAIN, "setup contact list: %p", list);
-
-       priv->setup = TRUE;
-       dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_conn), "NewChannel",
-                                    G_CALLBACK (tp_contact_list_newchannel_cb),
-                                    list, NULL);
-
-       /* Get existing channels */
-       if (!tp_conn_list_channels (DBUS_G_PROXY (priv->tp_conn),
-                                   &channels,
-                                   &error)) {
-               empathy_debug (DEBUG_DOMAIN,
-                             "Failed to get list of open channels: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-               return;
-       }
-
-       for (i = 0; channels->len > i; i++) {
-               GValueArray         *chan_struct;
-               const gchar         *object_path;
-               const gchar         *chan_iface;
-               TelepathyHandleType  handle_type;
-               guint                handle;
-
-               chan_struct = g_ptr_array_index (channels, i);
-               object_path = g_value_get_boxed (g_value_array_get_nth (chan_struct, 0));
-               chan_iface = g_value_get_string (g_value_array_get_nth (chan_struct, 1));
-               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_newchannel_cb (DBUS_G_PROXY (priv->tp_conn),
-                                              object_path, chan_iface,
-                                              handle_type, handle,
-                                              FALSE,
-                                              EMPATHY_TP_CONTACT_LIST (list));
-
-               g_value_array_free (chan_struct);
-       }
-
-       g_ptr_array_free (channels, TRUE);
-}
-
-static EmpathyContact *
-tp_contact_list_find (EmpathyContactList *list,
-                     const gchar        *id)
-{
-       EmpathyTpContactListPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
-       priv = GET_PRIV (list);
-
-       return g_hash_table_find (priv->contacts,
-                                 (GHRFunc) tp_contact_list_find_foreach,
-                                 (gchar*) id);
-}
-
-static void
-tp_contact_list_add (EmpathyContactList *list,
-                    EmpathyContact      *contact,
-                    const gchar        *message)
-{
-       EmpathyTpContactListPriv *priv;
-       guint                     handle;
-
-       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
-
-       priv = GET_PRIV (list);
-
-       handle = empathy_contact_get_handle (contact);
-       empathy_tp_group_add_member (priv->subscribe, handle, message);
-}
-
-static void
-tp_contact_list_remove (EmpathyContactList *list,
-                       EmpathyContact      *contact,
-                       const gchar        *message)
-{
-       EmpathyTpContactListPriv *priv;
-       guint                     handle;
+static void empathy_tp_contact_list_class_init (EmpathyTpContactListClass *klass);
+static void empathy_tp_contact_list_init       (EmpathyTpContactList      *list);
+static void tp_contact_list_iface_init         (EmpathyContactListIface   *iface);
 
-       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
-
-       priv = GET_PRIV (list);
-
-       handle = empathy_contact_get_handle (contact);
-       empathy_tp_group_remove_member (priv->subscribe, handle, message);
-}
-
-static GList *
-tp_contact_list_get_members (EmpathyContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
-       priv = GET_PRIV (list);
-
-       g_list_foreach (priv->members, (GFunc) g_object_ref, NULL);
-       return g_list_copy (priv->members);
-}
-
-static GList *
-tp_contact_list_get_local_pending (EmpathyContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
-       priv = GET_PRIV (list);
-
-       return g_list_copy (priv->local_pending);
-}
-
-static void
-tp_contact_list_process_pending (EmpathyContactList *list,
-                                EmpathyContact      *contact,
-                                gboolean            accept)
-{
-       EmpathyTpContactListPriv *priv;
-       guint                     handle;
-
-       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
-       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
-       priv = GET_PRIV (list);
-
-       handle = empathy_contact_get_handle (contact);
-       if (accept) {
-               empathy_tp_group_add_member (priv->publish, handle, NULL);
-               empathy_tp_group_add_member (priv->subscribe, handle, NULL);
-       } else {
-               empathy_tp_group_remove_member (priv->publish, handle, NULL);
-       }
-}
-
-McAccount *
-empathy_tp_contact_list_get_account (EmpathyTpContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
-       priv = GET_PRIV (list);
-
-       return priv->account;
-}
-
-EmpathyContact *
-empathy_tp_contact_list_get_user (EmpathyTpContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
-       priv = GET_PRIV (list);
-       
-       return priv->user_contact;
-}
-
-EmpathyContact *
-empathy_tp_contact_list_get_from_id (EmpathyTpContactList *list,
-                                    const gchar          *id)
-{
-       EmpathyTpContactListPriv *priv;
-       EmpathyContact            *contact;
-       const gchar              *contact_ids[] = {id, NULL};
-       GArray                   *handles;
-       guint                     handle;
-       GError                   *error = NULL;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-       g_return_val_if_fail (id != NULL, NULL);
-       
-       priv = GET_PRIV (list);
-
-       contact = tp_contact_list_find (EMPATHY_CONTACT_LIST (list), id);
-       if (contact) {
-               return g_object_ref (contact);
-       }
-
-       /* The id is unknown, requests a new handle */
-       if (!tp_conn_request_handles (DBUS_G_PROXY (priv->tp_conn),
-                                     TP_HANDLE_TYPE_CONTACT,
-                                     contact_ids,
-                                     &handles, &error)) {
-               empathy_debug (DEBUG_DOMAIN, 
-                             "RequestHandle for %s failed: %s", id,
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-               return NULL;
-       }
-
-       handle = g_array_index(handles, guint, 0);
-       g_array_free (handles, TRUE);
-
-       return empathy_tp_contact_list_get_from_handle (list, handle);
-}
-
-EmpathyContact *
-empathy_tp_contact_list_get_from_handle (EmpathyTpContactList *list,
-                                        guint                 handle)
-{
-       EmpathyContact *contact;
-       GArray        *handles;
-       GList         *contacts;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
-       handles = g_array_new (FALSE, FALSE, sizeof (guint));
-       g_array_append_val (handles, handle);
-
-       contacts = empathy_tp_contact_list_get_from_handles (list, handles);
-       g_array_free (handles, TRUE);
-
-       if (!contacts) {
-               return NULL;
-       }
-
-       contact = contacts->data;
-       g_list_free (contacts);
-
-       return contact;
-}
-
-GList *
-empathy_tp_contact_list_get_from_handles (EmpathyTpContactList *list,
-                                         GArray               *handles)
-{
-       EmpathyTpContactListPriv  *priv;
-       gchar                    **handles_names;
-       gchar                    **id;
-       GArray                    *new_handles;
-       GList                     *contacts = NULL;
-       guint                      i;
-       GError                    *error = NULL;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-       g_return_val_if_fail (handles != NULL, NULL);
-
-       priv = GET_PRIV (list);
-
-       /* Search all handles we already have */
-       new_handles = g_array_new (FALSE, FALSE, sizeof (guint));
-       for (i = 0; i < handles->len; i++) {
-               EmpathyContact *contact;
-               guint          handle;
-
-               handle = g_array_index (handles, guint, i);
-
-               if (handle == 0) {
-                       continue;
-               }
-
-               contact = g_hash_table_lookup (priv->contacts,
-                                              GUINT_TO_POINTER (handle));
-
-               if (contact) {
-                       contacts = g_list_prepend (contacts,
-                                                  g_object_ref (contact));
-               } else {
-                       g_array_append_val (new_handles, handle);
-               }
-       }
-
-       if (new_handles->len == 0) {
-               g_array_free (new_handles, TRUE);
-               return contacts;
-       }
-
-       /* Holds all handles we don't have yet.
-        * FIXME: We should release them at some point. */
-       if (!tp_conn_hold_handles (DBUS_G_PROXY (priv->tp_conn),
-                                  TP_HANDLE_TYPE_CONTACT,
-                                  new_handles, &error)) {
-               empathy_debug (DEBUG_DOMAIN, 
-                             "HoldHandles Error: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-               g_array_free (new_handles, TRUE);
-               return contacts;
-       }
-
-       /* Get the IDs of all new handles */
-       if (!tp_conn_inspect_handles (DBUS_G_PROXY (priv->tp_conn),
-                                     TP_HANDLE_TYPE_CONTACT,
-                                     new_handles,
-                                     &handles_names,
-                                     &error)) {
-               empathy_debug (DEBUG_DOMAIN, 
-                             "InspectHandle Error: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-               g_array_free (new_handles, TRUE);
-               return contacts;
-       }
-
-       /* Create contact objects */
-       for (i = 0, id = handles_names; *id && i < new_handles->len; id++, i++) {
-               EmpathyContact *contact;
-               guint           handle;
-
-               handle = g_array_index (new_handles, guint, i);
-               contact = g_object_new (EMPATHY_TYPE_CONTACT,
-                                       "account", priv->account,
-                                       "id", *id,
-                                       "handle", handle,
-                                       NULL);
-
-               if (priv->protocol_group) {
-                       empathy_contact_add_group (contact, priv->protocol_group);
-               }
-
-               if (!priv->presence_iface) {
-                       EmpathyPresence *presence;
-
-                       /* We have no presence iface, set default presence
-                        * to available */
-                       presence = empathy_presence_new_full (MC_PRESENCE_AVAILABLE,
-                                                            NULL);
-
-                       empathy_contact_set_presence (contact, presence);
-                       g_object_unref (presence);
-               }
-
-               g_signal_connect (contact, "notify::groups",
-                                 G_CALLBACK (tp_contact_list_groups_updated_cb),
-                                 list);
-               g_signal_connect (contact, "notify::name",
-                                 G_CALLBACK (tp_contact_list_name_updated_cb),
-                                 list);
-
-               empathy_debug (DEBUG_DOMAIN, "new contact created: %s (%d)",
-                             *id, handle);
-
-               g_hash_table_insert (priv->contacts,
-                                    GUINT_TO_POINTER (handle),
-                                    contact);
-
-               contacts = g_list_prepend (contacts, g_object_ref (contact));
-       }
-
-       tp_contact_list_get_info (list, new_handles);
-
-       g_array_free (new_handles, TRUE);
-       g_strfreev (handles_names);
-
-       return contacts;
-}
-
-void
-empathy_tp_contact_list_rename_group (EmpathyTpContactList *list,
-                                     const gchar          *old_group,
-                                     const gchar          *new_group)
-{
-       EmpathyTpContactListPriv *priv;
-       EmpathyTpGroup           *group;
-       GArray                   *members;
-
-       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
-       g_return_if_fail (old_group != NULL);
-       g_return_if_fail (new_group != NULL);
-
-       priv = GET_PRIV (list);
-
-       group = g_hash_table_find (priv->groups,
-                                  (GHRFunc) tp_contact_list_find_group,
-                                  (gchar*) old_group);
-       if (!group) {
-               /* The group doesn't exists on this account */
-               return;
-       }
-
-       empathy_debug (DEBUG_DOMAIN, "rename group %s to %s", group, new_group);
-
-       /* Remove all members from the old group */
-       members = empathy_tp_group_get_members (group);
-       empathy_tp_group_remove_members (group, members, "");
-       tp_contact_list_group_members_removed_cb (group, members, 
-                                                 0, 
-                                                 TP_CHANNEL_GROUP_CHANGE_REASON_NONE, 
-                                                 NULL, list);
-       g_hash_table_remove (priv->groups,
-                            empathy_tp_group_get_object_path (group));
-
-       /* Add all members to the new group */
-       group = tp_contact_list_get_group (list, new_group);
-       if (group) {
-               empathy_tp_group_add_members (group, members, "");
-       }
-}
-
-GList *
-empathy_tp_contact_list_get_groups (EmpathyTpContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-       GList                    *groups = NULL;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
-       priv = GET_PRIV (list);
-
-       g_hash_table_foreach (priv->groups,
-                             (GHFunc) tp_contact_list_get_groups_foreach,
-                             &groups);
-
-       groups = g_list_sort (groups, (GCompareFunc) strcmp);
-
-       return groups;
-}
-
-static void
-tp_contact_list_finalize_proxies (EmpathyTpContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-
-       priv = GET_PRIV (list);
-
-       if (priv->tp_conn) {
-               g_signal_handlers_disconnect_by_func (priv->tp_conn,
-                                                     tp_contact_list_destroy_cb,
-                                                     list);
-               dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->tp_conn), "NewChannel",
-                                               G_CALLBACK (tp_contact_list_newchannel_cb),
-                                               list);
-       }
-
-       if (priv->aliasing_iface) {
-               dbus_g_proxy_disconnect_signal (priv->aliasing_iface,
-                                               "AliasesChanged",
-                                               G_CALLBACK (tp_contact_list_aliases_update_cb),
-                                               list);
-       }
-
-       if (priv->avatars_iface) {
-               dbus_g_proxy_disconnect_signal (priv->avatars_iface,
-                                               "AvatarUpdated",
-                                               G_CALLBACK (tp_contact_list_avatar_update_cb),
-                                               list);
-       }
-
-       if (priv->presence_iface) {
-               dbus_g_proxy_disconnect_signal (priv->presence_iface,
-                                               "PresenceUpdate",
-                                               G_CALLBACK (tp_contact_list_presence_update_cb),
-                                               list);
-       }
-}
-
-static void
-tp_contact_list_destroy_cb (DBusGProxy           *proxy,
-                           EmpathyTpContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-
-       priv = GET_PRIV (list);
-
-       empathy_debug (DEBUG_DOMAIN, "Connection destroyed... "
-                     "Account disconnected or CM crashed");
-
-       /* DBus proxies should NOT be used anymore */
-       g_object_unref (priv->tp_conn);
-       priv->tp_conn = NULL;
-       priv->aliasing_iface = NULL;
-       priv->avatars_iface = NULL;
-       priv->presence_iface = NULL;
-
-       /* Remove all contacts */
-       g_hash_table_foreach (priv->contacts,
-                             (GHFunc) tp_contact_list_contact_removed_foreach,
-                             list);
-       g_hash_table_remove_all (priv->contacts);
-
-       /* Tell the world to not use us anymore */
-       g_signal_emit (list, signals[DESTROY], 0);
-}
-
-static void
-tp_contact_list_contact_removed_foreach (guint                 handle,
-                                        EmpathyContact        *contact,
-                                        EmpathyTpContactList *list)
-{
-       g_signal_handlers_disconnect_by_func (contact,
-                                             tp_contact_list_groups_updated_cb,
-                                             list);
-       g_signal_handlers_disconnect_by_func (contact,
-                                             tp_contact_list_name_updated_cb,
-                                             list);
-
-       g_signal_emit_by_name (list, "contact-removed", contact);
-}
-
-static void
-tp_contact_list_block_contact (EmpathyTpContactList *list,
-                              EmpathyContact        *contact)
-{
-       g_signal_handlers_block_by_func (contact,
-                                        tp_contact_list_groups_updated_cb,
-                                        list);
-       g_signal_handlers_block_by_func (contact,
-                                        tp_contact_list_name_updated_cb,
-                                        list);
-}
-
-static void
-tp_contact_list_unblock_contact (EmpathyTpContactList *list,
-                                EmpathyContact        *contact)
-{
-       g_signal_handlers_unblock_by_func (contact,
-                                          tp_contact_list_groups_updated_cb,
-                                          list);
-       g_signal_handlers_unblock_by_func (contact,
-                                          tp_contact_list_name_updated_cb,
-                                          list);
-}
-
-static gboolean
-tp_contact_list_find_foreach (guint          handle,
-                             EmpathyContact *contact,
-                             gchar         *id)
-{
-       if (strcmp (empathy_contact_get_id (contact), id) == 0) {
-               return TRUE;
-       }
-
-       return FALSE;
-}
-
-static void
-tp_contact_list_newchannel_cb (DBusGProxy           *proxy,
-                              const gchar          *object_path,
-                              const gchar          *channel_type,
-                              TelepathyHandleType   handle_type,
-                              guint                 channel_handle,
-                              gboolean              suppress_handle,
-                              EmpathyTpContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-       EmpathyTpGroup           *group;
-       TpChan                   *new_chan;
-       const gchar              *bus_name;
-       GArray                   *members;
-
-       priv = GET_PRIV (list);
-
-       if (strcmp (channel_type, TP_IFACE_CHANNEL_TYPE_CONTACT_LIST) != 0 ||
-           suppress_handle ||
-           !priv->setup) {
-               return;
-       }
-
-       bus_name = dbus_g_proxy_get_bus_name (DBUS_G_PROXY (priv->tp_conn));
-       new_chan = tp_chan_new (tp_get_bus (),
-                               bus_name,
-                               object_path,
-                               channel_type, handle_type, channel_handle);
-       g_return_if_fail (TELEPATHY_IS_CHAN (new_chan));
-
-       if (handle_type == TP_HANDLE_TYPE_LIST) {
-               TpContactListType list_type;
-
-               group = empathy_tp_group_new (priv->account, new_chan);
-
-               list_type = tp_contact_list_get_type (list, group);
-               if (list_type == TP_CONTACT_LIST_TYPE_UNKNOWN) {
-                       empathy_debug (DEBUG_DOMAIN,
-                                     "Type of contact list channel unknown: %s",
-                                     empathy_tp_group_get_name (group));
-
-                       g_object_unref (new_chan);
-                       g_object_unref (group);
-                       return;
-               } else {
-                       empathy_debug (DEBUG_DOMAIN,
-                                     "New contact list channel of type: %d",
-                                     list_type);
-               }
-
-               g_signal_connect (group, "members-added",
-                                 G_CALLBACK (tp_contact_list_added_cb),
-                                 list);
-               g_signal_connect (group, "members-removed",
-                                 G_CALLBACK (tp_contact_list_removed_cb),
-                                 list);
+enum {
+       DESTROY,
+       LAST_SIGNAL
+};
 
-               if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
-                       GList *pendings, *l;
+static guint signals[LAST_SIGNAL];
 
-                       if (priv->publish) {
-                               g_object_unref (priv->publish);
-                       }
-                       priv->publish = group;
+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));
 
-                       /* Makes no sense to be in remote-pending */
-                       g_signal_connect (group, "local-pending",
-                                         G_CALLBACK (tp_contact_list_pending_cb),
-                                         list);
+static void
+tp_contact_list_group_destroy_cb (EmpathyTpGroup       *group,
+                                 EmpathyTpContactList *list)
+{
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
 
-                       pendings = empathy_tp_group_get_local_pending_members_with_info (group);
-                       if (pendings) {
-                               GArray *pending;
-
-                               pending = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
-                               for (l = pendings; l; l = l->next) {
-                                       EmpathyTpGroupInfo *info;
-
-                                       info = l->data;
-
-                                       g_array_insert_val (pending, 0, info->member);
-                                       tp_contact_list_pending_cb (group, pending,
-                                                                   info->actor,
-                                                                   info->reason,
-                                                                   info->message,
-                                                                   list);
-                               }
-                               g_array_free (pending, TRUE);
-                               empathy_tp_group_info_list_free (pendings);
-                       }
-               }
-               if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
-                       GArray *remote_pendings = NULL;
+       empathy_debug (DEBUG_DOMAIN, "Group destroyed: %s",
+                      empathy_tp_group_get_name (group));
 
-                       if (priv->subscribe) {
-                               g_object_unref (priv->subscribe);
-                       }
-                       priv->subscribe = group;
+       priv->groups = g_list_remove (priv->groups, group);
+       g_object_unref (group);
+}
 
-                       /* Makes no sense to be in local-pending */
-                       g_signal_connect (group, "remote-pending",
-                                         G_CALLBACK (tp_contact_list_pending_cb),
-                                         list);
-                       empathy_tp_group_get_all_members (group,
-                                                         &members,
-                                                         NULL,
-                                                         &remote_pendings);
-
-                       tp_contact_list_pending_cb (group, remote_pendings, 0,
-                                                   TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
-                                                   NULL,
-                                                   list);
-                       g_array_free (remote_pendings, TRUE);
-               } else {
-                       members = empathy_tp_group_get_members (group);
-               }
+static void
+tp_contact_list_group_member_added_cb (EmpathyTpGroup       *group,
+                                      EmpathyContact       *contact,
+                                      EmpathyContact       *actor,
+                                      guint                 reason,
+                                      const gchar          *message,
+                                      EmpathyTpContactList *list)
+{
+       EmpathyTpContactListPriv  *priv = GET_PRIV (list);
+       const gchar               *group_name;
+       GList                    **groups;
 
-               tp_contact_list_added_cb (group, members, 0,
-                                         TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
-                                         NULL, list);
-               g_array_free (members, TRUE);
+       if (!g_list_find (priv->members, contact)) {
+               return;
        }
-       else if (handle_type == TP_HANDLE_TYPE_GROUP) {
-               const gchar *object_path;
 
-               object_path = dbus_g_proxy_get_path (DBUS_G_PROXY (new_chan));
-               if (g_hash_table_lookup (priv->groups, object_path)) {
-                       g_object_unref (new_chan);
-                       return;
-               }
+       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);
+       }
 
-               group = empathy_tp_group_new (priv->account, new_chan);
+       group_name = empathy_tp_group_get_name (group);
+       if (!g_list_find_custom (*groups, group_name, (GCompareFunc) strcmp)) {
+               empathy_debug (DEBUG_DOMAIN, "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);
+       }
+}
 
-               empathy_debug (DEBUG_DOMAIN, "New server-side group channel: %s",
-                             empathy_tp_group_get_name (group));
+static void
+tp_contact_list_group_member_removed_cb (EmpathyTpGroup       *group,
+                                        EmpathyContact       *contact,
+                                        EmpathyContact       *actor,
+                                        guint                 reason,
+                                        const gchar          *message,
+                                        EmpathyTpContactList *list)
+{
+       EmpathyTpContactListPriv  *priv = GET_PRIV (list);
+       const gchar               *group_name;
+       GList                    **groups, *l;
 
-               dbus_g_proxy_connect_signal (DBUS_G_PROXY (new_chan), "Closed",
-                                            G_CALLBACK
-                                            (tp_contact_list_group_channel_closed_cb),
-                                            list, NULL);
+       if (!g_list_find (priv->members, contact)) {
+               return;
+       }
 
-               g_hash_table_insert (priv->groups, g_strdup (object_path), group);
-               g_signal_connect (group, "members-added",
-                                 G_CALLBACK (tp_contact_list_group_members_added_cb),
-                                 list);
-               g_signal_connect (group, "members-removed",
-                                 G_CALLBACK (tp_contact_list_group_members_removed_cb),
-                                 list);
+       groups = g_hash_table_lookup (priv->contacts_groups, contact);
+       if (!groups) {
+               return;
+       }
 
-               members = empathy_tp_group_get_members (group);
-               tp_contact_list_group_members_added_cb (group, members, 0,
-                                                       TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
-                                                       NULL, list);
-               g_array_free (members, TRUE);
+       group_name = empathy_tp_group_get_name (group);
+       if ((l = g_list_find_custom (*groups, group_name, (GCompareFunc) strcmp))) {
+               empathy_debug (DEBUG_DOMAIN, "Contact %s (%d) removed from group %s",
+                              empathy_contact_get_id (contact),
+                              empathy_contact_get_handle (contact),
+                              group_name);
+               *groups = g_list_delete_link (*groups, l);
+               g_signal_emit_by_name (list, "groups-changed", contact,
+                                      group_name,
+                                      FALSE);
        }
+}
 
-       g_object_unref (new_chan);
+static EmpathyTpGroup *
+tp_contact_list_find_group (EmpathyTpContactList *list,
+                           const gchar          *group)
+{
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       GList                    *l;
+
+       for (l = priv->groups; l; l = l->next) {
+               if (strcmp (group, empathy_tp_group_get_name (l->data)) == 0) {
+                       return l->data;
+               }
+       }
+       return NULL;
 }
 
 static TpContactListType
@@ -1127,808 +199,795 @@ tp_contact_list_get_type (EmpathyTpContactList *list,
        return list_type;
 }
 
+static void
+tp_contact_list_add_member (EmpathyTpContactList *list,
+                           EmpathyContact       *contact,
+                           EmpathyContact       *actor,
+                           guint                 reason,
+                           const gchar          *message)
+{
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       GList                    *l;
+
+       /* 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);
+
+       /* This contact is now member, implicitly accept pending. */
+       if (g_list_find (priv->pendings, contact)) {
+               empathy_tp_group_add_member (priv->publish, contact, "");
+       }
+
+       /* 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);
+               }
+       }
+}
+
 static void
 tp_contact_list_added_cb (EmpathyTpGroup       *group,
-                         GArray               *handles,
-                         guint                 actor_handle,
+                         EmpathyContact       *contact,
+                         EmpathyContact       *actor,
                          guint                 reason,
                          const gchar          *message,
                          EmpathyTpContactList *list)
 {
-       EmpathyTpContactListPriv *priv;
-       GList                    *added_list, *l;
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
        TpContactListType         list_type;
 
-       priv = GET_PRIV (list);
-
        list_type = tp_contact_list_get_type (list, group);
-
-       added_list = empathy_tp_contact_list_get_from_handles (list, handles);
-       for (l = added_list; l; l = l->next) {
-               EmpathyContact      *contact;
-               EmpathySubscription  subscription;
-
-               contact = EMPATHY_CONTACT (l->data);
-
-               empathy_debug (DEBUG_DOMAIN, "Contact '%s' added to list type %d",
-                             empathy_contact_get_name (contact),
-                             list_type);
-
-               subscription = empathy_contact_get_subscription (contact);
-               if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
-                       subscription |= EMPATHY_SUBSCRIPTION_FROM;
-               }
-               else if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
-                       subscription |= EMPATHY_SUBSCRIPTION_TO;
-                       tp_contact_list_remove_local_pending (list, contact);
-               }
-
-               tp_contact_list_block_contact (list, contact);
-               empathy_contact_set_subscription (contact, subscription);
-               tp_contact_list_unblock_contact (list, contact);
-
-               if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
-                       if (!g_list_find (priv->members, contact)) {
-                               priv->members = g_list_prepend (priv->members,
-                                                               g_object_ref (contact));
-                               g_signal_emit_by_name (list, "contact-added", contact);
-                       }
-               }
-
+       empathy_debug (DEBUG_DOMAIN, "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);
+       }
+
+       /* 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);
        }
-
-       g_list_free (added_list);
 }
 
 static void
 tp_contact_list_removed_cb (EmpathyTpGroup       *group,
-                           GArray               *handles,
-                           guint                 actor_handle,
+                           EmpathyContact       *contact,
+                           EmpathyContact       *actor,
                            guint                 reason,
                            const gchar          *message,
                            EmpathyTpContactList *list)
 {
-       EmpathyTpContactListPriv *priv;
-       GList                    *removed_list, *l;
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
        TpContactListType         list_type;
 
-       priv = GET_PRIV (list);
-
        list_type = tp_contact_list_get_type (list, group);
-
-       removed_list = empathy_tp_contact_list_get_from_handles (list, handles);
-       for (l = removed_list; l; l = l->next) {
-               EmpathyContact      *contact;
-               EmpathySubscription  subscription;
-
-               contact = EMPATHY_CONTACT (l->data);
-
-               empathy_debug (DEBUG_DOMAIN, "Contact '%s' removed from list type %d",
-                             empathy_contact_get_name (contact),
-                             list_type);
-
-               subscription = empathy_contact_get_subscription (contact);
-               if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
-                       subscription &= !EMPATHY_SUBSCRIPTION_FROM;
-               }
-               else if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
-                       subscription &= !EMPATHY_SUBSCRIPTION_TO;
-                       tp_contact_list_remove_local_pending (list, contact);
-               }
-
-               tp_contact_list_block_contact (list, contact);
-               empathy_contact_set_subscription (contact, subscription);
-               tp_contact_list_unblock_contact (list, contact);
-
-               if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
-                       GList *l;
-
-                       if ((l = g_list_find (priv->members, contact))) {
-                               g_signal_emit_by_name (list, "contact-removed", contact);
-                               priv->members = g_list_delete_link (priv->members, l);
-                               g_object_unref (contact);
-                       }
-               }
+       empathy_debug (DEBUG_DOMAIN, "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);
        }
 
-       g_list_free (removed_list);
+       /* 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,
+                                      FALSE);
+               priv->pendings = g_list_remove (priv->pendings, contact);
+               g_object_unref (contact);
+       }
 }
 
 static void
 tp_contact_list_pending_cb (EmpathyTpGroup       *group,
-                           GArray               *handles,
-                           guint                 actor_handle,
+                           EmpathyContact       *contact,
+                           EmpathyContact       *actor,
                            guint                 reason,
                            const gchar          *message,
                            EmpathyTpContactList *list)
 {
-       EmpathyTpContactListPriv *priv;
-       GList                    *pending_list, *l;
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
        TpContactListType         list_type;
 
-       priv = GET_PRIV (list);
-
        list_type = tp_contact_list_get_type (list, group);
-
-       pending_list = empathy_tp_contact_list_get_from_handles (list, handles);
-       for (l = pending_list; l; l = l->next) {
-               EmpathyContact *contact;
-
-               contact = EMPATHY_CONTACT (l->data);
-
-               empathy_debug (DEBUG_DOMAIN, "Contact '%s' pending in list type %d",
-                             empathy_contact_get_name (contact),
-                             list_type);
-
-               if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
-                       if (!g_list_find (priv->members, contact)) {
-                               EmpathyContactListInfo *info;
-
-                               info = empathy_contact_list_info_new (contact, message);
-                               priv->local_pending = g_list_prepend (priv->local_pending,
-                                                                     info);
-
-                               g_signal_emit_by_name (list, "local-pending",
-                                                      contact, message);
-                       } else {
-                               guint handle;
-
-                               /* That contact wants our presence and he is
-                                * in our roster. Accept to publish our presence
-                                * without asking the user. */
-                               handle = empathy_contact_get_handle (contact);
-                               empathy_tp_group_add_member (priv->publish,
-                                                            handle, "");
-                       }
-               }
-               else if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
-                       if (!g_list_find (priv->members, contact)) {
-                               priv->members = g_list_prepend (priv->members,
-                                                               g_object_ref (contact));
-                               g_signal_emit_by_name (list, "contact-added", contact);
-                       }
+       empathy_debug (DEBUG_DOMAIN, "Contact %s (%d) pending in list type %d",
+                     empathy_contact_get_id (contact),
+                     empathy_contact_get_handle (contact),
+                     list_type);
+
+       /* 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);
+       }
+
+       /* 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);
                }
-
-               g_object_unref (contact);
        }
-
-       g_list_free (pending_list);
 }
 
 static void
-tp_contact_list_remove_local_pending (EmpathyTpContactList *list,
-                                     EmpathyContact        *contact)
+tp_contact_list_newchannel_cb (DBusGProxy           *proxy,
+                              const gchar          *object_path,
+                              const gchar          *channel_type,
+                              TelepathyHandleType   handle_type,
+                              guint                 channel_handle,
+                              gboolean              suppress_handle,
+                              EmpathyTpContactList *list)
 {
-       EmpathyTpContactListPriv *priv;
-       GList                    *l;
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       EmpathyTpGroup           *group;
+       TpChan                   *new_chan;
+       const gchar              *bus_name;
 
-       priv = GET_PRIV (list);
+       if (strcmp (channel_type, TP_IFACE_CHANNEL_TYPE_CONTACT_LIST) != 0 ||
+           suppress_handle) {
+               return;
+       }
 
-       for (l = priv->local_pending; l; l = l->next) {
-               EmpathyContactListInfo *info;
+       bus_name = dbus_g_proxy_get_bus_name (DBUS_G_PROXY (priv->tp_conn));
+       new_chan = tp_chan_new (tp_get_bus (),
+                               bus_name,
+                               object_path,
+                               channel_type,
+                               handle_type,
+                               channel_handle);
+       g_return_if_fail (TELEPATHY_IS_CHAN (new_chan));
 
-               info = l->data;
-               if (empathy_contact_equal (contact, info->contact)) {
-                       empathy_debug (DEBUG_DOMAIN, "Contact no more local-pending: %s",
-                                     empathy_contact_get_name (contact));
+       group = empathy_tp_group_new (priv->account, new_chan);
+       g_object_unref (new_chan);
 
-                       priv->local_pending = g_list_delete_link (priv->local_pending, l);
-                       empathy_contact_list_info_free (info);
-                       break;
-               }
-       }
-}
+       if (handle_type == TP_HANDLE_TYPE_LIST) {
+               TpContactListType  list_type;
+               GList             *contacts, *l;
 
-static void
-tp_contact_list_groups_updated_cb (EmpathyContact       *contact,
-                                  GParamSpec           *param,
-                                  EmpathyTpContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-       TpContactListData         data;
-       GList                    *groups, *l;
+               list_type = tp_contact_list_get_type (list, group);
+               if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH && !priv->publish) {
+                       priv->publish = group;
 
-       priv = GET_PRIV (list);
+                       /* 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);
 
-       /* Make sure all groups are created */
-       groups = empathy_contact_get_groups (contact);
-       for (l = groups; l; l = l->next) {
-               tp_contact_list_get_group (list, l->data);
-       }
+                       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) {
+                       priv->subscribe = group;
 
-       data.handle = empathy_contact_get_handle (contact);
-       data.new_groups = groups;
+                       /* 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);
 
-       g_hash_table_foreach (priv->groups,
-                             (GHFunc) tp_contact_list_update_groups_foreach,
-                             &data);
-}
+                       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 {
+                       empathy_debug (DEBUG_DOMAIN,
+                                     "Type of contact list channel unknown "
+                                     "or aleady have that list: %s",
+                                     empathy_tp_group_get_name (group));
+                       g_object_unref (group);
+                       return;
+               }
+               empathy_debug (DEBUG_DOMAIN,
+                              "New contact list channel of type: %d",
+                              list_type);
 
-static void
-tp_contact_list_name_updated_cb (EmpathyContact        *contact,
-                                GParamSpec           *param,
-                                EmpathyTpContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-       GHashTable               *new_alias;
-       const gchar              *new_name;
-       guint                     handle;
-       GError                   *error = NULL;
+               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);
 
-       priv = GET_PRIV (list);
-       
-       if (!priv->aliasing_iface) {
-               return;
+               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);
        }
+       else if (handle_type == TP_HANDLE_TYPE_GROUP) {
+               const gchar *group_name;
+               GList       *contacts, *l;
 
-       handle = empathy_contact_get_handle (contact);
-       new_name = empathy_contact_get_name (contact);
+               /* 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);
+                       return;
+               }
 
-       empathy_debug (DEBUG_DOMAIN, "renaming handle %d to %s",
-                     handle, new_name);
+               empathy_debug (DEBUG_DOMAIN, "New server-side group channel: %s",
+                              group_name);
 
-       new_alias = g_hash_table_new_full (g_direct_hash,
-                                          g_direct_equal,
-                                          NULL,
-                                          g_free);
+               priv->groups = g_list_prepend (priv->groups, group);
 
-       g_hash_table_insert (new_alias,
-                            GUINT_TO_POINTER (handle),
-                            g_strdup (new_name));
+               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),
+                                 list);
 
-       if (!tp_conn_iface_aliasing_set_aliases (priv->aliasing_iface,
-                                                new_alias,
-                                                &error)) {
-               empathy_debug (DEBUG_DOMAIN, 
-                             "Couldn't rename contact: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
+               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);
+               }
+               g_list_free (contacts);
+       } else {
+               empathy_debug (DEBUG_DOMAIN,
+                              "Unknown handle type (%d) for contact list channel",
+                              handle_type);
+               g_object_unref (group);
        }
-
-       g_hash_table_destroy (new_alias);
 }
 
 static void
-tp_contact_list_update_groups_foreach (gchar             *object_path,
-                                      EmpathyTpGroup    *group,
-                                      TpContactListData *data)
+tp_contact_list_remove_all (EmpathyTpContactList *list)
 {
-       gboolean     is_member;
-       gboolean     found = FALSE;
-       const gchar *group_name;
-       GList       *l;
-
-       is_member = empathy_tp_group_is_member (group, data->handle);
-       group_name = empathy_tp_group_get_name (group);
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       GList                    *l;
 
-       for (l = data->new_groups; l; l = l->next) {
-               if (strcmp (group_name, l->data) == 0) {
-                       found = TRUE;
-                       break;
-               }
+       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);
        }
-
-       if (is_member && !found) {
-               /* We are no longer member of this group */
-               empathy_debug (DEBUG_DOMAIN, "Contact %d removed from group '%s'",
-                             data->handle, group_name);
-               empathy_tp_group_remove_member (group, data->handle, "");
+       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 (!is_member && found) {
-               /* We are now member of this group */
-               empathy_debug (DEBUG_DOMAIN, "Contact %d added to group '%s'",
-                             data->handle, group_name);
-               empathy_tp_group_add_member (group, data->handle, "");
-       }
+       g_list_free (priv->members);
+       g_list_free (priv->pendings);
+       priv->members = NULL;
+       priv->pendings = NULL;
 }
 
-static EmpathyTpGroup *
-tp_contact_list_get_group (EmpathyTpContactList *list,
-                          const gchar          *name)
+static void
+tp_contact_list_destroy_cb (TpConn               *tp_conn,
+                           EmpathyTpContactList *list)
 {
-       EmpathyTpContactListPriv *priv;
-       EmpathyTpGroup           *group;
-       TpChan                   *group_channel;
-       GArray                   *handles;
-       guint                     group_handle;
-       char                     *group_object_path;
-       const char               *names[2] = {name, NULL};
-       GError                   *error = NULL;
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
 
-       priv = GET_PRIV (list);
-
-       group = g_hash_table_find (priv->groups,
-                                  (GHRFunc) tp_contact_list_find_group,
-                                  (gchar*) name);
-       if (group) {
-               return group;
-       }
+       empathy_debug (DEBUG_DOMAIN, "Account disconnected or CM crashed");
 
-       empathy_debug (DEBUG_DOMAIN, "creating new group: %s", name);
+       /* DBus proxie should NOT be used anymore */
+       g_object_unref (priv->tp_conn);
+       priv->tp_conn = NULL;
 
-       if (!tp_conn_request_handles (DBUS_G_PROXY (priv->tp_conn),
-                                     TP_HANDLE_TYPE_GROUP,
-                                     names,
-                                     &handles,
-                                     &error)) {
-               empathy_debug (DEBUG_DOMAIN,
-                             "Couldn't request the creation of a new handle for group: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-               return NULL;
-       }
-       group_handle = g_array_index (handles, guint, 0);
-       g_array_free (handles, TRUE);
+       tp_contact_list_remove_all (list);
 
-       if (!tp_conn_request_channel (DBUS_G_PROXY (priv->tp_conn),
-                                     TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
-                                     TP_HANDLE_TYPE_GROUP,
-                                     group_handle,
-                                     FALSE,
-                                     &group_object_path,
-                                     &error)) {
-               empathy_debug (DEBUG_DOMAIN,
-                             "Couldn't request the creation of a new group channel: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-               return NULL;
-       }
+       /* Tell the world to not use us anymore */
+       g_signal_emit (list, signals[DESTROY], 0);
+}
 
-       group_channel = tp_chan_new (tp_get_bus (),
-                                    dbus_g_proxy_get_bus_name (DBUS_G_PROXY (priv->tp_conn)),
-                                    group_object_path,
-                                    TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
-                                    TP_HANDLE_TYPE_GROUP,
-                                    group_handle);
-
-       dbus_g_proxy_connect_signal (DBUS_G_PROXY (group_channel),
-                                    "Closed",
-                                    G_CALLBACK
-                                    (tp_contact_list_group_channel_closed_cb),
-                                    list,
-                                    NULL);
-
-       group = empathy_tp_group_new (priv->account, group_channel);
-       g_hash_table_insert (priv->groups, group_object_path, group);
-       g_signal_connect (group, "members-added",
-                         G_CALLBACK (tp_contact_list_group_members_added_cb),
-                         list);
-       g_signal_connect (group, "members-removed",
-                         G_CALLBACK (tp_contact_list_group_members_removed_cb),
-                         list);
+static void
+tp_contact_list_disconnect (EmpathyTpContactList *list)
+{
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
 
-       return group;
+       if (priv->tp_conn) {
+               g_signal_handlers_disconnect_by_func (priv->tp_conn,
+                                                     tp_contact_list_destroy_cb,
+                                                     list);
+               dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->tp_conn), "NewChannel",
+                                               G_CALLBACK (tp_contact_list_newchannel_cb),
+                                               list);
+       }
 }
 
-static gboolean
-tp_contact_list_find_group (gchar          *key,
-                           EmpathyTpGroup *group,
-                           gchar          *group_name)
+static void
+tp_contact_list_status_changed_cb (MissionControl                  *mc,
+                                  TelepathyConnectionStatus        status,
+                                  McPresence                       presence,
+                                  TelepathyConnectionStatusReason  reason,
+                                  const gchar                     *unique_name,
+                                  EmpathyTpContactList            *list)
 {
-       if (strcmp (group_name, empathy_tp_group_get_name (group)) == 0) {
-               return TRUE;
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       McAccount                *account;
+
+       account = mc_account_lookup (unique_name);
+       if (status != TP_CONN_STATUS_CONNECTED &&
+           empathy_account_equal (account, priv->account)) {
+               /* We are disconnected */
+               tp_contact_list_disconnect (list);
+               tp_contact_list_destroy_cb (priv->tp_conn, list);
        }
 
-       return FALSE;
+       g_object_unref (account);
 }
 
 static void
-tp_contact_list_get_groups_foreach (gchar          *key,
-                                   EmpathyTpGroup *group,
-                                   GList          **groups)
+tp_contact_list_group_list_free (GList **groups)
 {
-       const gchar *name;
-
-       name = empathy_tp_group_get_name (group);
-       *groups = g_list_append (*groups, g_strdup (name));
+       g_list_foreach (*groups, (GFunc) g_free, NULL);
+       g_list_free (*groups);
+       g_slice_free (GList*, groups);
 }
 
 static void
-tp_contact_list_group_channel_closed_cb (TpChan             *channel,
-                                        EmpathyTpContactList *list)
+tp_contact_list_finalize (GObject *object)
 {
        EmpathyTpContactListPriv *priv;
+       EmpathyTpContactList     *list;
 
+       list = EMPATHY_TP_CONTACT_LIST (object);
        priv = GET_PRIV (list);
 
-       g_hash_table_remove (priv->groups,
-                            dbus_g_proxy_get_path (DBUS_G_PROXY (channel)));
-}
+       empathy_debug (DEBUG_DOMAIN, "finalize: %p", object);
 
-static void
-tp_contact_list_group_members_added_cb (EmpathyTpGroup       *group,
-                                       GArray               *members,
-                                       guint                 actor_handle,
-                                       guint                 reason,
-                                       const gchar          *message,
-                                       EmpathyTpContactList *list)
-{
-       EmpathyTpContactListPriv *priv;
-       GList                    *added_list, *l;
-       const gchar              *group_name;
+       tp_contact_list_disconnect (list);
+       tp_contact_list_remove_all (list);
 
-       priv = GET_PRIV (list);
+       if (priv->mc) {
+               dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc),
+                                               "AccountStatusChanged",
+                                               G_CALLBACK (tp_contact_list_status_changed_cb),
+                                               list);
+               g_object_unref (priv->mc);
+       }
 
-       group_name = empathy_tp_group_get_name (group);
-       added_list = empathy_tp_contact_list_get_from_handles (list, members);
+       if (priv->subscribe) {
+               g_object_unref (priv->subscribe);
+       }
+       if (priv->publish) {
+               g_object_unref (priv->publish);
+       }
+       if (priv->account) {
+               g_object_unref (priv->account);
+       }
+       if (priv->tp_conn) {
+               g_object_unref (priv->tp_conn);
+       }
+
+       g_hash_table_destroy (priv->contacts_groups);
+       g_list_foreach (priv->groups, (GFunc) g_object_unref, NULL);
+       g_list_free (priv->groups);
+
+       G_OBJECT_CLASS (empathy_tp_contact_list_parent_class)->finalize (object);
+}
 
-       for (l = added_list; l; l = l->next) {
-               EmpathyContact *contact;
+static void
+empathy_tp_contact_list_class_init (EmpathyTpContactListClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-               contact = EMPATHY_CONTACT (l->data);
+       object_class->finalize = tp_contact_list_finalize;
 
-               tp_contact_list_block_contact (list, contact);
-               empathy_contact_add_group (contact, group_name);
-               tp_contact_list_unblock_contact (list, contact);
+       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_object_unref (contact);
-       }
+       g_type_class_add_private (object_class, sizeof (EmpathyTpContactListPriv));
+}
 
-       g_list_free (added_list);
+static void
+empathy_tp_contact_list_init (EmpathyTpContactList *list)
+{
 }
 
 static void
-tp_contact_list_group_members_removed_cb (EmpathyTpGroup       *group,
-                                         GArray               *members,
-                                         guint                 actor_handle,
-                                         guint                 reason,
-                                         const gchar          *message,
-                                         EmpathyTpContactList *list)
+tp_contact_list_setup (EmpathyTpContactList *list)
 {
-       EmpathyTpContactListPriv *priv;
-       GList                    *removed_list, *l;
-       const gchar              *group_name;
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       GPtrArray                *channels;
+       guint                     i;
+       GError                   *error = NULL;
 
-       priv = GET_PRIV (list);
+       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
 
-       group_name = empathy_tp_group_get_name (group);
-       removed_list = empathy_tp_contact_list_get_from_handles (list, members);
+       /* Get existing channels */
+       if (!tp_conn_list_channels (DBUS_G_PROXY (priv->tp_conn),
+                                   &channels,
+                                   &error)) {
+               empathy_debug (DEBUG_DOMAIN,
+                             "Failed to get list of open channels: %s",
+                             error ? error->message : "No error given");
+               g_clear_error (&error);
+               return;
+       }
 
-       for (l = removed_list; l; l = l->next) {
-               EmpathyContact *contact;
+       for (i = 0; i < channels->len; i++) {
+               GValueArray         *chan_struct;
+               const gchar         *object_path;
+               const gchar         *chan_iface;
+               TelepathyHandleType  handle_type;
+               guint                handle;
 
-               contact = l->data;
+               chan_struct = g_ptr_array_index (channels, i);
+               object_path = g_value_get_boxed (g_value_array_get_nth (chan_struct, 0));
+               chan_iface = g_value_get_string (g_value_array_get_nth (chan_struct, 1));
+               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_block_contact (list, contact);
-               empathy_contact_remove_group (contact, group_name);
-               tp_contact_list_unblock_contact (list, contact);
+               tp_contact_list_newchannel_cb (DBUS_G_PROXY (priv->tp_conn),
+                                              object_path, chan_iface,
+                                              handle_type, handle,
+                                              FALSE,
+                                              list);
 
-               g_object_unref (contact);
+               g_value_array_free (chan_struct);
        }
-
-       g_list_free (removed_list);
+       g_ptr_array_free (channels, TRUE);
 }
 
-static void
-tp_contact_list_get_info (EmpathyTpContactList *list,
-                         GArray               *handles)
+EmpathyTpContactList *
+empathy_tp_contact_list_new (McAccount *account)
 {
        EmpathyTpContactListPriv *priv;
-       GError                   *error = NULL;
+       EmpathyTpContactList     *list;
+       MissionControl           *mc;
+       TpConn                   *tp_conn = NULL;
+       McProfile                *profile;
+       const gchar              *protocol_name;
 
-       priv = GET_PRIV (list);
+       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
 
-       if (priv->presence_iface) {
-               /* FIXME: We should use GetPresence instead */
-               if (!tp_conn_iface_presence_request_presence (priv->presence_iface,
-                                                             handles, &error)) {
-                       empathy_debug (DEBUG_DOMAIN, 
-                                     "Could not request presences: %s",
-                                     error ? error->message : "No error given");
-                       g_clear_error (&error);
-               }
+       mc = empathy_mission_control_new ();
+
+       /* status==0 means CONNECTED */
+       if (mission_control_get_connection_status (mc, account, NULL) == 0) {
+               tp_conn = mission_control_get_connection (mc, account, NULL);
+       }
+       if (!tp_conn) {
+               /* The account is not connected, nothing to do. */
+               g_object_unref (mc);
+               return NULL;
        }
 
-       if (priv->aliasing_iface) {
-               TpContactListAliasesRequestData *data;
+       list = g_object_new (EMPATHY_TYPE_TP_CONTACT_LIST, NULL);
+       priv = GET_PRIV (list);
 
-               data = g_slice_new (TpContactListAliasesRequestData);
-               data->list = list;
-               data->handles = g_memdup (handles->data, handles->len * sizeof (guint));
+       priv->tp_conn = tp_conn;
+       priv->account = g_object_ref (account);
+       priv->mc = mc;
+       priv->contacts_groups = g_hash_table_new_full (empathy_contact_hash,
+                                                      empathy_contact_equal,
+                                                      (GDestroyNotify) g_object_unref,
+                                                      (GDestroyNotify) tp_contact_list_group_list_free);
 
-               tp_conn_iface_aliasing_request_aliases_async (priv->aliasing_iface,
-                                                             handles,
-                                                             (tp_conn_iface_aliasing_request_aliases_reply)
-                                                             tp_contact_list_request_aliases_cb,
-                                                             data);
+       /* 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 (account);
+       protocol_name = mc_profile_get_protocol_name (profile);
+       if (strcmp (protocol_name, "local-xmpp") == 0) {
+               priv->protocol_group = _("People nearby");
        }
+       g_object_unref (profile);
 
-       if (priv->avatars_iface) {
-               guint i;
+       /* Connect signals */
+       dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc),
+                                    "AccountStatusChanged",
+                                    G_CALLBACK (tp_contact_list_status_changed_cb),
+                                    list, NULL);
+       dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_conn), "NewChannel",
+                                    G_CALLBACK (tp_contact_list_newchannel_cb),
+                                    list, NULL);
+       g_signal_connect (priv->tp_conn, "destroy",
+                         G_CALLBACK (tp_contact_list_destroy_cb),
+                         list);
 
-               for (i = 0; i < handles->len; i++) {
-                       guint handle;
+       tp_contact_list_setup (list);
 
-                       handle = g_array_index (handles, gint, i);
-                       tp_contact_list_request_avatar (list, handle);
-               }
-       }
+       return list;
 }
 
-static void
-tp_contact_list_request_avatar (EmpathyTpContactList *list,
-                               guint                 handle)
+McAccount *
+empathy_tp_contact_list_get_account (EmpathyTpContactList *list)
 {
-       EmpathyTpContactListPriv       *priv;
-       TpContactListAvatarRequestData *data;
+       EmpathyTpContactListPriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
 
        priv = GET_PRIV (list);
-       
-       /* We queue avatar requests to not send too many dbus async
-        * calls at once. If we don't we reach the dbus's limit of
-        * pending calls */
-       data = g_slice_new (TpContactListAvatarRequestData);
-       data->list = g_object_ref (list);
-       data->handle = handle;
-       avatar_requests_queue = g_list_append (avatar_requests_queue, data);
-       tp_contact_list_start_avatar_requests ();
+
+       return priv->account;
 }
 
 static void
-tp_contact_list_start_avatar_requests (void)
+tp_contact_list_add (EmpathyContactList *list,
+                    EmpathyContact     *contact,
+                    const gchar        *message)
 {
-       empathy_debug (DEBUG_DOMAIN, "Start avatar requests, pending calls: %d",
-                      n_avatar_requests);
-
-       while (n_avatar_requests <  MAX_AVATAR_REQUESTS && avatar_requests_queue) {
-               EmpathyTpContactListPriv       *priv;
-               TpContactListAvatarRequestData *data;
-
-               data = avatar_requests_queue->data;
-               priv = GET_PRIV (data->list);
-
-               n_avatar_requests++;
-               avatar_requests_queue = g_list_delete_link (avatar_requests_queue,
-                                                           avatar_requests_queue);
-
-               empathy_debug (DEBUG_DOMAIN, "Calling RequestAvatar async");
-               tp_conn_iface_avatars_request_avatar_async (priv->avatars_iface,
-                                                           data->handle,
-                                                           (tp_conn_iface_avatars_request_avatar_reply)
-                                                           tp_contact_list_request_avatar_cb,
-                                                           data);
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+
+       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
+
+       empathy_tp_group_add_member (priv->subscribe, contact, message);
+       if (g_list_find (priv->pendings, contact)) {
+               empathy_tp_group_add_member (priv->publish, contact, message);          
        }
 }
 
 static void
-tp_contact_list_avatar_update_cb (DBusGProxy           *proxy,
-                                 guint                 handle,
-                                 gchar                *new_token,
-                                 EmpathyTpContactList *list)
+tp_contact_list_remove (EmpathyContactList *list,
+                       EmpathyContact     *contact,
+                       const gchar        *message)
 {
-       EmpathyTpContactListPriv *priv;
-
-       priv = GET_PRIV (list);
-
-       if (!g_hash_table_lookup (priv->contacts, GUINT_TO_POINTER (handle))) {
-               /* We don't know this contact, skip */
-               return;
-       }
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
 
-       empathy_debug (DEBUG_DOMAIN, "Changing avatar for %d to %s",
-                     handle, new_token);
+       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
 
-       tp_contact_list_request_avatar (list, handle);
+       empathy_tp_group_remove_member (priv->subscribe, contact, message);
+       empathy_tp_group_remove_member (priv->publish, contact, message);               
 }
 
-static void
-tp_contact_list_request_avatar_cb (DBusGProxy                     *proxy,
-                                  GArray                         *avatar_data,
-                                  gchar                          *mime_type,
-                                  GError                         *error,
-                                  TpContactListAvatarRequestData *data)
+static GList *
+tp_contact_list_get_members (EmpathyContactList *list)
 {
-       EmpathyContact *contact;
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
 
-       contact = empathy_tp_contact_list_get_from_handle (data->list, data->handle);
+       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
 
-       if (error) {
-               empathy_debug (DEBUG_DOMAIN, "Error requesting avatar for %s: %s",
-                             empathy_contact_get_name (contact),
-                             error ? error->message : "No error given");
-       } else {
-               EmpathyAvatar *avatar;
+       g_list_foreach (priv->members, (GFunc) g_object_ref, NULL);
+       return g_list_copy (priv->members);
+}
 
-               empathy_debug (DEBUG_DOMAIN, "Avatar received for %s (%d)",
-                              empathy_contact_get_id (contact),
-                              data->handle);
-
-               avatar = empathy_avatar_new (avatar_data->data,
-                                           avatar_data->len,
-                                           mime_type);
-               tp_contact_list_block_contact (data->list, contact);
-               empathy_contact_set_avatar (contact, avatar);
-               tp_contact_list_unblock_contact (data->list, contact);
-               empathy_avatar_unref (avatar);
-       }
+static GList *
+tp_contact_list_get_pendings (EmpathyContactList *list)
+{
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
 
-       n_avatar_requests--;
-       tp_contact_list_start_avatar_requests ();
+       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
 
-       g_object_unref (contact);
-       g_object_unref (data->list);
-       g_slice_free (TpContactListAvatarRequestData, data);
+       g_list_foreach (priv->pendings, (GFunc) g_object_ref, NULL);
+       return g_list_copy (priv->pendings);
 }
 
-static void
-tp_contact_list_aliases_update_cb (DBusGProxy           *proxy,
-                                  GPtrArray            *renamed_handlers,
-                                  EmpathyTpContactList *list)
+static GList *
+tp_contact_list_get_all_groups (EmpathyContactList *list)
 {
-       EmpathyTpContactListPriv *priv;
-       guint                     i;
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       GList                    *groups = NULL, *l;
 
-       priv = GET_PRIV (list);
+       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
 
-       for (i = 0; renamed_handlers->len > i; i++) {
-               guint          handle;
-               const gchar   *alias;
-               GValueArray   *renamed_struct;
-               EmpathyContact *contact;
+       for (l = priv->groups; l; l = l->next) {
+               const gchar *name;
 
-               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));
+               name = empathy_tp_group_get_name (l->data);
+               groups = g_list_prepend (groups, g_strdup (name));
+       }
 
-               if (!g_hash_table_lookup (priv->contacts, GUINT_TO_POINTER (handle))) {
-                       /* We don't know this contact, skip */
-                       continue;
-               }
+       return groups;
+}
 
-               if (G_STR_EMPTY (alias)) {
-                       alias = NULL;
-               }
+static GList *
+tp_contact_list_get_groups (EmpathyContactList *list,
+                           EmpathyContact     *contact)
+{
+       EmpathyTpContactListPriv  *priv = GET_PRIV (list);
+       GList                    **groups;
+       GList                     *ret = NULL, *l;
 
-               contact = empathy_tp_contact_list_get_from_handle (list, handle);
-               tp_contact_list_block_contact (list, contact);
-               empathy_contact_set_name (contact, alias);
-               tp_contact_list_unblock_contact (list, contact);
-               g_object_unref (contact);
+       g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
+
+       groups = g_hash_table_lookup (priv->contacts_groups, contact);
+       if (!groups) {
+               return NULL;
+       }
 
-               empathy_debug (DEBUG_DOMAIN, "contact %d renamed to %s (update cb)",
-                             handle, alias);
+       for (l = *groups; l; l = l->next) {
+               ret = g_list_prepend (ret, g_strdup (l->data));
        }
+
+       return ret;
 }
 
-static void
-tp_contact_list_request_aliases_cb (DBusGProxy                       *proxy,
-                                   gchar                           **contact_names,
-                                   GError                           *error,
-                                   TpContactListAliasesRequestData  *data)
+static EmpathyTpGroup *
+tp_contact_list_get_group (EmpathyTpContactList *list,
+                          const gchar          *group)
 {
-       guint   i = 0;
-       gchar **name;
+       EmpathyTpContactListPriv *priv = GET_PRIV (list);
+       EmpathyTpGroup           *tp_group;
+       gchar                    *object_path;
+       guint                     handle;
+       GArray                   *handles;
+       const char               *names[2] = {group, NULL};
+       GError                   *error = NULL;
 
-       if (error) {
-               empathy_debug (DEBUG_DOMAIN, "Error requesting aliases: %s",
-                             error->message);
+       tp_group = tp_contact_list_find_group (list, group);
+       if (tp_group) {
+               return tp_group;
        }
 
-       for (name = contact_names; *name && !error; name++) {
-               EmpathyContact *contact;
+       empathy_debug (DEBUG_DOMAIN, "creating new group: %s", group);
 
-               contact = empathy_tp_contact_list_get_from_handle (data->list,
-                                                                  data->handles[i]);
-               tp_contact_list_block_contact (data->list, contact);
-               empathy_contact_set_name (contact, *name);
-               tp_contact_list_unblock_contact (data->list, contact);
-               g_object_unref (contact);
-
-               empathy_debug (DEBUG_DOMAIN, "contact %d renamed to %s (request cb)",
-                             data->handles[i], *name);
+       if (!tp_conn_request_handles (DBUS_G_PROXY (priv->tp_conn),
+                                     TP_HANDLE_TYPE_GROUP,
+                                     names,
+                                     &handles,
+                                     &error)) {
+               empathy_debug (DEBUG_DOMAIN,
+                             "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);
 
-               i++;
+       if (!tp_conn_request_channel (DBUS_G_PROXY (priv->tp_conn),
+                                     TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
+                                     TP_HANDLE_TYPE_GROUP,
+                                     handle,
+                                     FALSE,
+                                     &object_path,
+                                     &error)) {
+               empathy_debug (DEBUG_DOMAIN,
+                             "Failed to RequestChannel: %s",
+                             error ? error->message : "No error given");
+               g_clear_error (&error);
+               return NULL;
        }
 
-       g_free (data->handles);
-       g_slice_free (TpContactListAliasesRequestData, data);
-}
+       tp_contact_list_newchannel_cb (DBUS_G_PROXY (priv->tp_conn),
+                                      object_path,
+                                      TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
+                                      TP_HANDLE_TYPE_GROUP,
+                                      handle, FALSE,
+                                      list);
+       g_free (object_path);
 
-static void
-tp_contact_list_presence_update_cb (DBusGProxy           *proxy,
-                                   GHashTable           *handle_table,
-                                   EmpathyTpContactList *list)
-{
-       g_hash_table_foreach (handle_table,
-                             (GHFunc) tp_contact_list_parse_presence_foreach,
-                             list);
+       return tp_contact_list_find_group (list, group);
 }
 
 static void
-tp_contact_list_parse_presence_foreach (guint                 handle,
-                                       GValueArray          *presence_struct,
-                                       EmpathyTpContactList *list)
+tp_contact_list_add_to_group (EmpathyContactList *list,
+                             EmpathyContact     *contact,
+                             const gchar        *group)
 {
-       EmpathyTpContactListPriv *priv;
-       GHashTable     *presences_table;
-       EmpathyContact  *contact;
-       EmpathyPresence *presence = NULL;
-
-       priv = GET_PRIV (list);
-
-       if (!g_hash_table_lookup (priv->contacts, GUINT_TO_POINTER (handle))) {
-               /* We don't know this contact, skip */
-               return;
-       }
-
-       contact = empathy_tp_contact_list_get_from_handle (list, handle);
-       presences_table = g_value_get_boxed (g_value_array_get_nth (presence_struct, 1));
+       EmpathyTpGroup *tp_group;
 
-       g_hash_table_foreach (presences_table,
-                             (GHFunc) tp_contact_list_presences_table_foreach,
-                             &presence);
-
-       empathy_debug (DEBUG_DOMAIN, "Presence changed for %s (%d) to %s (%d)",
-                     empathy_contact_get_name (contact),
-                     handle,
-                     presence ? empathy_presence_get_status (presence) : "unset",
-                     presence ? empathy_presence_get_state (presence) : MC_PRESENCE_UNSET);
+       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
 
-       tp_contact_list_block_contact (list, contact);
-       empathy_contact_set_presence (contact, presence);
-       tp_contact_list_unblock_contact (list, contact);
+       tp_group = tp_contact_list_get_group (EMPATHY_TP_CONTACT_LIST (list),
+                                             group);
 
-       g_object_unref (contact);
+       empathy_tp_group_add_member (tp_group, contact, "");
 }
 
 static void
-tp_contact_list_presences_table_foreach (const gchar     *state_str,
-                                        GHashTable      *presences_table,
-                                        EmpathyPresence **presence)
+tp_contact_list_remove_from_group (EmpathyContactList *list,
+                                  EmpathyContact     *contact,
+                                  const gchar        *group)
 {
-       McPresence    state;
-       const GValue *message;
-
-       state = empathy_presence_state_from_str (state_str);
-       if ((state == MC_PRESENCE_UNSET) || (state == MC_PRESENCE_OFFLINE)) {
-               return;
-       }
+       EmpathyTpGroup *tp_group;
 
-       if (*presence) {
-               g_object_unref (*presence);
-               *presence = NULL;
-       }
+       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
 
-       *presence = empathy_presence_new ();
-       empathy_presence_set_state (*presence, state);
+       tp_group = tp_contact_list_find_group (EMPATHY_TP_CONTACT_LIST (list),
+                                              group);
 
-       message = g_hash_table_lookup (presences_table, "message");
-       if (message != NULL) {
-               empathy_presence_set_status (*presence,
-                                           g_value_get_string (message));
+       if (tp_group) {
+               empathy_tp_group_remove_member (tp_group, contact, "");
        }
 }
 
 static void
-tp_contact_list_status_changed_cb (MissionControl                  *mc,
-                                  TelepathyConnectionStatus        status,
-                                  McPresence                       presence,
-                                  TelepathyConnectionStatusReason  reason,
-                                  const gchar                     *unique_name,
-                                  EmpathyTpContactList            *list)
+tp_contact_list_rename_group (EmpathyContactList *list,
+                             const gchar        *old_group,
+                             const gchar        *new_group)
 {
-       EmpathyTpContactListPriv *priv;
-       McAccount                *account;
+       EmpathyTpGroup *tp_group;
+       GList          *members;
 
-       priv = GET_PRIV (list);
+       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
 
-       account = mc_account_lookup (unique_name);
-       if (status != TP_CONN_STATUS_DISCONNECTED ||
-           !empathy_account_equal (account, priv->account) ||
-           !priv->tp_conn) {
-               g_object_unref (account);
+       tp_group = tp_contact_list_find_group (EMPATHY_TP_CONTACT_LIST (list),
+                                              old_group);
+       if (!tp_group) {
                return;
        }
 
-       /* We are disconnected, do just like if the connection was destroyed */
-       g_signal_handlers_disconnect_by_func (priv->tp_conn,
-                                             tp_contact_list_destroy_cb,
-                                             list);
-       tp_contact_list_destroy_cb (DBUS_G_PROXY (priv->tp_conn), list);
+       empathy_debug (DEBUG_DOMAIN, "rename group %s to %s", old_group, new_group);
 
-       g_object_unref (account);
+       /* 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);
+
+       /* 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, "");
+
+       g_list_foreach (members, (GFunc) g_object_unref, NULL);
+       g_list_free (members);
+}
+
+static void
+tp_contact_list_iface_init (EmpathyContactListIface *iface)
+{
+       iface->add               = tp_contact_list_add;
+       iface->remove            = tp_contact_list_remove;
+       iface->get_members       = tp_contact_list_get_members;
+       iface->get_pendings      = tp_contact_list_get_pendings;
+       iface->get_all_groups    = tp_contact_list_get_all_groups;
+       iface->get_groups        = tp_contact_list_get_groups;
+       iface->add_to_group      = tp_contact_list_add_to_group;
+       iface->remove_from_group = tp_contact_list_remove_from_group;
+       iface->rename_group      = tp_contact_list_rename_group;
 }
 
index f0eccb37525979a7a03f2281166b913a1e39eac4..6ac4662fae718e3f44137b1a8ec4cfa324a736c9 100644 (file)
@@ -50,20 +50,9 @@ struct _EmpathyTpContactListClass {
        GObjectClass parent_class;
 };
 
-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);
-EmpathyContact *        empathy_tp_contact_list_get_user         (EmpathyTpContactList *list);
-EmpathyContact *        empathy_tp_contact_list_get_from_id      (EmpathyTpContactList *list,
-                                                                const gchar          *id);
-EmpathyContact *        empathy_tp_contact_list_get_from_handle  (EmpathyTpContactList *list,
-                                                                guint                 handle);
-GList *                empathy_tp_contact_list_get_from_handles (EmpathyTpContactList *list,
-                                                                GArray               *handles);
-void                   empathy_tp_contact_list_rename_group     (EmpathyTpContactList *list,
-                                                                const gchar          *old_group,
-                                                                const gchar          *new_group);
-GList *                empathy_tp_contact_list_get_groups       (EmpathyTpContactList *list);
+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);
 
 G_END_DECLS
 
index b86a00e28139a56cd989738a21f200acc249a3b1..1ffab9ecd2d27a8078ed40aacc43824e710cd4c3 100644 (file)
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2006 Xavier Claessens <xclaesse@gmail.com>
+ * Copyright (C) 2007 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
  * 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: Xavier Claessens <xclaesse@gmail.com>
  */
 
 #include <config.h>
 
 #include <dbus/dbus-glib.h>
 #include <libtelepathy/tp-chan.h>
+#include <libtelepathy/tp-chan-gen.h>
 #include <libtelepathy/tp-chan-iface-group-gen.h>
 #include <libtelepathy/tp-constants.h>
 #include <libtelepathy/tp-conn.h>
 
-#include "empathy-debug.h"
 #include "empathy-tp-group.h"
+#include "empathy-contact-factory.h"
+#include "empathy-debug.h"
 #include "empathy-utils.h"
 #include "empathy-marshal.h"
 
 #define DEBUG_DOMAIN "TpGroup"
 
 struct _EmpathyTpGroupPriv {
-       McAccount  *account;
-       DBusGProxy *group_iface;
-       TpChan     *tp_chan;
-       gchar      *group_name;
+       EmpathyContactFactory *factory;
+       McAccount             *account;
+       DBusGProxy            *group_iface;
+       TpChan                *tp_chan;
+       gchar                 *group_name;
+       guint                  self_handle;
+
+       GList                 *members;
+       GList                 *local_pendings;
+       GList                 *remote_pendings;
 };
 
 static void empathy_tp_group_class_init (EmpathyTpGroupClass *klass);
 static void empathy_tp_group_init       (EmpathyTpGroup      *group);
-static void tp_group_finalize           (GObject             *object);
-static void tp_group_destroy_cb         (DBusGProxy          *proxy,
-                                        EmpathyTpGroup      *group);
-static void tp_group_members_changed_cb (DBusGProxy          *group_iface,
-                                        gchar               *message,
-                                        GArray              *added,
-                                        GArray              *removed,
-                                        GArray              *local_pending,
-                                        GArray              *remote_pending,
-                                        guint                actor,
-                                        guint                reason,
-                                        EmpathyTpGroup      *group);
 
 enum {
-       MEMBERS_ADDED,
-       MEMBERS_REMOVED,
+       MEMBER_ADDED,
+       MEMBER_REMOVED,
        LOCAL_PENDING,
        REMOTE_PENDING,
+       DESTROY,
        LAST_SIGNAL
 };
 
@@ -70,6 +70,409 @@ 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 && empathy_contact_get_handle (contact) == priv->self_handle) {
+               empathy_contact_set_is_user (contact, TRUE);
+       }
+
+       return contact;
+}
+
+static GList *
+tp_group_get_contacts (EmpathyTpGroup *group,
+                      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_members_changed_cb (DBusGProxy     *group_iface,
+                            const gchar    *message,
+                            GArray         *added,
+                            GArray         *removed,
+                            GArray         *local_pending,
+                            GArray         *remote_pending,
+                            guint           actor,
+                            guint           reason,
+                            EmpathyTpGroup *group)
+{
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+       EmpathyContact     *actor_contact = NULL;
+       GList              *contacts, *l, *ll;
+
+       actor_contact = tp_group_get_contact (group, actor);
+
+       empathy_debug (DEBUG_DOMAIN, "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",
+                      empathy_tp_group_get_name (group),
+                      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->members, 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);
+       }
+
+       empathy_debug (DEBUG_DOMAIN, "Members changed done for list %s:\n"
+                                    "  members-len=%d\n"
+                                    "  local-pendings-len=%d\n"
+                                    "  remote-pendings-len=%d",
+                      empathy_tp_group_get_name (group),
+                      g_list_length (priv->members),
+                      g_list_length (priv->local_pendings),
+                      g_list_length (priv->remote_pendings));
+}
+
+static void
+tp_group_destroy_cb (TpChan         *tp_chan,
+                    EmpathyTpGroup *group)
+{
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+
+       empathy_debug (DEBUG_DOMAIN, "Account disconnected or CM crashed");
+
+       g_object_unref (priv->tp_chan);
+       priv->group_iface = NULL;
+       priv->tp_chan = NULL;
+
+       g_signal_emit (group, signals[DESTROY], 0);
+}
+
+static void tp_group_closed_cb (DBusGProxy     *proxy,
+                               EmpathyTpGroup *group);
+
+static void
+tp_group_disconnect (EmpathyTpGroup *group)
+{
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+
+       if (priv->group_iface) {
+               dbus_g_proxy_disconnect_signal (priv->group_iface, "MembersChanged",
+                                               G_CALLBACK (tp_group_members_changed_cb),
+                                               group);
+       }
+       if (priv->tp_chan) {
+               g_signal_handlers_disconnect_by_func (priv->tp_chan,
+                                                     tp_group_destroy_cb,
+                                                     group);
+               dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->tp_chan), "Closed",
+                                               G_CALLBACK (tp_group_closed_cb),
+                                               group);
+       }
+}
+
+static void
+tp_group_closed_cb (DBusGProxy     *proxy,
+                   EmpathyTpGroup *group)
+{
+       tp_group_disconnect (group);
+       tp_group_destroy_cb (TELEPATHY_CHAN (proxy), group);
+}
+
+static void
+tp_group_get_members_cb (DBusGProxy *proxy,
+                        GArray     *handles,
+                        GError     *error,
+                        gpointer    user_data)
+{
+       EmpathyTpGroup     *group = user_data;
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+
+       if (error) {
+               empathy_debug (DEBUG_DOMAIN, "Failed to get members: %s",
+                              error->message);
+               return;
+       }
+
+       tp_group_members_changed_cb (priv->group_iface,
+                                    NULL,    /* message */
+                                    handles, /* added */
+                                    NULL,    /* removed */
+                                    NULL,    /* local_pending */
+                                    NULL,    /* remote_pending */
+                                    0,       /* actor */
+                                    0,       /* reason */
+                                    group);
+}
+
+static void
+tp_group_get_local_pending_cb (DBusGProxy *proxy,
+                              GPtrArray  *array,
+                              GError     *error,
+                              gpointer    user_data)
+{
+       EmpathyTpGroup     *group = user_data;
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+       GArray             *handles;
+       guint               i;
+       
+       if (error) {
+               empathy_debug (DEBUG_DOMAIN, "Failed to get local pendings: %s",
+                              error->message);
+               return;
+       }
+
+       handles = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
+       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_insert_val (handles, 0, member_handle);
+               tp_group_members_changed_cb (priv->group_iface,
+                                            message,      /* message */
+                                            NULL,         /* added */
+                                            NULL,         /* removed */
+                                            handles,      /* local_pending */
+                                            NULL,         /* remote_pending */
+                                            actor_handle, /* actor */
+                                            reason,       /* reason */
+                                            group);
+       }
+       g_array_free (handles, TRUE);
+}
+
+static void
+tp_group_get_remote_pending_cb (DBusGProxy *proxy,
+                               GArray     *handles,
+                               GError     *error,
+                               gpointer    user_data)
+{
+       EmpathyTpGroup     *group = user_data;
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+       
+       if (error) {
+               empathy_debug (DEBUG_DOMAIN, "Failed to get remote pendings: %s",
+                              error->message);
+               return;
+       }
+
+       tp_group_members_changed_cb (priv->group_iface,
+                                    NULL,    /* message */
+                                    NULL,    /* added */
+                                    NULL,    /* removed */
+                                    NULL,    /* local_pending */
+                                    handles, /* remote_pending */
+                                    0,       /* actor */
+                                    0,       /* reason */
+                                    group);
+}
+
+static void
+tp_group_finalize (GObject *object)
+{
+       EmpathyTpGroupPriv *priv = GET_PRIV (object);
+
+       tp_group_disconnect (EMPATHY_TP_GROUP (object));
+
+       if (priv->tp_chan) {
+               g_object_unref (priv->tp_chan);
+       }
+       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
 empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
 {
@@ -77,25 +480,25 @@ empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
 
        object_class->finalize = tp_group_finalize;
 
-       signals[MEMBERS_ADDED] =
-               g_signal_new ("members-added",
+       signals[MEMBER_ADDED] =
+               g_signal_new ("member-added",
                              G_TYPE_FROM_CLASS (klass),
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
-                             empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
+                             empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
                              G_TYPE_NONE,
-                             4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
+                             4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
 
-       signals[MEMBERS_REMOVED] =
-               g_signal_new ("members-removed",
+       signals[MEMBER_REMOVED] =
+               g_signal_new ("member-removed",
                              G_TYPE_FROM_CLASS (klass),
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
-                             empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
+                             empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
                              G_TYPE_NONE,
-                             4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
+                             4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
 
        signals[LOCAL_PENDING] =
                g_signal_new ("local-pending",
@@ -103,9 +506,9 @@ empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
-                             empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
+                             empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
                              G_TYPE_NONE,
-                             4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
+                             4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
 
        signals[REMOTE_PENDING] =
                g_signal_new ("remote-pending",
@@ -113,9 +516,19 @@ empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
-                             empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
+                             empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
                              G_TYPE_NONE,
-                             4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
+                             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));
 }
@@ -125,36 +538,6 @@ empathy_tp_group_init (EmpathyTpGroup *group)
 {
 }
 
-static void
-tp_group_finalize (GObject *object)
-{
-       EmpathyTpGroupPriv *priv;
-
-       priv = GET_PRIV (object);
-
-       if (priv->group_iface) {
-               g_signal_handlers_disconnect_by_func (priv->group_iface,
-                                                     tp_group_destroy_cb,
-                                                     object);
-               dbus_g_proxy_disconnect_signal (priv->group_iface, "MembersChanged",
-                                               G_CALLBACK (tp_group_members_changed_cb),
-                                               object);
-               g_object_unref (priv->group_iface);
-       }
-
-       if (priv->account) {
-               g_object_unref (priv->account);
-       }
-
-       if (priv->tp_chan) {
-               g_object_unref (priv->tp_chan);
-       }
-
-       g_free (priv->group_name);
-
-       G_OBJECT_CLASS (empathy_tp_group_parent_class)->finalize (object);
-}
-
 EmpathyTpGroup *
 empathy_tp_group_new (McAccount *account,
                      TpChan    *tp_chan)
@@ -162,6 +545,7 @@ empathy_tp_group_new (McAccount *account,
        EmpathyTpGroup     *group;
        EmpathyTpGroupPriv *priv;
        DBusGProxy         *group_iface;
+       GError             *error;
 
        g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL);
        g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
@@ -175,262 +559,205 @@ empathy_tp_group_new (McAccount *account,
 
        priv->account = g_object_ref (account);
        priv->tp_chan = g_object_ref (tp_chan);
-       priv->group_iface = g_object_ref (group_iface);
+       priv->group_iface = group_iface;
+       priv->factory = empathy_contact_factory_new ();
+
+       if (!tp_chan_iface_group_get_self_handle (priv->group_iface,
+                                                 &priv->self_handle,
+                                                 &error)) {
+               empathy_debug (DEBUG_DOMAIN, 
+                             "Failed to get self handle: %s",
+                             error ? error->message : "No error given");
+               g_clear_error (&error);
+       }
 
        dbus_g_proxy_connect_signal (priv->group_iface, "MembersChanged",
                                     G_CALLBACK (tp_group_members_changed_cb),
                                     group, NULL);
-       g_signal_connect (group_iface, "destroy",
+       dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_chan), "Closed",
+                                    G_CALLBACK (tp_group_closed_cb),
+                                    group, NULL);
+       g_signal_connect (priv->tp_chan, "destroy",
                          G_CALLBACK (tp_group_destroy_cb),
                          group);
 
+       tp_chan_iface_group_get_members_async (priv->group_iface,
+                                              tp_group_get_members_cb,
+                                              group);
+       tp_chan_iface_group_get_local_pending_members_with_info_async (priv->group_iface,
+                                                                      tp_group_get_local_pending_cb,
+                                                                      group);
+       tp_chan_iface_group_get_remote_pending_members_async (priv->group_iface,
+                                                             tp_group_get_remote_pending_cb,
+                                                             group);
+
        return group;
 }
 
+static void
+tp_group_async_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+       const gchar *msg = user_data;
+
+       if (error) {
+               empathy_debug (DEBUG_DOMAIN, "%s: %s", msg, error->message);
+       }
+}
+
+void
+empathy_tp_group_close  (EmpathyTpGroup *group)
+{
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+
+       tp_chan_close_async (DBUS_G_PROXY (priv->tp_chan),
+                            tp_group_async_cb,
+                            "Failed to close");
+}
+
+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,
-                             GArray         *handles,
+                             GList          *contacts,
                              const gchar    *message)
 {
-       EmpathyTpGroupPriv *priv;
-       GError             *error = NULL;
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+       GArray             *handles;
 
        g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
-       g_return_if_fail (handles != NULL);
+       g_return_if_fail (contacts != NULL);
 
-       priv = GET_PRIV (group);
+       handles = tp_group_get_handles (contacts);
+       tp_chan_iface_group_add_members_async (priv->group_iface,
+                                              handles,
+                                              message,
+                                              tp_group_async_cb,
+                                              "Failed to add members");
 
-       if (!tp_chan_iface_group_add_members (priv->group_iface,
-                                             handles,
-                                             message,
-                                             &error)) {
-               empathy_debug (DEBUG_DOMAIN,
-                             "Failed to add members: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-       }
+       g_array_free (handles, TRUE);
 }
 
 void
 empathy_tp_group_add_member (EmpathyTpGroup *group,
-                            guint           handle,
+                            EmpathyContact *contact,
                             const gchar    *message)
 {
-       GArray *handles;
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+       GArray             *handles;
+       guint               handle;
 
+       handle = empathy_contact_get_handle (contact);
        handles = g_array_new (FALSE, FALSE, sizeof (guint));
        g_array_append_val (handles, handle);
 
-       empathy_tp_group_add_members (group, handles, message);
+       tp_chan_iface_group_add_members_async (priv->group_iface,
+                                              handles,
+                                              message,
+                                              tp_group_async_cb,
+                                              "Failed to add member");
 
        g_array_free (handles, TRUE);
 }
 
 void
 empathy_tp_group_remove_members (EmpathyTpGroup *group,
-                                GArray         *handles,
+                                GList          *contacts,
                                 const gchar    *message)
 {
-       EmpathyTpGroupPriv *priv;
-       GError             *error = NULL;
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+       GArray             *handles;
 
        g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
+       g_return_if_fail (contacts != NULL);
 
-       priv = GET_PRIV (group);
+       handles = tp_group_get_handles (contacts);
+       tp_chan_iface_group_remove_members_async (priv->group_iface,
+                                                 handles,
+                                                 message,
+                                                 tp_group_async_cb,
+                                                 "Failed to remove members");
 
-       if (!tp_chan_iface_group_remove_members (priv->group_iface,
-                                                handles,
-                                                message,
-                                                &error)) {
-               empathy_debug (DEBUG_DOMAIN, 
-                             "Failed to remove members: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-       }
+       g_array_free (handles, TRUE);
 }
 
 void
 empathy_tp_group_remove_member (EmpathyTpGroup *group,
-                               guint           handle,
+                               EmpathyContact *contact,
                                const gchar    *message)
 {
-       GArray *handles;
-
-       g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+       GArray             *handles;
+       guint               handle;
 
+       handle = empathy_contact_get_handle (contact);
        handles = g_array_new (FALSE, FALSE, sizeof (guint));
        g_array_append_val (handles, handle);
 
-       empathy_tp_group_remove_members (group, handles, message);
+       tp_chan_iface_group_remove_members_async (priv->group_iface,
+                                                 handles,
+                                                 message,
+                                                 tp_group_async_cb,
+                                                 "Failed to remove member");
 
        g_array_free (handles, TRUE);
 }
 
-GArray *
+GList *
 empathy_tp_group_get_members (EmpathyTpGroup *group)
 {
-       EmpathyTpGroupPriv *priv;
-       GArray             *members;
-       GError             *error = NULL;
+       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);
 
-       priv = GET_PRIV (group);
-
-       if (!tp_chan_iface_group_get_members (priv->group_iface,
-                                             &members,
-                                             &error)) {
-               empathy_debug (DEBUG_DOMAIN, 
-                             "Couldn't get members: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-               return NULL;
-       }
-
-       return members;
-}
-
-void
-empathy_tp_group_get_all_members (EmpathyTpGroup  *group,
-                                 GArray         **members,
-                                 GArray         **local_pending,
-                                 GArray         **remote_pending)
-{
-       EmpathyTpGroupPriv *priv;
-       GError             *error = NULL;
-
-       g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
-
-       priv = GET_PRIV (group);
-
-       if (!tp_chan_iface_group_get_all_members (priv->group_iface,
-                                                 members,
-                                                 local_pending,
-                                                 remote_pending,
-                                                 &error)) {
-               empathy_debug (DEBUG_DOMAIN,
-                             "Couldn't get all members: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-       }
+       return g_list_copy (priv->members);
 }
 
 GList *
-empathy_tp_group_get_local_pending_members_with_info (EmpathyTpGroup *group)
-{
-       EmpathyTpGroupPriv *priv;
-       GPtrArray          *array;
-       guint               i;
-       GList              *infos = NULL;
-       GError             *error = NULL;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
-
-       priv = GET_PRIV (group);
-
-       if (!tp_chan_iface_group_get_local_pending_members_with_info (priv->group_iface,
-                                                                     &array,
-                                                                     &error)) {
-               empathy_debug (DEBUG_DOMAIN, 
-                             "GetLocalPendingMembersWithInfo failed: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-
-               return NULL;
-       }
-
-       if (!array) {
-               /* This happens with butterfly because
-                * GetLocalPendingMembersWithInfo is not 
-                * implemented */
-               return NULL;
-       }
-
-       for (i = 0; array->len > i; i++) {
-               GValueArray        *pending_struct;
-               EmpathyTpGroupInfo *info;
-               const gchar        *message;
-
-               info = g_slice_new (EmpathyTpGroupInfo);
-
-               pending_struct = g_ptr_array_index (array, i);
-               info->member = g_value_get_uint (g_value_array_get_nth (pending_struct, 0));
-               info->actor = g_value_get_uint (g_value_array_get_nth (pending_struct, 1));
-               info->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));
-               info->message = g_strdup (message);
-               g_value_array_free (pending_struct);
-
-               infos = g_list_prepend (infos, info);
-       }
-       g_ptr_array_free (array, TRUE);
-
-       return infos;
-}
-
-void
-empathy_tp_group_info_list_free (GList *infos)
+empathy_tp_group_get_local_pendings (EmpathyTpGroup *group)
 {
-       GList *l;
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+       GList              *pendings = NULL, *l;
 
-       for (l = infos; l; l = l->next) {
-               EmpathyTpGroupInfo *info;
+       for (l = priv->local_pendings; l; l = l->next) {
+               EmpathyPendingInfo *info;
+               EmpathyPendingInfo *new_info;
 
                info = l->data;
-
-               g_free (info->message);
-               g_slice_free (EmpathyTpGroupInfo, info);
+               new_info = empathy_pending_info_new (info->member,
+                                                    info->actor,
+                                                    info->message);
+               pendings = g_list_prepend (pendings, new_info);
        }
-       g_list_free (infos);
-}
 
-
-static void
-tp_group_destroy_cb (DBusGProxy     *proxy,
-                    EmpathyTpGroup *group)
-{
-       EmpathyTpGroupPriv *priv;
-
-       priv = GET_PRIV (group);
-
-       g_object_unref (priv->group_iface);
-       g_object_unref (priv->tp_chan);
-       priv->group_iface = NULL;
-       priv->tp_chan = NULL;
+       return pendings;
 }
 
-static void
-tp_group_members_changed_cb (DBusGProxy     *group_iface,
-                            gchar          *message,
-                            GArray         *added,
-                            GArray         *removed,
-                            GArray         *local_pending,
-                            GArray         *remote_pending,
-                            guint           actor,
-                            guint           reason,
-                            EmpathyTpGroup *group)
+GList *
+empathy_tp_group_get_remote_pendings (EmpathyTpGroup *group)
 {
-       EmpathyTpGroupPriv *priv;
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
 
-       priv = GET_PRIV (group);
+       g_list_foreach (priv->remote_pendings, (GFunc) g_object_ref, NULL);
 
-       /* emit signals */
-       if (added->len > 0) {
-               g_signal_emit (group, signals[MEMBERS_ADDED], 0, 
-                              added, actor, reason, message);
-       }
-       if (removed->len > 0) {
-               g_signal_emit (group, signals[MEMBERS_REMOVED], 0, 
-                              removed, actor, reason, message);
-       }
-       if (local_pending->len > 0) {
-               g_signal_emit (group, signals[LOCAL_PENDING], 0,
-                              local_pending, actor, reason, message);
-       }
-       if (remote_pending->len > 0) {
-               g_signal_emit (group, signals[REMOTE_PENDING], 0,
-                              remote_pending, actor, reason, message);
-       }
+       return g_list_copy (priv->remote_pendings);
 }
 
 const gchar *
@@ -443,35 +770,21 @@ empathy_tp_group_get_name (EmpathyTpGroup *group)
        priv = GET_PRIV (group);
 
        /* Lazy initialisation */
-       if (priv->group_name) {
-               return priv->group_name;
+       if (!priv->group_name) {
+               priv->group_name = empathy_inspect_channel (priv->account, priv->tp_chan);
        }
 
-       priv->group_name = empathy_inspect_channel (priv->account, priv->tp_chan);
-
        return priv->group_name;
 }
 
-guint 
-empathy_tp_group_get_self_handle (EmpathyTpGroup *group)
+EmpathyContact *
+empathy_tp_group_get_self_contact (EmpathyTpGroup *group)
 {
-       EmpathyTpGroupPriv *priv;
-       guint               handle;
-       GError             *error = NULL;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), 0 );
-
-       priv = GET_PRIV (group);
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
 
-       if (!tp_chan_iface_group_get_self_handle (priv->group_iface, &handle, &error)) {
-               empathy_debug (DEBUG_DOMAIN, 
-                             "Failed to get self handle: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-               return 0;
-       }
+       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
 
-       return handle;
+       return tp_group_get_contact (group, priv->self_handle);
 }
 
 const gchar *
@@ -488,21 +801,10 @@ empathy_tp_group_get_object_path (EmpathyTpGroup *group)
 
 gboolean
 empathy_tp_group_is_member (EmpathyTpGroup *group,
-                           guint           handle)
+                           EmpathyContact *contact)
 {
-       GArray   *members;
-       guint     i;
-       gboolean  found = FALSE;
-
-       members = empathy_tp_group_get_members (group);
-       for (i = 0; i < members->len; i++) {
-               if (g_array_index (members, guint, i) == handle) {
-                       found = TRUE;
-                       break;
-               }
-       }
-       g_array_free (members, TRUE);
-       
-       return found;
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+
+       return g_list_find (priv->members, contact) != NULL;
 }
 
index 5ea7bfc710f092ba1daf2fa89eef0c93f995c621..14cbd4649992b6b5d51908278cbc76a27bb645de 100644 (file)
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2006 Xavier Claessens <xclaesse@gmail.com>
+ * Copyright (C) 2007 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
@@ -16,6 +17,8 @@
  * 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: Xavier Claessens <xclaesse@gmail.com>
  */
 
 #ifndef __EMPATHY_TP_GROUP_H__
 #include <glib.h>
 
 #include <libtelepathy/tp-chan.h>
+#include <libtelepathy/tp-constants.h>
 #include <libmissioncontrol/mc-account.h>
 
+#include "empathy-contact.h"
+
 G_BEGIN_DECLS
 
 #define EMPATHY_TYPE_TP_GROUP         (empathy_tp_group_get_type ())
@@ -48,39 +54,40 @@ struct _EmpathyTpGroupClass {
 };
 
 typedef struct {
-       guint  member;
-       guint  actor;
-       guint  reason;
-       gchar *message;
-} EmpathyTpGroupInfo;
+       EmpathyContact *member;
+       EmpathyContact *actor;
+       gchar          *message;
+       guint           reason;
+} EmpathyPendingInfo;
 
-GType            empathy_tp_group_get_type                            (void) G_GNUC_CONST;
-EmpathyTpGroup * empathy_tp_group_new                                 (McAccount       *account,
-                                                                      TpChan          *tp_chan);
-void             empathy_tp_group_add_members                         (EmpathyTpGroup  *group,
-                                                                      GArray          *handles,
-                                                                      const gchar     *message);
-void             empathy_tp_group_add_member                          (EmpathyTpGroup  *group,
-                                                                      guint            handle,
-                                                                      const gchar     *message);
-void             empathy_tp_group_remove_members                      (EmpathyTpGroup  *group,
-                                                                      GArray          *handle,
-                                                                      const gchar     *message);
-void             empathy_tp_group_remove_member                       (EmpathyTpGroup  *group,
-                                                                      guint            handle,
-                                                                      const gchar     *message);
-GArray *         empathy_tp_group_get_members                         (EmpathyTpGroup  *group);
-void             empathy_tp_group_get_all_members                     (EmpathyTpGroup  *group,
-                                                                      GArray         **members,
-                                                                      GArray         **local_pending,
-                                                                      GArray         **remote_pending);
-GList *          empathy_tp_group_get_local_pending_members_with_info (EmpathyTpGroup  *group);
-void             empathy_tp_group_info_list_free                      (GList           *infos);
-const gchar *    empathy_tp_group_get_name                            (EmpathyTpGroup  *group);
-guint            empathy_tp_group_get_self_handle                     (EmpathyTpGroup  *group);
-const gchar *    empathy_tp_group_get_object_path                     (EmpathyTpGroup  *group);
-gboolean         empathy_tp_group_is_member                           (EmpathyTpGroup  *group,
-                                                                      guint            handle);
+GType               empathy_tp_group_get_type            (void) G_GNUC_CONST;
+EmpathyTpGroup *    empathy_tp_group_new                 (McAccount          *account,
+                                                         TpChan             *tp_chan);
+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);
+const gchar *       empathy_tp_group_get_object_path     (EmpathyTpGroup     *group);
+gboolean            empathy_tp_group_is_member           (EmpathyTpGroup     *group,
+                                                         EmpathyContact     *contact);
+EmpathyPendingInfo *empathy_pending_info_new             (EmpathyContact     *member,
+                                                         EmpathyContact     *actor,
+                                                         const gchar        *message);
+void                empathy_pending_info_free            (EmpathyPendingInfo *info);
 
 G_END_DECLS
 
diff --git a/python/README b/python/README
new file mode 100644 (file)
index 0000000..f9c121b
--- /dev/null
@@ -0,0 +1,19 @@
+To update python binding:
+1)
+  $ make distclean
+  $ python /usr/share/pygtk/2.0/codegen/h2def.py libempathy/*.h > python/pyempathy/pyempathy.defs
+  $ python /usr/share/pygtk/2.0/codegen/h2def.py libempathy-gtk/*.h > python/pyempathygtk/pyempathygtk.defs
+
+2)
+Manually modify pyempathy.defs, ContactList is not an object but an interface:
+(define-interface ContactList
+  (in-module "Empathy")
+  (c-name "EmpathyContactList")
+  (gtype-id "EMPATHY_TYPE_CONTACT_LIST")
+)
+
+ContactManager, TpChatroom and TpContactList implements ContactList interface:
+  (implements "EmpathyContactList")
+
+3)
+Manually update headers in pyempathy.override and pyempathygtk.override.
index eea0b76d3b37731734474429b18a0304d559b465..97f7b6ac9bd39b337ae2bb253bfc1a892758d62e 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-object ContactManager
   (in-module "Empathy")
   (parent "GObject")
   (gtype-id "EMPATHY_TYPE_TP_GROUP")
 )
 
-;; Enumerations and flags ...
-
-(define-flags Subscription
+(define-object TpRoomlist
   (in-module "Empathy")
-  (c-name "EmpathySubscription")
-  (gtype-id "EMPATHY_TYPE_SUBSCRIPTION")
-  (values
-    '("none" "EMPATHY_SUBSCRIPTION_NONE")
-    '("to" "EMPATHY_SUBSCRIPTION_TO")
-    '("from" "EMPATHY_SUBSCRIPTION_FROM")
-    '("both" "EMPATHY_SUBSCRIPTION_BOTH")
-  )
+  (parent "GObject")
+  (c-name "EmpathyTpRoomlist")
+  (gtype-id "EMPATHY_TYPE_TP_ROOMLIST")
 )
 
+;; Enumerations and flags ...
+
 (define-enum MessageType
   (in-module "Empathy")
   (c-name "EmpathyMessageType")
 
 ;; From empathy-avatar.h
 
-(define-function empathy_avatar_get_gtype
-  (c-name "empathy_avatar_get_gtype")
+(define-function empathy_avatar_get_type
+  (c-name "empathy_avatar_get_type")
   (return-type "GType")
 )
 
 
 
 
-;; From empathy-chandler-glue.h
-
-(define-function dbus_glib_marshal_empathy_chandler_BOOLEAN__STRING_BOXED_STRING_BOXED_UINT_UINT_POINTER
-  (c-name "dbus_glib_marshal_empathy_chandler_BOOLEAN__STRING_BOXED_STRING_BOXED_UINT_UINT_POINTER")
-  (return-type "none")
-  (parameters
-    '("GClosure*" "closure")
-    '("GValue*" "return_value")
-    '("guint" "n_param_values")
-    '("const-GValue*" "param_values")
-    '("gpointer" "invocation_hint")
-    '("gpointer" "marshal_data")
-  )
-)
-
-
-
 ;; From empathy-chandler.h
 
 (define-function empathy_chandler_get_type
 
 
 
-;; From empathy-chatroom-manager.h
-
-(define-function empathy_chatroom_manager_get_type
-  (c-name "empathy_chatroom_manager_get_type")
-  (return-type "GType")
-)
-
-(define-function empathy_chatroom_manager_new
-  (c-name "empathy_chatroom_manager_new")
-  (is-constructor-of "EmpathyChatroomManager")
-  (return-type "EmpathyChatroomManager*")
-)
-
-(define-method add
-  (of-object "EmpathyChatroomManager")
-  (c-name "empathy_chatroom_manager_add")
-  (return-type "gboolean")
-  (parameters
-    '("EmpathyChatroom*" "chatroom")
-  )
-)
-
-(define-method remove
-  (of-object "EmpathyChatroomManager")
-  (c-name "empathy_chatroom_manager_remove")
-  (return-type "none")
-  (parameters
-    '("EmpathyChatroom*" "chatroom")
-  )
-)
-
-(define-method find
-  (of-object "EmpathyChatroomManager")
-  (c-name "empathy_chatroom_manager_find")
-  (return-type "EmpathyChatroom*")
-  (parameters
-    '("McAccount*" "account")
-    '("const-gchar*" "room")
-  )
-)
-
-(define-method get_chatrooms
-  (of-object "EmpathyChatroomManager")
-  (c-name "empathy_chatroom_manager_get_chatrooms")
-  (return-type "GList*")
-  (parameters
-    '("McAccount*" "account")
-  )
-)
-
-(define-method get_count
-  (of-object "EmpathyChatroomManager")
-  (c-name "empathy_chatroom_manager_get_count")
-  (return-type "guint")
-  (parameters
-    '("McAccount*" "account")
-  )
-)
-
-(define-method store
-  (of-object "EmpathyChatroomManager")
-  (c-name "empathy_chatroom_manager_store")
-  (return-type "none")
-)
-
-
-
 ;; From empathy-chatroom.h
 
 (define-function empathy_chatroom_get_type
 
 
 
+;; From empathy-chatroom-manager.h
+
+(define-function empathy_chatroom_manager_get_type
+  (c-name "empathy_chatroom_manager_get_type")
+  (return-type "GType")
+)
+
+(define-function empathy_chatroom_manager_new
+  (c-name "empathy_chatroom_manager_new")
+  (is-constructor-of "EmpathyChatroomManager")
+  (return-type "EmpathyChatroomManager*")
+)
+
+(define-method add
+  (of-object "EmpathyChatroomManager")
+  (c-name "empathy_chatroom_manager_add")
+  (return-type "gboolean")
+  (parameters
+    '("EmpathyChatroom*" "chatroom")
+  )
+)
+
+(define-method remove
+  (of-object "EmpathyChatroomManager")
+  (c-name "empathy_chatroom_manager_remove")
+  (return-type "none")
+  (parameters
+    '("EmpathyChatroom*" "chatroom")
+  )
+)
+
+(define-method find
+  (of-object "EmpathyChatroomManager")
+  (c-name "empathy_chatroom_manager_find")
+  (return-type "EmpathyChatroom*")
+  (parameters
+    '("McAccount*" "account")
+    '("const-gchar*" "room")
+  )
+)
+
+(define-method get_chatrooms
+  (of-object "EmpathyChatroomManager")
+  (c-name "empathy_chatroom_manager_get_chatrooms")
+  (return-type "GList*")
+  (parameters
+    '("McAccount*" "account")
+  )
+)
+
+(define-method get_count
+  (of-object "EmpathyChatroomManager")
+  (c-name "empathy_chatroom_manager_get_count")
+  (return-type "guint")
+  (parameters
+    '("McAccount*" "account")
+  )
+)
+
+(define-method store
+  (of-object "EmpathyChatroomManager")
+  (c-name "empathy_chatroom_manager_store")
+  (return-type "none")
+)
+
+
+
 ;; From empathy-conf.h
 
 (define-function empathy_conf_get_type
 
 
 
-;; From empathy-contact-list.h
+;; From empathy-contact-factory.h
 
-(define-function contact_list_get_type
-  (c-name "empathy_contact_list_get_type")
+(define-function empathy_contact_factory_get_type
+  (c-name "empathy_contact_factory_get_type")
   (return-type "GType")
 )
 
-(define-method list_info_new
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_list_info_new")
-  (return-type "EmpathyContactListInfo*")
-  (parameters
-    '("const-gchar*" "message")
-  )
-)
-
-(define-method free
-  (of-object "EmpathyContactListInfo")
-  (c-name "empathy_contact_list_info_free")
-  (return-type "none")
-)
-
-(define-method setup
-  (of-object "EmpathyContactList")
-  (c-name "empathy_contact_list_setup")
-  (return-type "none")
+(define-function empathy_contact_factory_new
+  (c-name "empathy_contact_factory_new")
+  (is-constructor-of "EmpathyContactFactory")
+  (return-type "EmpathyContactFactory*")
 )
 
-(define-method find
-  (of-object "EmpathyContactList")
-  (c-name "empathy_contact_list_find")
+(define-method get_user
+  (of-object "EmpathyContactFactory")
+  (c-name "empathy_contact_factory_get_user")
   (return-type "EmpathyContact*")
   (parameters
-    '("const-gchar*" "id")
-  )
-)
-
-(define-method add
-  (of-object "EmpathyContactList")
-  (c-name "empathy_contact_list_add")
-  (return-type "none")
-  (parameters
-    '("EmpathyContact*" "contact")
-    '("const-gchar*" "message")
-  )
-)
-
-(define-method remove
-  (of-object "EmpathyContactList")
-  (c-name "empathy_contact_list_remove")
-  (return-type "none")
-  (parameters
-    '("EmpathyContact*" "contact")
-    '("const-gchar*" "message")
-  )
-)
-
-(define-method get_members
-  (of-object "EmpathyContactList")
-  (c-name "empathy_contact_list_get_members")
-  (return-type "GList*")
-)
-
-(define-method get_local_pending
-  (of-object "EmpathyContactList")
-  (c-name "empathy_contact_list_get_local_pending")
-  (return-type "GList*")
-)
-
-(define-method process_pending
-  (of-object "EmpathyContactList")
-  (c-name "empathy_contact_list_process_pending")
-  (return-type "none")
-  (parameters
-    '("EmpathyContact*" "contact")
-    '("gboolean" "accept")
+    '("McAccount*" "account")
   )
 )
 
-(define-virtual setup
-  (of-object "EmpathyContactList")
-  (return-type "none")
-)
-
-(define-virtual find
-  (of-object "EmpathyContactList")
+(define-method get_from_id
+  (of-object "EmpathyContactFactory")
+  (c-name "empathy_contact_factory_get_from_id")
   (return-type "EmpathyContact*")
-  (parameters
-    '("const-gchar*" "id")
-  )
-)
-
-(define-virtual add
-  (of-object "EmpathyContactList")
-  (return-type "none")
-  (parameters
-    '("EmpathyContact*" "contact")
-    '("const-gchar*" "message")
-  )
-)
-
-(define-virtual remove
-  (of-object "EmpathyContactList")
-  (return-type "none")
-  (parameters
-    '("EmpathyContact*" "contact")
-    '("const-gchar*" "message")
-  )
-)
-
-(define-virtual get_members
-  (of-object "EmpathyContactList")
-  (return-type "GList*")
-)
-
-(define-virtual get_local_pending
-  (of-object "EmpathyContactList")
-  (return-type "GList*")
-)
-
-(define-virtual process_pending
-  (of-object "EmpathyContactList")
-  (return-type "none")
-  (parameters
-    '("EmpathyContact*" "contact")
-    '("gboolean" "accept")
-  )
-)
-
-;; From empathy-contact-manager.h
-
-(define-function empathy_contact_manager_get_type
-  (c-name "empathy_contact_manager_get_type")
-  (return-type "GType")
-)
-
-(define-function empathy_contact_manager_new
-  (c-name "empathy_contact_manager_new")
-  (is-constructor-of "EmpathyContactManager")
-  (return-type "EmpathyContactManager*")
-)
-
-(define-method get_list
-  (of-object "EmpathyContactManager")
-  (c-name "empathy_contact_manager_get_list")
-  (return-type "EmpathyTpContactList*")
   (parameters
     '("McAccount*" "account")
+    '("const-gchar*" "id")
   )
 )
 
-(define-method get_user
-  (of-object "EmpathyContactManager")
-  (c-name "empathy_contact_manager_get_user")
+(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 create
-  (of-object "EmpathyContactManager")
-  (c-name "empathy_contact_manager_create")
-  (return-type "EmpathyContact*")
+(define-method get_from_handles
+  (of-object "EmpathyContactFactory")
+  (c-name "empathy_contact_factory_get_from_handles")
+  (return-type "GList*")
   (parameters
     '("McAccount*" "account")
-    '("const-gchar*" "id")
+    '("GArray*" "handles")
   )
 )
 
-(define-method rename_group
-  (of-object "EmpathyContactManager")
-  (c-name "empathy_contact_manager_rename_group")
+(define-method set_name
+  (of-object "EmpathyContactFactory")
+  (c-name "empathy_contact_factory_set_name")
   (return-type "none")
   (parameters
-    '("const-gchar*" "old_group")
-    '("const-gchar*" "new_group")
+    '("EmpathyContact*" "contact")
+    '("const-gchar*" "name")
   )
 )
 
-(define-method get_groups
-  (of-object "EmpathyContactManager")
-  (c-name "empathy_contact_manager_get_groups")
-  (return-type "GList*")
-)
-
 
 
 ;; From empathy-contact.h
 
-(define-function empathy_contact_get_gtype
-  (c-name "empathy_contact_get_gtype")
+(define-function empathy_contact_get_type
+  (c-name "empathy_contact_get_type")
   (return-type "GType")
 )
 
   (return-type "const-gchar*")
 )
 
+(define-method set_id
+  (of-object "EmpathyContact")
+  (c-name "empathy_contact_set_id")
+  (return-type "none")
+  (parameters
+    '("const-gchar*" "id")
+  )
+)
+
 (define-method get_name
   (of-object "EmpathyContact")
   (c-name "empathy_contact_get_name")
   (return-type "const-gchar*")
 )
 
+(define-method set_name
+  (of-object "EmpathyContact")
+  (c-name "empathy_contact_set_name")
+  (return-type "none")
+  (parameters
+    '("const-gchar*" "name")
+  )
+)
+
 (define-method get_avatar
   (of-object "EmpathyContact")
   (c-name "empathy_contact_get_avatar")
   (return-type "EmpathyAvatar*")
 )
 
+(define-method set_avatar
+  (of-object "EmpathyContact")
+  (c-name "empathy_contact_set_avatar")
+  (return-type "none")
+  (parameters
+    '("EmpathyAvatar*" "avatar")
+  )
+)
+
 (define-method get_account
   (of-object "EmpathyContact")
   (c-name "empathy_contact_get_account")
   (return-type "McAccount*")
 )
 
-(define-method get_presence
+(define-method set_account
   (of-object "EmpathyContact")
-  (c-name "empathy_contact_get_presence")
-  (return-type "EmpathyPresence*")
+  (c-name "empathy_contact_set_account")
+  (return-type "none")
+  (parameters
+    '("McAccount*" "account")
+  )
 )
 
-(define-method get_groups
+(define-method get_presence
   (of-object "EmpathyContact")
-  (c-name "empathy_contact_get_groups")
-  (return-type "GList*")
+  (c-name "empathy_contact_get_presence")
+  (return-type "EmpathyPresence*")
 )
 
-(define-method get_subscription
+(define-method set_presence
   (of-object "EmpathyContact")
-  (c-name "empathy_contact_get_subscription")
-  (return-type "EmpathySubscription")
+  (c-name "empathy_contact_set_presence")
+  (return-type "none")
+  (parameters
+    '("EmpathyPresence*" "presence")
+  )
 )
 
 (define-method get_handle
   (return-type "guint")
 )
 
+(define-method set_handle
+  (of-object "EmpathyContact")
+  (c-name "empathy_contact_set_handle")
+  (return-type "none")
+  (parameters
+    '("guint" "handle")
+  )
+)
+
 (define-method is_user
   (of-object "EmpathyContact")
   (c-name "empathy_contact_is_user")
   (return-type "gboolean")
 )
 
-(define-method set_id
+(define-method set_is_user
   (of-object "EmpathyContact")
-  (c-name "empathy_contact_set_id")
+  (c-name "empathy_contact_set_is_user")
   (return-type "none")
   (parameters
-    '("const-gchar*" "id")
+    '("gboolean" "is_user")
   )
 )
 
-(define-method set_name
+(define-method is_online
   (of-object "EmpathyContact")
-  (c-name "empathy_contact_set_name")
-  (return-type "none")
+  (c-name "empathy_contact_is_online")
+  (return-type "gboolean")
+)
+
+(define-method get_status
+  (of-object "EmpathyContact")
+  (c-name "empathy_contact_get_status")
+  (return-type "const-gchar*")
+)
+
+(define-function empathy_contact_equal
+  (c-name "empathy_contact_equal")
+  (return-type "gboolean")
   (parameters
-    '("const-gchar*" "name")
+    '("gconstpointer" "v1")
+    '("gconstpointer" "v2")
   )
 )
 
-(define-method set_avatar
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_set_avatar")
-  (return-type "none")
+(define-function empathy_contact_hash
+  (c-name "empathy_contact_hash")
+  (return-type "guint")
   (parameters
-    '("EmpathyAvatar*" "avatar")
+    '("gconstpointer" "key")
   )
 )
 
-(define-method set_account
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_set_account")
-  (return-type "none")
-  (parameters
-    '("McAccount*" "account")
-  )
+
+
+;; From empathy-contact-list.h
+
+(define-function empathy_contact_list_get_type
+  (c-name "empathy_contact_list_get_type")
+  (return-type "GType")
 )
 
-(define-method set_presence
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_set_presence")
+(define-method add
+  (of-object "EmpathyContactList")
+  (c-name "empathy_contact_list_add")
   (return-type "none")
   (parameters
-    '("EmpathyPresence*" "presence")
+    '("EmpathyContact*" "contact")
+    '("const-gchar*" "message")
   )
 )
 
-(define-method set_groups
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_set_groups")
+(define-method remove
+  (of-object "EmpathyContactList")
+  (c-name "empathy_contact_list_remove")
   (return-type "none")
   (parameters
-    '("GList*" "categories")
+    '("EmpathyContact*" "contact")
+    '("const-gchar*" "message")
   )
 )
 
-(define-method set_subscription
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_set_subscription")
-  (return-type "none")
-  (parameters
-    '("EmpathySubscription" "subscription")
-  )
+(define-method get_members
+  (of-object "EmpathyContactList")
+  (c-name "empathy_contact_list_get_members")
+  (return-type "GList*")
 )
 
-(define-method set_handle
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_set_handle")
-  (return-type "none")
-  (parameters
-    '("guint" "handle")
-  )
+(define-method get_pendings
+  (of-object "EmpathyContactList")
+  (c-name "empathy_contact_list_get_pendings")
+  (return-type "GList*")
 )
 
-(define-method set_is_user
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_set_is_user")
-  (return-type "none")
+(define-method get_all_groups
+  (of-object "EmpathyContactList")
+  (c-name "empathy_contact_list_get_all_groups")
+  (return-type "GList*")
+)
+
+(define-method get_groups
+  (of-object "EmpathyContactList")
+  (c-name "empathy_contact_list_get_groups")
+  (return-type "GList*")
   (parameters
-    '("gboolean" "is_user")
+    '("EmpathyContact*" "contact")
   )
 )
 
-(define-method add_group
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_add_group")
+(define-method add_to_group
+  (of-object "EmpathyContactList")
+  (c-name "empathy_contact_list_add_to_group")
   (return-type "none")
   (parameters
+    '("EmpathyContact*" "contact")
     '("const-gchar*" "group")
   )
 )
 
-(define-method remove_group
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_remove_group")
+(define-method remove_from_group
+  (of-object "EmpathyContactList")
+  (c-name "empathy_contact_list_remove_from_group")
   (return-type "none")
   (parameters
+    '("EmpathyContact*" "contact")
     '("const-gchar*" "group")
   )
 )
 
-(define-method is_online
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_is_online")
-  (return-type "gboolean")
-)
-
-(define-method is_in_group
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_is_in_group")
-  (return-type "gboolean")
+(define-method rename_group
+  (of-object "EmpathyContactList")
+  (c-name "empathy_contact_list_rename_group")
+  (return-type "none")
   (parameters
-    '("const-gchar*" "group")
+    '("const-gchar*" "old_group")
+    '("const-gchar*" "new_group")
   )
 )
 
-(define-method get_status
-  (of-object "EmpathyContact")
-  (c-name "empathy_contact_get_status")
-  (return-type "const-gchar*")
+
+
+;; From empathy-contact-manager.h
+
+(define-function empathy_contact_manager_get_type
+  (c-name "empathy_contact_manager_get_type")
+  (return-type "GType")
 )
 
-(define-function empathy_contact_equal
-  (c-name "empathy_contact_equal")
-  (return-type "gboolean")
-  (parameters
-    '("gconstpointer" "v1")
-    '("gconstpointer" "v2")
-  )
+(define-function empathy_contact_manager_new
+  (c-name "empathy_contact_manager_new")
+  (is-constructor-of "EmpathyContactManager")
+  (return-type "EmpathyContactManager*")
 )
 
-(define-function empathy_contact_hash
-  (c-name "empathy_contact_hash")
-  (return-type "guint")
+(define-method get_list
+  (of-object "EmpathyContactManager")
+  (c-name "empathy_contact_manager_get_list")
+  (return-type "EmpathyTpContactList*")
   (parameters
-    '("gconstpointer" "key")
+    '("McAccount*" "account")
   )
 )
 
   (varargs #t)
 )
 
-
-
-;; From empathy-filter-glue.h
-
-(define-function dbus_glib_marshal_empathy_filter_BOOLEAN__STRING_BOXED_STRING_BOXED_UINT_UINT_UINT_POINTER
-  (c-name "dbus_glib_marshal_empathy_filter_BOOLEAN__STRING_BOXED_STRING_BOXED_UINT_UINT_UINT_POINTER")
+(define-function empathy_debug_set_log_file_from_env
+  (c-name "empathy_debug_set_log_file_from_env")
   (return-type "none")
-  (parameters
-    '("GClosure*" "closure")
-    '("GValue*" "return_value")
-    '("guint" "n_param_values")
-    '("const-GValue*" "param_values")
-    '("gpointer" "invocation_hint")
-    '("gpointer" "marshal_data")
-  )
 )
 
 
   )
 )
 
+(define-method get_messages_for_file
+  (of-object "EmpathyLogManager")
+  (c-name "empathy_log_manager_get_messages_for_file")
+  (return-type "GList*")
+  (parameters
+    '("const-gchar*" "filename")
+  )
+)
+
 (define-method get_messages_for_date
   (of-object "EmpathyLogManager")
   (c-name "empathy_log_manager_get_messages_for_date")
   )
 )
 
+(define-method get_messages_for_file
+  (of-object "EmpathyLogManager")
+  (c-name "empathy_log_manager_get_messages_for_file")
+  (return-type "GList*")
+  (parameters
+    '("const-gchar*" "filename")
+  )
+)
+
 (define-method get_chats
   (of-object "EmpathyLogManager")
   (c-name "empathy_log_manager_get_chats")
 
 
 
-;; From empathy-marshal.h
-
-
-
 ;; From empathy-message.h
 
 (define-function empathy_message_get_gtype
   )
 )
 
+(define-function empathy_message_type_from_str
+  (c-name "empathy_message_type_from_str")
+  (return-type "EmpathyMessageType")
+  (parameters
+    '("const-gchar*" "type_str")
+  )
+)
+
+(define-method to_str
+  (of-object "EmpathyMessageType")
+  (c-name "empathy_message_type_to_str")
+  (return-type "const-gchar*")
+)
+
 
 
 ;; From empathy-presence.h
   (return-type "McAccount*")
 )
 
-(define-method get_user
-  (of-object "EmpathyTpContactList")
-  (c-name "empathy_tp_contact_list_get_user")
-  (return-type "EmpathyContact*")
-)
-
-(define-method get_from_id
-  (of-object "EmpathyTpContactList")
-  (c-name "empathy_tp_contact_list_get_from_id")
-  (return-type "EmpathyContact*")
-  (parameters
-    '("const-gchar*" "id")
-  )
-)
-
-(define-method get_from_handle
-  (of-object "EmpathyTpContactList")
-  (c-name "empathy_tp_contact_list_get_from_handle")
-  (return-type "EmpathyContact*")
-  (parameters
-    '("guint" "handle")
-  )
-)
-
-(define-method get_from_handles
-  (of-object "EmpathyTpContactList")
-  (c-name "empathy_tp_contact_list_get_from_handles")
-  (return-type "GList*")
-  (parameters
-    '("GArray*" "handles")
-  )
-)
-
-(define-method rename_group
-  (of-object "EmpathyTpContactList")
-  (c-name "empathy_tp_contact_list_rename_group")
-  (return-type "none")
-  (parameters
-    '("const-gchar*" "old_group")
-    '("const-gchar*" "new_group")
-  )
-)
-
-(define-method get_groups
-  (of-object "EmpathyTpContactList")
-  (c-name "empathy_tp_contact_list_get_groups")
-  (return-type "GList*")
-)
-
 
 
 ;; From empathy-tp-group.h
   (is-constructor-of "EmpathyTpGroup")
   (return-type "EmpathyTpGroup*")
   (parameters
+    '("McAccount*" "account")
     '("TpChan*" "tp_chan")
-    '("TpConn*" "tp_conn")
   )
 )
 
+(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
-    '("GArray*" "handles")
+    '("GList*" "contacts")
     '("const-gchar*" "message")
   )
 )
   (c-name "empathy_tp_group_add_member")
   (return-type "none")
   (parameters
-    '("guint" "handle")
+    '("EmpathyContact*" "contact")
     '("const-gchar*" "message")
   )
 )
   (c-name "empathy_tp_group_remove_members")
   (return-type "none")
   (parameters
-    '("GArray*" "handle")
+    '("GList*" "contacts")
     '("const-gchar*" "message")
   )
 )
   (c-name "empathy_tp_group_remove_member")
   (return-type "none")
   (parameters
-    '("guint" "handle")
+    '("EmpathyContact*" "contact")
     '("const-gchar*" "message")
   )
 )
 (define-method get_members
   (of-object "EmpathyTpGroup")
   (c-name "empathy_tp_group_get_members")
-  (return-type "GArray*")
+  (return-type "GList*")
 )
 
-(define-method get_all_members
+(define-method get_local_pendings
   (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_get_all_members")
-  (return-type "none")
-  (parameters
-    '("GArray**" "members")
-    '("GArray**" "local_pending")
-    '("GArray**" "remote_pending")
-  )
+  (c-name "empathy_tp_group_get_local_pendings")
+  (return-type "GList*")
 )
 
-(define-method get_local_pending_members_with_info
+(define-method get_remote_pendings
   (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_get_local_pending_members_with_info")
+  (c-name "empathy_tp_group_get_remote_pendings")
   (return-type "GList*")
 )
 
-(define-function empathy_tp_group_info_list_free
-  (c-name "empathy_tp_group_info_list_free")
-  (return-type "none")
-  (parameters
-    '("GList*" "infos")
-  )
-)
-
 (define-method get_name
   (of-object "EmpathyTpGroup")
   (c-name "empathy_tp_group_get_name")
   (return-type "const-gchar*")
 )
 
-(define-method get_self_handle
+(define-method get_self_contact
   (of-object "EmpathyTpGroup")
-  (c-name "empathy_tp_group_get_self_handle")
-  (return-type "guint")
+  (c-name "empathy_tp_group_get_self_contact")
+  (return-type "EmpathyContact*")
 )
 
 (define-method get_object_path
   (c-name "empathy_tp_group_is_member")
   (return-type "gboolean")
   (parameters
-    '("guint" "handle")
+    '("EmpathyContact*" "contact")
+  )
+)
+
+(define-function empathy_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")
+)
+
+
+
+;; From empathy-tp-roomlist.h
+
+(define-function empathy_tp_roomlist_get_type
+  (c-name "empathy_tp_roomlist_get_type")
+  (return-type "GType")
+)
+
+(define-function empathy_tp_roomlist_new
+  (c-name "empathy_tp_roomlist_new")
+  (is-constructor-of "EmpathyTpRoomlist")
+  (return-type "EmpathyTpRoomlist*")
+  (parameters
+    '("McAccount*" "account")
   )
 )
 
+(define-method is_listing
+  (of-object "EmpathyTpRoomlist")
+  (c-name "empathy_tp_roomlist_is_listing")
+  (return-type "gboolean")
+)
+
+(define-method start
+  (of-object "EmpathyTpRoomlist")
+  (c-name "empathy_tp_roomlist_start")
+  (return-type "none")
+)
+
+(define-method stop
+  (of-object "EmpathyTpRoomlist")
+  (c-name "empathy_tp_roomlist_stop")
+  (return-type "none")
+)
+
 
 
 ;; From empathy-utils.h
   (return-type "MissionControl*")
 )
 
-(define-function empathy_get_channel_id
-  (c-name "empathy_get_channel_id")
+(define-function empathy_inspect_handle
+  (c-name "empathy_inspect_handle")
+  (return-type "gchar*")
+  (parameters
+    '("McAccount*" "account")
+    '("guint" "handle")
+    '("guint" "handle_type")
+  )
+)
+
+(define-function empathy_inspect_channel
+  (c-name "empathy_inspect_channel")
   (return-type "gchar*")
   (parameters
     '("McAccount*" "account")
   )
 )
 
+(define-function empathy_strdiff
+  (c-name "empathy_strdiff")
+  (return-type "gboolean")
+  (parameters
+    '("const-gchar*" "left")
+    '("const-gchar*" "right")
+  )
+)
+
+
index 607a9e520f8f97688fd1e484f1e0b57483a78764..dd816e23a2b1fdd6c0585b17df38c4daafb970c3 100644 (file)
@@ -21,15 +21,10 @@ headers
 #include "empathy-tp-chatroom.h"
 #include "empathy-tp-contact-list.h"
 #include "empathy-tp-group.h"
+#include "empathy-tp-roomlist.h"
 #include "empathy-utils.h"
-
-
-/* FIXME */
-#define MC_TYPE_PRESENCE 1
-#define EMPATHY_TYPE_SUBSCRIPTION 2
-#define EMPATHY_TYPE_MESSAGE_TYPE 3
-#define EMPATHY_TYPE_REG_EX_TYPE 4
-
+#include "empathy-contact-factory.h"
+#include "empathy-enum-types.h"
 
 void empathy_add_constants(PyObject *module, const gchar *strip_prefix);
 void empathy_register_classes(PyObject *d);
@@ -62,22 +57,3 @@ _wrap_empathy_contact_list_get_members(PyGObject *self, PyObject *args, PyObject
 
 }
 %%
-override empathy_contact_get_groups kwargs
-static PyObject *
-_wrap_empathy_contact_get_groups(PyGObject *self, PyObject *args, PyObject *kwargs)
-{
-
-       GList *groups = empathy_contact_get_groups(EMPATHY_CONTACT(self->obj));
-       PyObject *py_groups = PyList_New(0);
-       GList *l;
-
-       for(l = groups; l; l = l->next) {
-               const gchar *group;
-               group = l->data;
-               PyList_Append(py_groups, PyString_FromString(group));
-       }
-
-       return py_groups;
-
-}
-%%
index c41ea45c7fdec37231c8f1a5b56bd4c04eef71fe..71a4437b657d08a72f7cd10ca9e5f0ad1e9e1a76 100644 (file)
 
 
 
+;; From empathy-account-widget-salut.h
+
+(define-function empathy_account_widget_salut_new
+  (c-name "empathy_account_widget_salut_new")
+  (is-constructor-of "EmpathyAccountWidgetSalut")
+  (return-type "GtkWidget*")
+  (parameters
+    '("McAccount*" "account")
+  )
+)
+
+
+
 ;; From empathy-cell-renderer-expander.h
 
 (define-function empathy_cell_renderer_expander_get_type
   )
 )
 
-(define-method set_contact_groups_func
-  (of-object "EmpathyContactListStore")
-  (c-name "empathy_contact_list_store_set_contact_groups_func")
-  (return-type "none")
-  (parameters
-    '("EmpathyContactGroupsFunc" "func")
-    '("gpointer" "user_data")
-  )
-)
-
-(define-method update_contact_groups
-  (of-object "EmpathyContactListStore")
-  (c-name "empathy_contact_list_store_update_contact_groups")
-  (return-type "none")
-  (parameters
-    '("EmpathyContact*" "contact")
-  )
-)
-
 
 
 ;; From empathy-contact-list-view.h
   (return-type "GtkWidget*")
 )
 
-(define-method set_filter
-  (of-object "EmpathyContactListView")
-  (c-name "empathy_contact_list_view_set_filter")
-  (return-type "none")
-  (parameters
-    '("const-gchar*" "filter")
-  )
-)
-
-(define-method set_drag_received_func
-  (of-object "EmpathyContactListView")
-  (c-name "empathy_contact_list_view_set_drag_received_func")
-  (return-type "none")
-  (parameters
-    '("EmpathyContactListViewDragReceivedFunc" "func")
-    '("gpointer" "user_data")
-  )
-)
-
 
 
 ;; From empathy-contact-widget.h