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:
parent
f45e55388f
commit
8ce5c1862b
6 changed files with 1125 additions and 452 deletions
|
|
@ -22,10 +22,6 @@ from sat_frontends import constants
|
|||
|
||||
class Const(constants.Const):
|
||||
|
||||
#Chats
|
||||
CHAT_ONE2ONE = 'one2one'
|
||||
CHAT_GROUP = 'group'
|
||||
|
||||
#Contact list
|
||||
CONTACT_GROUPS = 'groups'
|
||||
CONTACT_RESOURCES = 'resources'
|
||||
|
|
|
|||
|
|
@ -22,11 +22,9 @@ import sys
|
|||
from sat.core.log import getLogger
|
||||
log = getLogger(__name__)
|
||||
from sat.core import exceptions
|
||||
from sat_frontends.bridge.DBus import DBusBridgeFrontend
|
||||
from sat_frontends.tools import jid
|
||||
from sat_frontends.quick_frontend.quick_widgets import QuickWidgetsManager
|
||||
from sat_frontends.quick_frontend import quick_chat
|
||||
from optparse import OptionParser
|
||||
|
||||
from sat_frontends.quick_frontend.constants import Const as C
|
||||
|
||||
|
|
@ -78,20 +76,54 @@ class ProfileManager(object):
|
|||
contact_list.fill()
|
||||
|
||||
#The waiting subscription requests
|
||||
waitingSub = self.bridge.getWaitingSub(self.profile)
|
||||
for sub in waitingSub:
|
||||
self.host.subscribeHandler(waitingSub[sub], sub, self.profile)
|
||||
self.bridge.getWaitingSub(self.profile, callback=self._plug_profile_gotWaitingSub)
|
||||
|
||||
#Now we open the MUC window where we already are:
|
||||
for room_args in self.bridge.getRoomsJoined(self.profile):
|
||||
self.host.roomJoinedHandler(*room_args, profile=self.profile)
|
||||
def _plug_profile_gotWaitingSub(self, waiting_sub):
|
||||
for sub in waiting_sub:
|
||||
self.host.subscribeHandler(waiting_sub[sub], sub, self.profile)
|
||||
|
||||
for subject_args in self.bridge.getRoomsSubjects(self.profile):
|
||||
self.host.roomNewSubjectHandler(*subject_args, profile=self.profile)
|
||||
self.bridge.getRoomsJoined(self.profile, callback=self._plug_profile_gotRoomsJoined)
|
||||
|
||||
#Finaly, we get the waiting confirmation requests
|
||||
for confirm_id, confirm_type, data in self.bridge.getWaitingConf(self.profile):
|
||||
self.host.askConfirmationHandler(confirm_id, confirm_type, data, self.profile)
|
||||
def _plug_profile_gotRoomsJoined(self, rooms_args):
|
||||
#Now we open the MUC window where we already are:
|
||||
for room_args in rooms_args:
|
||||
self.host.roomJoinedHandler(*room_args, profile=self.profile)
|
||||
|
||||
self.bridge.getRoomsSubjects(self.profile, callback=self._plug_profile_gotRoomsSubjects)
|
||||
|
||||
def _plug_profile_gotRoomsSubjects(self, subjects_args):
|
||||
for subject_args in subjects_args:
|
||||
self.host.roomNewSubjectHandler(*subject_args, profile=self.profile)
|
||||
|
||||
#Presence must be requested after rooms are filled
|
||||
self.host.bridge.getPresenceStatuses(self.profile, callback=self._plug_profile_gotPresences)
|
||||
|
||||
|
||||
def _plug_profile_gotPresences(self, presences):
|
||||
def gotEntityData(data, contact):
|
||||
for key in ('avatar', 'nick'):
|
||||
if key in data:
|
||||
self.host.entityDataUpdatedHandler(contact, key, data[key], self.profile)
|
||||
|
||||
for contact in presences:
|
||||
for res in presences[contact]:
|
||||
jabber_id = ('%s/%s' % (jid.JID(contact).bare, res)) if res else contact
|
||||
show = presences[contact][res][0]
|
||||
priority = presences[contact][res][1]
|
||||
statuses = presences[contact][res][2]
|
||||
self.host.presenceUpdateHandler(jabber_id, show, priority, statuses, self.profile)
|
||||
self.host.bridge.getEntityData(contact, ['avatar', 'nick'], self.profile, callback=lambda data, contact=contact: gotEntityData(data, contact), errback=lambda failure, contact=contact: log.debug("No cache data for {}".format(contact)))
|
||||
|
||||
#Finaly, we get the waiting confirmation requests
|
||||
self.bridge.getWaitingConf(self.profile, callback=self._plug_profile_gotWaitingConf)
|
||||
|
||||
def _plug_profile_gotWaitingConf(self, waiting_confs):
|
||||
for confirm_id, confirm_type, data in waiting_confs:
|
||||
self.host.askConfirmationHandler(confirm_id, confirm_type, data, self.profile)
|
||||
|
||||
# At this point, profile should be fully plugged
|
||||
# and we launch frontend specific method
|
||||
self.host.profilePlugged(self.profile)
|
||||
|
||||
def _getParamError(self, ignore):
|
||||
log.error(_("Can't get profile parameter"))
|
||||
|
|
@ -132,20 +164,27 @@ class ProfilesManager(object):
|
|||
class QuickApp(object):
|
||||
"""This class contain the main methods needed for the frontend"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, create_bridge, check_options=None):
|
||||
"""Create a frontend application
|
||||
|
||||
@param create_bridge: method to use to create the Bridge
|
||||
@param check_options: method to call to check options (usually command line arguments)
|
||||
"""
|
||||
ProfileManager.host = self
|
||||
self.profiles = ProfilesManager()
|
||||
self.contact_lists = {}
|
||||
self.widgets = QuickWidgetsManager(self)
|
||||
self.check_options()
|
||||
if check_options is not None:
|
||||
self.options = check_options()
|
||||
else:
|
||||
self.options = None
|
||||
|
||||
# widgets
|
||||
self.visible_widgets = set() # widgets currently visible (must be filled by frontend)
|
||||
self.selected_widget = None # widget currently selected (must be filled by frontend)
|
||||
|
||||
## bridge ##
|
||||
try:
|
||||
self.bridge = DBusBridgeFrontend()
|
||||
self.bridge = create_bridge()
|
||||
except exceptions.BridgeExceptionNoService:
|
||||
print(_(u"Can't connect to SàT backend, are you sure it's launched ?"))
|
||||
sys.exit(1)
|
||||
|
|
@ -202,6 +241,11 @@ class QuickApp(object):
|
|||
except (TypeError, AttributeError):
|
||||
return self.profiles.chooseOneProfile()
|
||||
|
||||
@property
|
||||
def visible_widgets(self):
|
||||
"""widgets currently visible (must be implemented by frontend)"""
|
||||
raise NotImplementedError
|
||||
|
||||
def registerSignal(self, functionName, handler=None, iface="core", with_profile=True):
|
||||
"""Register a handler for a signal
|
||||
|
||||
|
|
@ -211,7 +255,7 @@ class QuickApp(object):
|
|||
@param with_profile (boolean): True if the signal concerns a specific profile, in that case the profile name has to be passed by the caller
|
||||
"""
|
||||
if handler is None:
|
||||
handler = getattr(self, "%s%s" % (functionName, 'Handler'))
|
||||
handler = getattr(self, "{}{}".format(functionName, 'Handler'))
|
||||
if not with_profile:
|
||||
self.bridge.register(functionName, handler, iface)
|
||||
return
|
||||
|
|
@ -236,24 +280,15 @@ class QuickApp(object):
|
|||
|
||||
@param profile_manager: instance of a subclass of Quick_frontend.QuickProfileManager
|
||||
"""
|
||||
if self.options.profile:
|
||||
if self.options and self.options.profile:
|
||||
profile_manager.autoconnect([self.options.profile])
|
||||
|
||||
def check_options(self):
|
||||
"""Check command line options"""
|
||||
usage = _("""
|
||||
%prog [options]
|
||||
def profilePlugged(self, profile):
|
||||
"""Method called when the profile is fully plugged, to launch frontend specific workflow
|
||||
|
||||
%prog --help for options list
|
||||
""")
|
||||
parser = OptionParser(usage=usage) # TODO: use argparse
|
||||
|
||||
parser.add_option("-p", "--profile", help=_("Select the profile to use"))
|
||||
|
||||
(self.options, args) = parser.parse_args()
|
||||
if self.options.profile:
|
||||
self.options.profile = self.options.profile.decode('utf-8')
|
||||
return args
|
||||
@param profile(unicode): %(doc_profile)s
|
||||
"""
|
||||
pass
|
||||
|
||||
def asyncConnect(self, profile, callback=None, errback=None):
|
||||
if not callback:
|
||||
|
|
@ -281,7 +316,7 @@ class QuickApp(object):
|
|||
|
||||
will be called when profiles are choosen and are to be plugged soon
|
||||
"""
|
||||
raise NotImplementedError
|
||||
pass
|
||||
|
||||
def unplug_profile(self, profile):
|
||||
"""Tell the application to not follow anymore the profile"""
|
||||
|
|
@ -292,6 +327,14 @@ class QuickApp(object):
|
|||
def clear_profile(self):
|
||||
self.profiles.clear()
|
||||
|
||||
def addContactList(self, profile):
|
||||
"""Method to subclass to add a contact list widget
|
||||
|
||||
will be called on each profile session build
|
||||
@return: a ContactList widget
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def newWidget(self, widget):
|
||||
raise NotImplementedError
|
||||
|
||||
|
|
@ -331,7 +374,7 @@ class QuickApp(object):
|
|||
|
||||
def sendMessage(self, to_jid, message, subject='', mess_type="auto", extra={}, callback=None, errback=None, profile_key=C.PROF_KEY_NONE):
|
||||
if callback is None:
|
||||
callback = lambda: None
|
||||
callback = lambda dummy=None: None # FIXME: optional argument is here because pyjamas doesn't support callback without arg with json proxy
|
||||
if errback is None:
|
||||
errback = lambda failure: self.showDialog(failure.fullname, failure.message, "error")
|
||||
self.bridge.sendMessage(to_jid, message, subject, mess_type, extra, profile_key, callback=callback, errback=errback)
|
||||
|
|
@ -500,10 +543,9 @@ class QuickApp(object):
|
|||
@profile: current profile
|
||||
"""
|
||||
from_jid = jid.JID(from_jid_s) if from_jid_s != C.ENTITY_ALL else C.ENTITY_ALL
|
||||
for widget in self.visible_widgets:
|
||||
if isinstance(widget, quick_chat.QuickChat):
|
||||
if from_jid == C.ENTITY_ALL or from_jid.bare == widget.target.bare:
|
||||
widget.updateChatState(from_jid, state)
|
||||
for widget in self.widgets.getWidgets(quick_chat.QuickChat):
|
||||
if from_jid == C.ENTITY_ALL or from_jid.bare == widget.target.bare:
|
||||
widget.updateChatState(from_jid, state)
|
||||
|
||||
def _subscribe_cb(self, answer, data):
|
||||
entity, profile = data
|
||||
|
|
@ -554,8 +596,9 @@ class QuickApp(object):
|
|||
self.contact_lists[profile].setCache(entity, 'nick', value)
|
||||
elif key == "avatar":
|
||||
if entity in self.contact_lists[profile]:
|
||||
filename = self.bridge.getAvatarFile(value)
|
||||
self.contact_lists[profile].setCache(entity, 'avatar', filename)
|
||||
def gotFilename(filename):
|
||||
self.contact_lists[profile].setCache(entity, 'avatar', filename)
|
||||
self.bridge.getAvatarFile(value, callback=gotFilename)
|
||||
|
||||
def askConfirmationHandler(self, confirm_id, confirm_type, data, profile):
|
||||
raise NotImplementedError
|
||||
|
|
|
|||
|
|
@ -20,11 +20,18 @@
|
|||
from sat.core.i18n import _
|
||||
from sat.core.log import getLogger
|
||||
log = getLogger(__name__)
|
||||
from sat_frontends.tools.jid import JID
|
||||
from sat_frontends.tools import jid
|
||||
from sat_frontends.quick_frontend import quick_widgets
|
||||
from sat_frontends.quick_frontend.constants import Const as C
|
||||
|
||||
|
||||
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 = lambda x: str(x)
|
||||
|
||||
|
||||
class QuickChat(quick_widgets.QuickWidget):
|
||||
|
||||
def __init__(self, host, target, type_=C.CHAT_ONE2ONE, profiles=None):
|
||||
|
|
@ -153,11 +160,11 @@ class QuickChat(quick_widgets.QuickWidget):
|
|||
|
||||
def onHistory(history):
|
||||
for line in history:
|
||||
timestamp, from_jid, to_jid, message, _type, extra = line
|
||||
if ((self.type == C.CHAT_GROUP and _type != C.MESS_TYPE_GROUPCHAT) or
|
||||
(self.type == C.CHAT_ONE2ONE and _type == C.MESS_TYPE_GROUPCHAT)):
|
||||
timestamp, from_jid, to_jid, message, type_, extra = line # FIXME: extra is unused !
|
||||
if ((self.type == C.CHAT_GROUP and type_ != C.MESS_TYPE_GROUPCHAT) or
|
||||
(self.type == C.CHAT_ONE2ONE and type_ == C.MESS_TYPE_GROUPCHAT)):
|
||||
continue
|
||||
self.printMessage(JID(from_jid), message, profile, timestamp)
|
||||
self.printMessage(jid.JID(from_jid), message, {'timestamp':timestamp}, profile)
|
||||
self.afterHistoryPrint()
|
||||
|
||||
def onHistoryError(err):
|
||||
|
|
@ -165,7 +172,7 @@ class QuickChat(quick_widgets.QuickWidget):
|
|||
|
||||
target = self.target.bare
|
||||
|
||||
return self.host.bridge.getHistory(self.host.profiles[profile].whoami.bare, target, size, search=search, profile=profile, callback=onHistory, errback=onHistoryError)
|
||||
self.host.bridge.getHistory(unicode(self.host.profiles[profile].whoami.bare), unicode(target), size, True, search, profile, callback=onHistory, errback=onHistoryError)
|
||||
|
||||
def _get_nick(self, entity):
|
||||
"""Return nick of this entity when possible"""
|
||||
|
|
@ -193,29 +200,27 @@ class QuickChat(quick_widgets.QuickWidget):
|
|||
chat_widget = self.getOrCreatePrivateWidget(target)
|
||||
chat_widget.newMessage(from_jid, target, msg, type_, extra, profile)
|
||||
else:
|
||||
timestamp = extra.get('archive')
|
||||
if type_ == C.MESS_TYPE_INFO:
|
||||
self.printInfo(msg, timestamp=float(timestamp) if timestamp else None)
|
||||
self.printInfo(msg, extra=extra)
|
||||
else:
|
||||
self.printMessage(from_jid, msg, profile, float(timestamp) if timestamp else None)
|
||||
self.printMessage(from_jid, msg, extra, profile)
|
||||
|
||||
def printMessage(self, from_jid, msg, profile, timestamp=None):
|
||||
def printMessage(self, from_jid, msg, extra=None, profile=C.PROF_KEY_NONE):
|
||||
"""Print message in chat window. Must be implemented by child class"""
|
||||
jid = JID(from_jid)
|
||||
nick = self._get_nick(jid)
|
||||
mymess = (jid.resource == self.nick) if self.type == C.CHAT_GROUP else (jid.bare == self.host.profiles[profile].whoami.bare) #mymess = True if message comes from local user
|
||||
nick = self._get_nick(from_jid)
|
||||
mymess = (from_jid.resource == self.nick) if self.type == C.CHAT_GROUP else (from_jid.bare == self.host.profiles[profile].whoami.bare) #mymess = True if message comes from local user
|
||||
if msg.startswith('/me '):
|
||||
self.printInfo('* %s %s' % (nick, msg[4:]), type_='me', timestamp=timestamp)
|
||||
self.printInfo('* %s %s' % (nick, msg[4:]), type_='me', extra=extra)
|
||||
return
|
||||
return jid, nick, mymess
|
||||
return nick, mymess
|
||||
|
||||
def printInfo(self, msg, type_='normal', timestamp=None):
|
||||
def printInfo(self, msg, type_='normal', extra=None):
|
||||
"""Print general info
|
||||
@param msg: message to print
|
||||
@type_: one of:
|
||||
normal: general info like "toto has joined the room"
|
||||
me: "/me" information like "/me clenches his fist" ==> "toto clenches his fist"
|
||||
@param timestamp (float): number of seconds since epoch
|
||||
@param extra (dict): message data
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,18 @@ from sat.core.log import getLogger
|
|||
log = getLogger(__name__)
|
||||
from sat_frontends.quick_frontend.quick_widgets import QuickWidget
|
||||
from sat_frontends.quick_frontend.constants import Const as C
|
||||
from sat_frontends.tools import jid
|
||||
|
||||
|
||||
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
|
||||
# XXX: pyjamas' max doesn't support key argument, so we implement it ourself
|
||||
pyjamas_max = max
|
||||
def max(iterable, key):
|
||||
iter_cpy = list(iterable)
|
||||
iter_cpy.sort(key=key)
|
||||
return pyjamas_max(iter_cpy)
|
||||
|
||||
|
||||
class QuickContactList(QuickWidget):
|
||||
|
|
@ -78,18 +89,6 @@ class QuickContactList(QuickWidget):
|
|||
for contact in contacts:
|
||||
self.host.newContactHandler(*contact, profile=self.profile)
|
||||
|
||||
presences = self.host.bridge.getPresenceStatuses(self.profile)
|
||||
for contact in presences:
|
||||
for res in presences[contact]:
|
||||
jabber_id = ('%s/%s' % (jid.JID(contact).bare, res)) if res else contact
|
||||
show = presences[contact][res][0]
|
||||
priority = presences[contact][res][1]
|
||||
statuses = presences[contact][res][2]
|
||||
self.host.presenceUpdateHandler(jabber_id, show, priority, statuses, self.profile)
|
||||
data = self.host.bridge.getEntityData(contact, ['avatar', 'nick'], self.profile)
|
||||
for key in ('avatar', 'nick'):
|
||||
if key in data:
|
||||
self.host.entityDataUpdatedHandler(contact, key, data[key], self.profile)
|
||||
self.host.bridge.getContacts(self.profile, callback=gotContacts)
|
||||
|
||||
def update(self):
|
||||
|
|
@ -105,7 +104,12 @@ class QuickContactList(QuickWidget):
|
|||
- if resource is given, it is used
|
||||
@param name(unicode): name the data to get, or None to get everything
|
||||
"""
|
||||
cache = self._cache[entity.bare]
|
||||
try:
|
||||
cache = self._cache[entity.bare]
|
||||
except KeyError:
|
||||
self.setContact(entity)
|
||||
cache = self._cache[entity.bare]
|
||||
|
||||
if name is None:
|
||||
return cache
|
||||
try:
|
||||
|
|
@ -280,10 +284,6 @@ class QuickContactList(QuickWidget):
|
|||
set_.difference_update(to_remove)
|
||||
self.update()
|
||||
|
||||
def add(self, jid, param_groups=None):
|
||||
"""add a contact to the list"""
|
||||
raise NotImplementedError
|
||||
|
||||
def updatePresence(self, entity, show, priority, statuses):
|
||||
"""Update entity's presence status
|
||||
|
||||
|
|
@ -311,7 +311,6 @@ class QuickContactList(QuickWidget):
|
|||
|
||||
priority_resource = max(resources_data, key=lambda res: resources_data[res][C.PRESENCE_PRIORITY])
|
||||
cache[C.CONTACT_MAIN_RESOURCE] = priority_resource
|
||||
self.update()
|
||||
|
||||
def unselectAll(self):
|
||||
"""Unselect all contacts"""
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@
|
|||
# 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 _
|
||||
from os.path import exists, splitext
|
||||
from optparse import OptionParser
|
||||
|
||||
def getNewPath(path):
|
||||
""" Check if path exists, and find a non existant path if needed """
|
||||
|
|
@ -31,3 +33,19 @@ def getNewPath(path):
|
|||
return new_path
|
||||
idx+=1
|
||||
|
||||
def check_options():
|
||||
"""Check command line options"""
|
||||
usage = _("""
|
||||
%prog [options]
|
||||
|
||||
%prog --help for options list
|
||||
""")
|
||||
parser = OptionParser(usage=usage) # TODO: use argparse
|
||||
|
||||
parser.add_option("-p", "--profile", help=_("Select the profile to use"))
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
if options.profile:
|
||||
options.profile = options.profile.decode('utf-8')
|
||||
return options
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@ from sat.core import exceptions
|
|||
classes_map = {}
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
def register(base_cls, child_cls=None):
|
||||
"""Register a child class to use by default when a base class is needed
|
||||
|
||||
|
|
@ -43,6 +50,40 @@ class QuickWidgetsManager(object):
|
|||
self.host = host
|
||||
self._widgets = {}
|
||||
|
||||
def __iter__(self):
|
||||
"""Iterate throught all widgets"""
|
||||
for widget_map in self._widgets.itervalues():
|
||||
for widget in widget_map.itervalues():
|
||||
yield widget
|
||||
|
||||
def getRealClass(self, class_):
|
||||
"""Return class registered for given class_
|
||||
|
||||
@param class_: subclass of QuickWidget
|
||||
@return: class actually used to create widget
|
||||
"""
|
||||
try:
|
||||
cls = classes_map[class_]
|
||||
except KeyError:
|
||||
cls = class_
|
||||
if cls is None:
|
||||
raise exceptions.InternalError("There is not class registered for {}".format(class_))
|
||||
return cls
|
||||
|
||||
def getWidgets(self, class_):
|
||||
"""Get all subclassed widgets
|
||||
|
||||
@param class_: subclass of QuickWidget, same parameter as used in [getOrCreateWidget]
|
||||
@return: iterator on widgets
|
||||
"""
|
||||
class_ = self.getRealClass(class_)
|
||||
try:
|
||||
widgets_map = self._widgets[class_]
|
||||
except KeyError:
|
||||
return iter([])
|
||||
else:
|
||||
return widgets_map.itervalues()
|
||||
|
||||
def getOrCreateWidget(self, class_, target, *args, **kwargs):
|
||||
"""Get an existing widget or create a new one when necessary
|
||||
|
||||
|
|
@ -60,13 +101,7 @@ class QuickWidgetsManager(object):
|
|||
if 'force_hash' is present, the hash given in value will be used instead of the one returned by class_.getWidgetHash
|
||||
@return: a class_ instance, either new or already existing
|
||||
"""
|
||||
# class management
|
||||
try:
|
||||
cls = classes_map[class_]
|
||||
except KeyError:
|
||||
cls = class_
|
||||
if cls is None:
|
||||
raise exceptions.InternalError("There is not class registered for {}".format(class_))
|
||||
cls = self.getRealClass(class_)
|
||||
|
||||
# arguments management
|
||||
_args = [self.host, target] + list(args) or [] # FIXME: check if it's really necessary to use optional args
|
||||
|
|
@ -86,12 +121,12 @@ class QuickWidgetsManager(object):
|
|||
hash_ = cls.getWidgetHash(target, _kwargs['profiles'])
|
||||
|
||||
# widget creation or retrieval
|
||||
widgets_list = self._widgets.setdefault(cls, {}) # we sorts widgets by classes
|
||||
widgets_map = self._widgets.setdefault(cls, {}) # we sorts widgets by classes
|
||||
if not cls.SINGLE:
|
||||
widget = None # if the class is not SINGLE, we always create a new widget
|
||||
else:
|
||||
try:
|
||||
widget = widgets_list[hash_]
|
||||
widget = widgets_map[hash_]
|
||||
widget.addTarget(target)
|
||||
except KeyError:
|
||||
widget = None
|
||||
|
|
@ -106,7 +141,7 @@ class QuickWidgetsManager(object):
|
|||
|
||||
log.debug(u"Creating new widget for target {} {}".format(target, cls))
|
||||
widget = cls(*_args, **_kwargs)
|
||||
widgets_list[hash_] = widget
|
||||
widgets_map[hash_] = widget
|
||||
|
||||
if on_new_widget == 'NEW_WIDGET':
|
||||
self.host.newWidget(widget)
|
||||
|
|
|
|||
Loading…
Reference in a new issue