quick_frontend (widget, chat): implementation of new sync mechanism, first draft:
QuickWidget implement base of sync mechanism with a sync property which can be overriden, and resync method which is called when resynchronisation is needed. When resync is required, chat widget get missing occupant and history elements A new callable argument can be used with historyPrint, when set it is called when history has been fully printed.
This commit is contained in:
parent
060c985aba
commit
4c8f108192
2 changed files with 80 additions and 2 deletions
|
|
@ -281,6 +281,9 @@ class QuickChat(quick_widgets.QuickWidget):
|
|||
self.type = type_
|
||||
self.encrypted = False # True if this session is currently encrypted
|
||||
self._locked = False
|
||||
# True when resync is in progress, avoid resynchronising twice when resync is called
|
||||
# and history is still being updated. For internal use only
|
||||
self._resync_lock = False
|
||||
self.setLocked()
|
||||
if type_ == C.CHAT_GROUP:
|
||||
if target.resource:
|
||||
|
|
@ -363,6 +366,43 @@ class QuickChat(quick_widgets.QuickWidget):
|
|||
def contact_list(self):
|
||||
return self.host.contact_lists[self.profile]
|
||||
|
||||
## synchornisation handling ##
|
||||
|
||||
@quick_widgets.QuickWidget.sync.setter
|
||||
def sync(self, state):
|
||||
quick_widgets.QuickWidget.sync.fset(self, state)
|
||||
if not state:
|
||||
self.setLocked()
|
||||
|
||||
def _resyncComplete(self):
|
||||
self.sync = True
|
||||
self._resync_lock = False
|
||||
|
||||
def resync(self):
|
||||
if self._resync_lock:
|
||||
return
|
||||
self._resync_lock = True
|
||||
log.debug(u"resynchronising {self}".format(self=self))
|
||||
for mess in reversed(self.messages.values()):
|
||||
if mess.type == C.MESS_TYPE_INFO:
|
||||
continue
|
||||
last_message = mess
|
||||
break
|
||||
else:
|
||||
# we have no message yet, we can get normal history
|
||||
self.historyPrint(callback=self._resyncComplete, profile=self.profile)
|
||||
return
|
||||
if self.type == C.CHAT_GROUP:
|
||||
self.occupants.clear()
|
||||
self.host.bridge.mucOccupantsGet(
|
||||
unicode(self.target), self.profile, callback=self.updateOccupants,
|
||||
errback=log.error)
|
||||
self.historyPrint(
|
||||
size=C.HISTORY_LIMIT_NONE,
|
||||
filters={'timestamp_start': last_message.timestamp},
|
||||
callback=self._resyncComplete,
|
||||
profile=self.profile)
|
||||
|
||||
## Widget management ##
|
||||
|
||||
def __unicode__(self):
|
||||
|
|
@ -428,9 +468,11 @@ class QuickChat(quick_widgets.QuickWidget):
|
|||
## occupants ##
|
||||
|
||||
def setOccupants(self, occupants):
|
||||
"""set the whole list of occupants"""
|
||||
"""Set the whole list of occupants"""
|
||||
assert len(self.occupants) == 0
|
||||
for nick, data in occupants.iteritems():
|
||||
log.debug(u"adding occupant {nick} to {room}".format(
|
||||
nick=nick, room=self.target))
|
||||
self.occupants[nick] = Occupant(self, data, self.profile)
|
||||
|
||||
def updateOccupants(self, occupants):
|
||||
|
|
@ -523,12 +565,14 @@ class QuickChat(quick_widgets.QuickWidget):
|
|||
"""
|
||||
self.setUnlocked()
|
||||
|
||||
def historyPrint(self, size=C.HISTORY_LIMIT_DEFAULT, filters=None, profile="@NONE@"):
|
||||
def historyPrint(self, size=C.HISTORY_LIMIT_DEFAULT, filters=None, callback=None,
|
||||
profile="@NONE@"):
|
||||
"""Print the current history
|
||||
|
||||
Note: self.setUnlocked will be called once history is printed
|
||||
@param size (int): number of messages
|
||||
@param search (str): pattern to filter the history results
|
||||
@param callback(callable, None): method to call when history has been printed
|
||||
@param profile (str): %(doc_profile)s
|
||||
"""
|
||||
if filters is None:
|
||||
|
|
@ -589,10 +633,14 @@ class QuickChat(quick_widgets.QuickWidget):
|
|||
profile,
|
||||
)
|
||||
self._onHistoryPrinted()
|
||||
if callback is not None:
|
||||
callback()
|
||||
|
||||
def _historyGetEb(err):
|
||||
log.error(_(u"Can't get history: {}").format(err))
|
||||
self._onHistoryPrinted()
|
||||
if callback is not None:
|
||||
callback()
|
||||
|
||||
self.host.bridge.historyGet(
|
||||
unicode(self.host.profiles[profile].whoami.bare),
|
||||
|
|
|
|||
|
|
@ -334,6 +334,7 @@ class QuickWidget(object):
|
|||
self.targets = set()
|
||||
self.addTarget(target)
|
||||
self.profiles = set()
|
||||
self._sync = True
|
||||
if isinstance(profiles, basestring):
|
||||
self.addProfile(profiles)
|
||||
elif profiles is None:
|
||||
|
|
@ -354,6 +355,31 @@ class QuickWidget(object):
|
|||
)
|
||||
return list(self.profiles)[0]
|
||||
|
||||
# synchronisation state
|
||||
|
||||
@property
|
||||
def sync(self):
|
||||
return self._sync
|
||||
|
||||
@sync.setter
|
||||
def sync(self, state):
|
||||
"""state of synchronisation with backend
|
||||
|
||||
@param state(bool): True when backend is synchronised
|
||||
False is set by core
|
||||
True must be set by the widget when resynchronisation is finished
|
||||
"""
|
||||
self._sync = state
|
||||
|
||||
def resync(self):
|
||||
"""Method called when backend can be resynchronized
|
||||
|
||||
The widget has to set self.sync itself when the synchronisation if finished
|
||||
"""
|
||||
pass
|
||||
|
||||
# target/profile
|
||||
|
||||
def addTarget(self, target):
|
||||
"""Add a target if it doesn't already exists
|
||||
|
||||
|
|
@ -370,6 +396,8 @@ class QuickWidget(object):
|
|||
raise ValueError("multiple profiles are not allowed")
|
||||
self.profiles.add(profile)
|
||||
|
||||
# widget identitication
|
||||
|
||||
@staticmethod
|
||||
def getWidgetHash(target, profiles):
|
||||
"""Return the hash associated with this target for this widget class
|
||||
|
|
@ -386,6 +414,8 @@ class QuickWidget(object):
|
|||
"""
|
||||
return unicode(target) # by defaut, there is one hash for one target
|
||||
|
||||
# widget life events
|
||||
|
||||
def onDelete(self, *args, **kwargs):
|
||||
"""Called when a widget is being deleted
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue