changeset 1337:f29beedb33b0 frontends_multi_profiles

merged souliane changes
author Goffi <goffi@goffi.org>
date Mon, 23 Feb 2015 18:08:22 +0100
parents 2ecc07a8f91b (current diff) 0f92b6a150ff (diff)
children 139263ee85c5
files frontends/src/constants.py frontends/src/primitivus/primitivus frontends/src/quick_frontend/quick_app.py frontends/src/quick_frontend/quick_contact_list.py src/plugins/plugin_xep_0085.py
diffstat 12 files changed, 149 insertions(+), 133 deletions(-) [+]
line wrap: on
line diff
--- a/frontends/src/constants.py	Mon Feb 23 18:04:25 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# generic module for SàT frontends
-# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Jérôme Poisson (goffi@goffi.org)
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 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 Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-
-from sat.core import constants
-from sat.core.i18n import _, D_
-from collections import OrderedDict  # only available from python 2.7
-
-
-def getPresence():
-    """We cannot do it directly in the Const class, if it is not encapsulated
-    in a method we get a JS runtime SyntaxError: "missing ) in parenthetical".
-    # TODO: merge this definition with those in primitivus.constants
-    """
-
-
-class Const(constants.Const):
-
-    PRESENCE = OrderedDict([("", _("Online")),
-                            ("chat", _("Free for chat")),
-                            ("away", _("Away from keyboard")),
-                            ("dnd", _("Do not disturb")),
-                            ("xa", _("Extended away"))])
-
-    # from plugin_misc_text_syntaxes
-    SYNTAX_XHTML = "XHTML"
-    SYNTAX_CURRENT = "@CURRENT@"
-    SYNTAX_TEXT = "text"
-
-    # XMLUI
-    SAT_FORM_PREFIX = "SAT_FORM_"
-    SAT_PARAM_SEPARATOR = "_XMLUI_PARAM_"  # used to have unique elements names
-    XMLUI_STATUS_VALIDATED = "validated"
-    XMLUI_STATUS_CANCELLED = constants.Const.XMLUI_DATA_CANCELLED
-
-    # MUC
-    ALL_OCCUPANTS = 1
-    MUC_USER_STATES = {
-        "active": u'✔',
-        "inactive": u'☄',
-        "gone": u'✈',
-        "composing": u'✎',
-        "paused": u"⦷"
-    }
-
-    # Roster
-    GROUP_NOT_IN_ROSTER = D_('Not in roster')
-
-    # Chats
-    CHAT_ONE2ONE = 'one2one'
-    CHAT_GROUP = 'group'
-
-    # Widgets management
-    # FIXME: should be in quick_frontend.constant, but Libervia doesn't inherit from it
-    WIDGET_NEW = 'NEW'
-    WIDGET_KEEP = 'KEEP'
-    WIDGET_RAISE = 'RAISE'
-    WIDGET_RECREATE = 'RECREATE'
-
--- a/frontends/src/primitivus/primitivus	Mon Feb 23 18:04:25 2015 +0100
+++ b/frontends/src/primitivus/primitivus	Mon Feb 23 18:08:22 2015 +0100
@@ -464,7 +464,6 @@
     def addContactList(self, profile):
         contact_list = ContactList(self, on_click=self.contactSelected, on_change=lambda w: self.redraw(), profile=profile)
         self.contact_lists_pile.contents.append((contact_list, ('weight', 1)))
-        self.contact_lists[profile] = contact_list
         return contact_list
 
     def plugging_profiles(self):
--- a/frontends/src/primitivus/profile_manager.py	Mon Feb 23 18:04:25 2015 +0100
+++ b/frontends/src/primitivus/profile_manager.py	Mon Feb 23 18:08:22 2015 +0100
@@ -153,7 +153,7 @@
         self.host.redraw()
 
     def alert(self, title, message):
-        popup = sat_widgets.alert(title, message, ok_cb=self.host.removePopUp)
+        popup = sat_widgets.Alert(title, message, ok_cb=self.host.removePopUp)
         self.host.showPopUp(popup)
 
     def onProfileChange(self, list_wid):
--- a/frontends/src/primitivus/status.py	Mon Feb 23 18:04:25 2015 +0100
+++ b/frontends/src/primitivus/status.py	Mon Feb 23 18:08:22 2015 +0100
@@ -20,7 +20,7 @@
 from sat.core.i18n import _
 import urwid
 from urwid_satext import sat_widgets
-from sat_frontends.constants import Const as commonConst
+from sat_frontends.quick_frontend.constants import Const as commonConst
 from sat_frontends.primitivus.constants import Const
 
 
--- a/frontends/src/quick_frontend/constants.py	Mon Feb 23 18:04:25 2015 +0100
+++ b/frontends/src/quick_frontend/constants.py	Mon Feb 23 18:08:22 2015 +0100
@@ -17,18 +17,58 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from sat_frontends import constants
+from sat.core import constants
+from sat.core.i18n import _, D_
+from collections import OrderedDict  # only available from python 2.7
 
 
 class Const(constants.Const):
 
-    #Contact list
+    PRESENCE = OrderedDict([("", _("Online")),
+                            ("chat", _("Free for chat")),
+                            ("away", _("Away from keyboard")),
+                            ("dnd", _("Do not disturb")),
+                            ("xa", _("Extended away"))])
+
+    # from plugin_misc_text_syntaxes
+    SYNTAX_XHTML = "XHTML"
+    SYNTAX_CURRENT = "@CURRENT@"
+    SYNTAX_TEXT = "text"
+
+    # XMLUI
+    SAT_FORM_PREFIX = "SAT_FORM_"
+    SAT_PARAM_SEPARATOR = "_XMLUI_PARAM_"  # used to have unique elements names
+    XMLUI_STATUS_VALIDATED = "validated"
+    XMLUI_STATUS_CANCELLED = constants.Const.XMLUI_DATA_CANCELLED
+
+    # MUC
+    ALL_OCCUPANTS = 1
+    MUC_USER_STATES = {
+        "active": u'✔',
+        "inactive": u'☄',
+        "gone": u'✈',
+        "composing": u'✎',
+        "paused": u"⦷"
+    }
+
+    # Roster
     CONTACT_GROUPS = 'groups'
     CONTACT_RESOURCES = 'resources'
     CONTACT_MAIN_RESOURCE = 'main_resource'
     CONTACT_SPECIAL = 'special'
-    CONTACT_SPECIAL_GROUP = 'group' # group chat special entity
-    CONTACT_SPECIAL_ALLOWED = (CONTACT_SPECIAL_GROUP,) # set of allowed values for special flag
-    CONTACT_DATA_FORBIDDEN = {CONTACT_GROUPS, CONTACT_RESOURCES, CONTACT_MAIN_RESOURCE} # set of forbidden names for contact data
+    CONTACT_SPECIAL_GROUP = 'group'  # group chat special entity
+    CONTACT_SPECIAL_ALLOWED = (CONTACT_SPECIAL_GROUP,)  # set of allowed values for special flag
+    CONTACT_DATA_FORBIDDEN = {CONTACT_GROUPS, CONTACT_RESOURCES, CONTACT_MAIN_RESOURCE}  # set of forbidden names for contact data
+
+    # Chats
+    CHAT_ONE2ONE = 'one2one'
+    CHAT_GROUP = 'group'
 
-    LISTENERS = {'avatar'}
+    # Widgets management
+    # FIXME: should be in quick_frontend.constant, but Libervia doesn't inherit from it
+    WIDGET_NEW = 'NEW'
+    WIDGET_KEEP = 'KEEP'
+    WIDGET_RAISE = 'RAISE'
+    WIDGET_RECREATE = 'RECREATE'
+
+    LISTENERS = {'avatar', 'presence'}
--- a/frontends/src/quick_frontend/quick_app.py	Mon Feb 23 18:04:25 2015 +0100
+++ b/frontends/src/quick_frontend/quick_app.py	Mon Feb 23 18:08:22 2015 +0100
@@ -17,16 +17,25 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from sat.core.i18n import _
-import sys
 from sat.core.log import getLogger
 log = getLogger(__name__)
+
+from sat.core.i18n import _
 from sat.core import exceptions
+
 from sat_frontends.tools import jid
 from sat_frontends.quick_frontend.quick_widgets import QuickWidgetsManager
 from sat_frontends.quick_frontend import quick_chat
+from sat_frontends.quick_frontend.constants import Const as C
 
-from sat_frontends.quick_frontend.constants import Const as C
+import sys
+from collections import OrderedDict
+
+try:
+    # FIXME: to be removed when an acceptable solution is here
+    unicode('')  # XXX: unicode doesn't exist in pyjamas
+except (TypeError, AttributeError):  # Error raised is not the same depending on pyjsbuild options
+    unicode = str
 
 
 class ProfileManager(object):
@@ -75,11 +84,14 @@
 
     def _plug_profile_gotCachedValues(self, cached_values):
         # TODO: watched plugin
+
+        # add the contact list and its listener
         contact_list = self.host.addContactList(self.profile)
+        self.host.contact_lists[self.profile] = contact_list
 
         for entity, data in cached_values.iteritems():
             for key, value in data.iteritems():
-                self.host.contact_lists[self.profile].setCache(jid.JID(entity), key, value)
+                contact_list.setCache(jid.JID(entity), key, value)
 
         if not self.bridge.isConnected(self.profile):
             self.host.setStatusOnline(False, profile=self.profile)
@@ -169,11 +181,18 @@
     def unplug(self, profile):
         if profile not in self._profiles:
             raise ValueError('The profile [{}] is not plugged'.format(profile))
+
+        # remove the contact list and its listener
+        host = self._profiles[profile].host
+        host.contact_lists[profile].onDelete()
+        del host.contact_lists[profile]
+
         del self._profiles[profile]
 
     def chooseOneProfile(self):
         return self._profiles.keys()[0]
 
+
 class QuickApp(object):
     """This class contain the main methods needed for the frontend"""
 
@@ -196,7 +215,7 @@
         self.selected_widget = None # widget currently selected (must be filled by frontend)
 
         # listeners
-        self._listeners = {} # key: listerner type ("avatar", "selected", etc), value: list of callbacks
+        self._listeners = {} # key: listener type ("avatar", "selected", etc), value: list of callbacks
 
         ## bridge ##
         try:
@@ -287,31 +306,38 @@
             handler(*args, **kwargs)
         self.bridge.register(functionName, signalReceived, iface)
 
-    def addListerner(self, type_, callback):
-        """Add a listerner for an event
+    def addListener(self, type_, callback, profiles_filter=None):
+        """Add a listener for an event
 
         /!\ don't forget to remove listener when not used anymore (e.g. if you delete a widget)
         @param type_: type of event, can be:
             - avatar: called when avatar data is updated
-                      args: (entity, avatar file, profile)
+                      args: (entity, avatar file)
+            - presence: called when a presence is received
+                         args: (entity, show, priority, statuses)
         @param callback: method to call on event
+        @param profiles_filter (set[unicode]): if set and not empty, the
+            listener will be callable only by one of the given profiles.
         """
         assert type_ in C.LISTENERS
-        self._listeners.setdefault(type_, []).append(callback)
+        self._listeners.setdefault(type_, OrderedDict())[callback] = profiles_filter
 
     def removeListener(self, type_, callback):
         """Remove a callback from listeners
 
-        @param type_: same as for [addListerner]
+        @param type_: same as for [addListener]
         @param callback: callback to remove
         """
         assert type_ in C.LISTENERS
-        self._listeners[type_].remove(callback)
+        self._listeners[type_].pop(callback)
 
-    def callListeners(self, type_, *args):
-        """Call all methods which listen of type_ event
+    def callListeners(self, type_, profile, *args):
+        """Call the methods which listen type_ event. If a profiles filter has
+        been register with a listener and profile argument is not None, the
+        listener will be called only if profile is in the profiles filter list.
 
-        @param type_: same as for [addListerner]
+        @param type_: same as for [addListener]
+        @param profile (unicode): %(doc_profile)s
         @param *args: arguments sent to callback
         """
         assert type_ in C.LISTENERS
@@ -320,8 +346,9 @@
         except KeyError:
             pass
         else:
-            for listener in listeners:
-                listener(*args)
+            for listener, profiles_filter in listeners.iteritems():
+                if profile is None or not profiles_filter or profile in profiles_filter:
+                    listener(*args)
 
     def check_profile(self, profile):
         """Tell if the profile is currently followed by the application"""
@@ -374,7 +401,7 @@
         """Tell the application to not follow anymore the profile"""
         if not profile in self.profiles:
             raise ValueError("The profile [{}] is not plugged".format(profile))
-        self.profiles.remove(profile)
+        self.profiles.unplug(profile)
 
     def clear_profile(self):
         self.profiles.clear()
@@ -468,7 +495,7 @@
         # if entity.bare in self.profiles[profile].data.get('watched',[]) and not entity.bare in self.profiles[profile]['onlineContact']:
         #     self.showAlert(_("Watched jid [%s] is connected !") % entity.bare)
 
-        self.contact_lists[profile].updatePresence(entity, show, priority, statuses)
+        self.callListeners('presence', profile, entity, show, priority, statuses)
 
     def roomJoinedHandler(self, room_jid_s, room_nicks, user_nick, profile):
         """Called when a MUC room is joined"""
@@ -614,10 +641,8 @@
 
     def _subscribe_cb(self, answer, data):
         entity, profile = data
-        if answer:
-            self.bridge.subscription("subscribed", entity.bare, profile_key=profile)
-        else:
-            self.bridge.subscription("unsubscribed", entity.bare, profile_key=profile)
+        type_ = "subscribed" if answer else "unsubscribed"
+        self.bridge.subscription(type_, unicode(entity.bare), profile_key=profile)
 
     def subscribeHandler(self, type, raw_jid, profile):
         """Called when a subsciption management signal is received"""
@@ -632,7 +657,7 @@
             # this is a subscriptionn request, we have to ask for user confirmation
             self.showDialog(_("The contact %s wants to subscribe to your presence.\nDo you accept ?") % entity.bare, _('Subscription confirmation'), 'yes/no', answer_cb=self._subscribe_cb, answer_data=(entity, profile))
 
-    def showDialog(self, message, title, type="info", answer_cb=None):
+    def showDialog(self, message, title, type="info", answer_cb=None, answer_data=None):
         raise NotImplementedError
 
     def showAlert(self, message):
@@ -650,8 +675,8 @@
         elif (namespace, name) == ('General', C.SHOW_EMPTY_GROUPS):
             self.contact_lists[profile].showEmptyGroups(C.bool(value))
 
-    def contactDeletedHandler(self, jid, profile):
-        target = jid.JID(jid)
+    def contactDeletedHandler(self, jid_s, profile):
+        target = jid.JID(jid_s)
         self.contact_lists[profile].remove(target)
 
     def entityDataUpdatedHandler(self, entity_s, key, value, profile):
@@ -663,7 +688,7 @@
             if entity in self.contact_lists[profile]:
                 def gotFilename(filename):
                     self.contact_lists[profile].setCache(entity, 'avatar', filename)
-                    self.callListeners('avatar', entity, filename, profile)
+                    self.callListeners('avatar', profile, entity, filename)
                 self.bridge.getAvatarFile(value, callback=gotFilename)
 
     def askConfirmationHandler(self, confirm_id, confirm_type, data, profile):
@@ -687,8 +712,12 @@
 
     def onExit(self):
         """Must be called when the frontend is terminating"""
+        to_unplug = []
         for profile in self.profiles:
             if self.bridge.isConnected(profile):
                 if C.bool(self.bridge.getParamA("autodisconnect", "Connection", profile_key=profile)):
                     #The user wants autodisconnection
                     self.bridge.disconnect(profile)
+            to_unplug.append(profile)
+        for profile in to_unplug:
+            self.unplug_profile(profile)
--- a/frontends/src/quick_frontend/quick_contact_list.py	Mon Feb 23 18:04:25 2015 +0100
+++ b/frontends/src/quick_frontend/quick_contact_list.py	Mon Feb 23 18:08:22 2015 +0100
@@ -72,6 +72,10 @@
         self.host.bridge.asyncGetParamA(C.SHOW_EMPTY_GROUPS, "General", profile_key=profile, callback=self._showEmptyGroups)
         self.host.bridge.asyncGetParamA(C.SHOW_OFFLINE_CONTACTS, "General", profile_key=profile, callback=self._showOfflineContacts)
 
+        # FIXME: workaround for a pyjamas issue: calling hash on a class method always return a different value if that method is defined directly within the class (with the "def" keyword)
+        self.presenceListener = self.updatePresence
+        self.host.addListener('presence', self.presenceListener, [profile])
+
     def __contains__(self, entity):
         """Check if entity is in contact list
 
@@ -93,16 +97,26 @@
         return self._roster
 
     @property
+    def roster_entities_connected(self):
+        """Return all the bare JIDs of the roster entities that are connected.
+
+        @return: set(jid.JID)
+        """
+        return set([entity for entity in self._roster if self.getCache(entity, C.PRESENCE_SHOW) is not None])
+
+    @property
     def roster_entities_by_group(self):
-        """Return a dictionary binding the roster groups to their entities bare JIDs.
+        """Return a dictionary binding the roster groups to their entities bare
+        JIDs. This also includes the empty group (None key).
 
         @return: dict{unicode: set(jid.JID)}
         """
         return {group: self._groups[group]['jids'] for group in self._groups}
 
     @property
-    def roster_groups_by_entity(self, contact_jid_s):
-        """Return a dictionary binding the entities bare JIDs to their roster groups.
+    def roster_groups_by_entity(self):
+        """Return a dictionary binding the entities bare JIDs to their roster
+        groups. The empty group is filtered out.
 
         @return: dict{jid.JID: set(unicode)}
         """
@@ -212,6 +226,17 @@
         assert special_type in C.CONTACT_SPECIAL_ALLOWED + (None,)
         self.setCache(entity, C.CONTACT_SPECIAL, special_type)
 
+    def getSpecials(self, special_type=None):
+        """Return all the bare JIDs of the special roster entities of the type
+        specified by special_type. If special_type is None, return all specials.
+
+        @param special_type: one of special type (e.g. C.CONTACT_SPECIAL_GROUP) or None to return all specials.
+        @return: set(jid.JID)
+        """
+        if special_type is None:
+            return self._specials
+        return set([entity for entity in self._specials if self.getCache(entity, C.CONTACT_SPECIAL) == special_type])
+
     def clearContacts(self):
         """Clear all the contact list"""
         self.unselectAll()
@@ -425,3 +450,7 @@
             return
         self.show_resources = show
         self.update()
+
+    def onDelete(self):
+        QuickWidget.onDelete(self)
+        self.host.removeListener('presence', self.presenceListener)
--- a/frontends/src/quick_frontend/quick_profile_manager.py	Mon Feb 23 18:04:25 2015 +0100
+++ b/frontends/src/quick_frontend/quick_profile_manager.py	Mon Feb 23 18:08:22 2015 +0100
@@ -113,7 +113,7 @@
                 self._autoconnect = False # manual mode
                 msg = _("Trying to plug an unknown profile key ({})".format(profile_key))
                 log.warning(msg)
-                self.alert(_("Profile plugging in error"), msg, ok_cb=self.host.removePopUp)
+                self.alert(_("Profile plugging in error"), msg)
                 break
             self.host.launchAction(C.AUTHENTICATE_PROFILE_ID, callback=authenticate_cb, profile=profile)
 
--- a/frontends/src/quick_frontend/quick_widgets.py	Mon Feb 23 18:04:25 2015 +0100
+++ b/frontends/src/quick_frontend/quick_widgets.py	Mon Feb 23 18:08:22 2015 +0100
@@ -105,15 +105,13 @@
             if there is neither 'profile' nor 'profiles', None will be used for 'profiles'
             if 'on_new_widget' is present it can have the following values:
                 C.WIDGET_NEW [default]: self.host.newWidget will be called on widget creation
-                [callable]: this method will be called instead of self.host.newWidget,
-                    and can return another widget to modify the result of the present method
+                [callable]: this method will be called instead of self.host.newWidget
                 None: do nothing
             if 'on_existing_widget' is present it can have the following values:
                 C.WIDGET_KEEP  [default]: return the existing widget
                 C.WIDGET_RAISE: raise WidgetAlreadyExistsError
                 C.WIDGET_RECREATE: create a new widget *WITH A NEW HASH*
-                [callable]: this method will be called with existing widget as argument,
-                    and can return another widget to modify the result of the present method
+                [callable]: this method will be called with existing widget as argument
             if 'force_hash' is present, the hash given in value will be used instead of the one returned by class_.getWidgetHash
             other keys will be used to instanciate class_ if the case happen (e.g. if type_ is present and class_ is a QuickChat subclass,
                 it will be used to create a new QuickChat instance).
@@ -171,9 +169,7 @@
             if on_new_widget == C.WIDGET_NEW:
                 self.host.newWidget(widget)
             elif callable(on_new_widget):
-                result = on_new_widget(widget)
-                if isinstance(result, QuickWidget):
-                    widget = result
+                on_new_widget(widget)
             else:
                 assert on_new_widget is None
         else:
@@ -207,9 +203,7 @@
                         log.debug(u"Widget already exists, a new one has been recreated with hash {}".format(new_kwargs['force_hash']))
                         break
             elif callable(on_existing_widget):
-                result = on_existing_widget(widget)
-                if isinstance(result, QuickWidget):
-                    widget = result
+                on_existing_widget(widget)
             else:
                 raise exceptions.InternalError("Unexpected on_existing_widget value ({})".format(on_existing_widget))
 
--- a/frontends/src/tools/xmlui.py	Mon Feb 23 18:04:25 2015 +0100
+++ b/frontends/src/tools/xmlui.py	Mon Feb 23 18:08:22 2015 +0100
@@ -20,7 +20,7 @@
 from sat.core.i18n import _
 from sat.core.log import getLogger
 log = getLogger(__name__)
-from sat_frontends.constants import Const as C
+from sat_frontends.quick_frontend.constants import Const as C
 from sat.core.exceptions import DataError
 
 
--- a/src/core/sat_main.py	Mon Feb 23 18:04:25 2015 +0100
+++ b/src/core/sat_main.py	Mon Feb 23 18:08:22 2015 +0100
@@ -640,7 +640,7 @@
         assert profile
         d1 = self.profiles[profile].roster.removeItem(to_jid)
         d2 = self.profiles[profile].presence.unsubscribe(to_jid)
-        d_list = defer.DefferedList([d1, d2])
+        d_list = defer.DeferredList([d1, d2])
         def check_result(list_result):
             for success, value in list_result:
                 if not success:
--- a/src/plugins/plugin_xep_0085.py	Mon Feb 23 18:04:25 2015 +0100
+++ b/src/plugins/plugin_xep_0085.py	Mon Feb 23 18:08:22 2015 +0100
@@ -126,16 +126,16 @@
             self.map[profile][to_jid]._onEvent('gone')
         del self.map[profile]
 
-    def updateEntityData(self, entity_jid, value, profile):
+    def updateCache(self, entity_jid, value, profile):
         """Update the entity data of the given profile for one or all contacts.
+        Reset the chat state(s) display if the notification has been disabled.
 
-        Reset the chat state(s) display if the notification has been disabled.
         @param entity_jid: contact's JID, or C.ENTITY_ALL to update all contacts.
         @param value: True, False or DELETE_VALUE to delete the entity data
         @param profile: current profile
         """
         if value == DELETE_VALUE:
-            self.host.memory.delEntityData(entity_jid, ENTITY_KEY, profile)
+            self.host.memory.delEntityDatum(entity_jid, ENTITY_KEY, profile)
         else:
             self.host.memory.updateEntityData(entity_jid, ENTITY_KEY, value, profile_key=profile)
         if not value or value == DELETE_VALUE:
@@ -151,7 +151,7 @@
         @param type_: parameter type
         """
         if (category, name) == (PARAM_KEY, PARAM_NAME):
-            self.updateEntityData(C.ENTITY_ALL, True if bool("true") else DELETE_VALUE, profile=profile)
+            self.updateCache(C.ENTITY_ALL, True if bool("true") else DELETE_VALUE, profile=profile)
             return False
         return True
 
@@ -173,11 +173,11 @@
                 try:
                     domish.generateElementsNamed(message.elements(), name="active").next()
                     # contact enabled Chat State Notifications
-                    self.updateEntityData(from_jid, True, profile=profile)
+                    self.updateCache(from_jid, True, profile=profile)
                 except StopIteration:
                     if message.getAttribute('type') == 'chat':
                         # contact didn't enable Chat State Notifications
-                        self.updateEntityData(from_jid, False, profile=profile)
+                        self.updateCache(from_jid, False, profile=profile)
                         return True
             except StopIteration:
                 pass
@@ -260,7 +260,7 @@
         except (exceptions.UnknownEntityError, KeyError):
             if forceEntityData:
                 # enable it for the first time
-                self.updateEntityData(to_jid, True, profile=profile)
+                self.updateCache(to_jid, True, profile=profile)
                 return True
         # wait for the first message before sending states
         return False