core, frontends: refactoring to base Libervia on QuickFrontend (big mixed commit):

/!\ not finished, everything is still instable !
    - bridge: DBus bridge has been modified to allow blocking call to be called in the same way as asynchronous calls
    - bridge: calls with a callback and no errback are now possible, default errback log the error
    - constants: removed hack to manage presence without OrderedDict, as an OrderedDict like class has been implemented in Libervia
    - core: getLastResource has been removed and replaced by getMainResource (there is a global better management of resources)
    - various style improvments: use of constants when possible, fixed variable overlaps, import of module instead of direct class import
    - frontends: printInfo and printMessage methods in (Quick)Chat are more generic (use of extra instead of timestamp)
    - frontends: bridge creation and option parsing (command line arguments) are now specified by the frontend in QuickApp __init__
    - frontends: ProfileManager manage a more complete plug sequence (some stuff formerly manage in contact_list have moved to ProfileManager)
    - quick_frontend (quick_widgets): QuickWidgetsManager is now iterable (all widgets are then returned), or can return an iterator on a specific class (return all widgets of this class) with getWidgets
    - frontends: tools.jid can now be used in Pyjamas, with some care
    - frontends (XMLUI): profile is now managed
    - core (memory): big improvment on entities cache management (and specially resource management)
    - core (params/exceptions): added PermissionError
    - various fixes and improvments, check diff for more details
This commit is contained in:
Goffi 2015-01-24 01:00:29 +01:00
commit 8ce5c1862b

View file

@ -39,6 +39,7 @@ MESSAGE_TYPES = ["chat", "groupchat"]
PARAM_KEY = "Notifications"
PARAM_NAME = "Enable chat state notifications"
ENTITY_KEY = PARAM_KEY + "_" + PARAM_NAME
DELETE_VALUE = "DELETE"
PLUGIN_INFO = {
"name": "Chat State Notifications Protocol Plugin",
@ -126,28 +127,31 @@ class XEP_0085(object):
del self.map[profile]
def updateEntityData(self, entity_jid, value, profile):
"""
Update the entity data of the given profile for one or all contacts.
"""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 '@ALL@' to update all contacts.
@param value: True, False or C.PROF_KEY_NONE to delete the entity data
@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
"""
self.host.memory.updateEntityData(entity_jid, ENTITY_KEY, value, profile)
if not value or value == C.PROF_KEY_NONE:
# disable chat state for this or these contact(s)
self.host.bridge.chatStateReceived(unicode(entity_jid), "", profile)
if value == DELETE_VALUE:
self.host.memory.delEntityData(entity_jid, ENTITY_KEY, profile)
else:
self.host.memory.updateEntityData(entity_jid, ENTITY_KEY, value, profile)
if not value or value == DELETE_VALUE:
# reinit chat state UI for this or these contact(s)
self.host.bridge.chatStateReceived(entity_jid.full(), "", profile)
def paramUpdateTrigger(self, name, value, category, type_, profile):
"""
Reset all the existing chat state entity data associated with this profile after a parameter modification.
"""Reset all the existing chat state entity data associated with this profile after a parameter modification.
@param name: parameter name
@param value: "true" to activate the notifications, or any other value to delete it
@param category: parameter category
@param type_: parameter type
"""
if (category, name) == (PARAM_KEY, PARAM_NAME):
self.updateEntityData("@ALL@", True if value == "true" else C.PROF_KEY_NONE, profile)
self.updateEntityData(C.ENTITY_ALL, True if bool("true") else DELETE_VALUE, profile)
return False
return True
@ -160,7 +164,7 @@ class XEP_0085(object):
return True
from_jid = JID(message.getAttribute("from"))
if self.__isMUC(from_jid, profile):
if self._isMUC(from_jid, profile):
from_jid = from_jid.userhostJID()
else: # update entity data for one2one chat
# assert from_jid.resource # FIXME: assert doesn't work on normal message from server (e.g. server announce), because there is no resource
@ -200,27 +204,27 @@ class XEP_0085(object):
def treatment(mess_data):
message = mess_data['xml']
to_jid = JID(message.getAttribute("to"))
if not self.__checkActivation(to_jid, forceEntityData=True, profile=profile):
if not self._checkActivation(to_jid, forceEntityData=True, profile=profile):
return mess_data
try:
# message with a body always mean active state
domish.generateElementsNamed(message.elements(), name="body").next()
message.addElement('active', NS_CHAT_STATES)
# launch the chat state machine (init the timer)
if self.__isMUC(to_jid, profile):
if self._isMUC(to_jid, profile):
to_jid = to_jid.userhostJID()
self.__chatStateActive(to_jid, mess_data["type"], profile)
except StopIteration:
if "chat_state" in mess_data["extra"]:
state = mess_data["extra"].pop("chat_state")
assert(state in CHAT_STATES)
assert state in CHAT_STATES
message.addElement(state, NS_CHAT_STATES)
return mess_data
post_xml_treatments.addCallback(treatment)
return True
def __isMUC(self, to_jid, profile):
def _isMUC(self, to_jid, profile):
"""Tell if that JID is a MUC or not
@param to_jid (JID): full or bare JID to check
@ -229,13 +233,13 @@ class XEP_0085(object):
"""
try:
type_ = self.host.memory.getEntityDatum(to_jid.userhostJID(), 'type', profile)
if type_ == 'chatroom':
if type_ == 'chatroom': # FIXME: should not use disco instead ?
return True
except (exceptions.UnknownEntityError, KeyError):
pass
return False
def __checkActivation(self, to_jid, forceEntityData, profile):
def _checkActivation(self, to_jid, forceEntityData, profile):
"""
@param to_jid: the contact's full JID (or bare if you know it's a MUC)
@param forceEntityData: if set to True, a non-existing
@ -247,9 +251,10 @@ class XEP_0085(object):
if not self.host.memory.getParamA(PARAM_NAME, PARAM_KEY, profile_key=profile):
return False
# check if notifications should be sent to this contact
if self.__isMUC(to_jid, profile):
if self._isMUC(to_jid, profile):
return True
assert to_jid.resource or not self.host.memory.isContactConnected(to_jid, profile)
# FIXME: this assertion crash when we want to send a message to an online bare jid
# assert to_jid.resource or not self.host.memory.isEntityAvailable(to_jid, profile) # must either have a resource, or talk to an offline contact
try:
return self.host.memory.getEntityDatum(to_jid, ENTITY_KEY, profile)
except (exceptions.UnknownEntityError, KeyError):
@ -305,11 +310,11 @@ class XEP_0085(object):
if profile is None:
raise exceptions.ProfileUnknownError
to_jid = JID(to_jid_s)
if self.__isMUC(to_jid, profile):
if self._isMUC(to_jid, profile):
to_jid = to_jid.userhostJID()
elif not to_jid.resource:
to_jid.resource = self.host.memory.getLastResource(to_jid, profile)
if not self.__checkActivation(to_jid, forceEntityData=False, profile=profile):
to_jid.resource = self.host.memory.getMainResource(to_jid, profile)
if not self._checkActivation(to_jid, forceEntityData=False, profile=profile):
return
try:
self.map[profile][to_jid]._onEvent("composing")
@ -347,9 +352,9 @@ class ChatStateMachine:
notification to the contact (the "active" state is
automatically sent with each message) and set the timer.
"""
assert(state in TRANSITIONS)
assert state in TRANSITIONS
transition = TRANSITIONS[state]
assert("next_state" in transition and "delay" in transition)
assert "next_state" in transition and "delay" in transition
if state != self.state and state != "active":
if state != 'gone' or self.mess_type != 'groupchat':