merged souliane changes
This commit is contained in:
commit
27c26487c3
12 changed files with 149 additions and 133 deletions
|
|
@ -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'
|
||||
|
||||
|
|
@ -464,7 +464,6 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
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):
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ class ProfileManager(QuickProfileManager, urwid.WidgetWrap):
|
|||
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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
LISTENERS = {'avatar'}
|
||||
# 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'
|
||||
|
||||
LISTENERS = {'avatar', 'presence'}
|
||||
|
|
|
|||
|
|
@ -17,17 +17,26 @@
|
|||
# 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
|
||||
|
||||
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):
|
||||
"""Class managing all data relative to one profile, and plugging in mechanism"""
|
||||
|
|
@ -75,11 +84,14 @@ class ProfileManager(object):
|
|||
|
||||
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 @@ class ProfilesManager(object):
|
|||
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 @@ class QuickApp(object):
|
|||
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 @@ class QuickApp(object):
|
|||
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 @@ class QuickApp(object):
|
|||
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 @@ class QuickApp(object):
|
|||
"""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 @@ class QuickApp(object):
|
|||
# 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 @@ class QuickApp(object):
|
|||
|
||||
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 @@ class QuickApp(object):
|
|||
# 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 @@ class QuickApp(object):
|
|||
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 @@ class QuickApp(object):
|
|||
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 @@ class QuickApp(object):
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -72,6 +72,10 @@ class QuickContactList(QuickWidget):
|
|||
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
|
||||
|
||||
|
|
@ -92,17 +96,27 @@ class QuickContactList(QuickWidget):
|
|||
"""
|
||||
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 @@ class QuickContactList(QuickWidget):
|
|||
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 @@ class QuickContactList(QuickWidget):
|
|||
return
|
||||
self.show_resources = show
|
||||
self.update()
|
||||
|
||||
def onDelete(self):
|
||||
QuickWidget.onDelete(self)
|
||||
self.host.removeListener('presence', self.presenceListener)
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ class QuickProfileManager(object):
|
|||
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)
|
||||
|
||||
|
|
|
|||
|
|
@ -105,15 +105,13 @@ class QuickWidgetsManager(object):
|
|||
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 @@ class QuickWidgetsManager(object):
|
|||
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 @@ class QuickWidgetsManager(object):
|
|||
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))
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -640,7 +640,7 @@ class SAT(service.Service):
|
|||
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:
|
||||
|
|
|
|||
|
|
@ -126,16 +126,16 @@ class XEP_0085(object):
|
|||
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.
|
||||
|
||||
@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 @@ class XEP_0085(object):
|
|||
@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 @@ class XEP_0085(object):
|
|||
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 @@ class XEP_0085(object):
|
|||
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
|
||||
|
|
|
|||
Loading…
Reference in a new issue