merged souliane changes

This commit is contained in:
Goffi 2015-02-23 18:08:22 +01:00
commit 27c26487c3

View file

@ -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)