diff frontends/src/quick_frontend/quick_app.py @ 1103:a096b8579a3c

frontends: signals are managed in a more generic way
author Goffi <goffi@goffi.org>
date Mon, 11 Aug 2014 19:10:24 +0200
parents 11e2bb20e896
children 6053fb8a6466
line wrap: on
line diff
--- a/frontends/src/quick_frontend/quick_app.py	Tue Jul 15 18:28:40 2014 +0200
+++ b/frontends/src/quick_frontend/quick_app.py	Mon Aug 11 19:10:24 2014 +0200
@@ -47,47 +47,64 @@
         except BridgeInitError:
             print(_(u"Can't init bridge"))
             sys.exit(1)
-        self.bridge.register("connected", self.connected)
-        self.bridge.register("disconnected", self.disconnected)
-        self.bridge.register("newContact", self.newContact)
-        self.bridge.register("newMessage", self._newMessage)
-        self.bridge.register("newAlert", self.newAlert)
-        self.bridge.register("presenceUpdate", self.presenceUpdate)
-        self.bridge.register("subscribe", self.subscribe)
-        self.bridge.register("paramUpdate", self.paramUpdate)
-        self.bridge.register("contactDeleted", self.contactDeleted)
-        self.bridge.register("entityDataUpdated", self.entityDataUpdated)
-        self.bridge.register("askConfirmation", self.askConfirmation)
-        self.bridge.register("actionResult", self.actionResult)
-        self.bridge.register("actionResultExt", self.actionResult)
-        self.bridge.register("roomJoined", self.roomJoined, "plugin")
-        self.bridge.register("roomLeft", self.roomLeft, "plugin")
-        self.bridge.register("roomUserJoined", self.roomUserJoined, "plugin")
-        self.bridge.register("roomUserLeft", self.roomUserLeft, "plugin")
-        self.bridge.register("roomUserChangedNick", self.roomUserChangedNick, "plugin")
-        self.bridge.register("roomNewSubject", self.roomNewSubject, "plugin")
-        self.bridge.register("tarotGameStarted", self.tarotGameStarted, "plugin")
-        self.bridge.register("tarotGameNew", self.tarotGameNew, "plugin")
-        self.bridge.register("tarotGameChooseContrat", self.tarotChooseContrat, "plugin")
-        self.bridge.register("tarotGameShowCards", self.tarotShowCards, "plugin")
-        self.bridge.register("tarotGameYourTurn", self.tarotMyTurn, "plugin")
-        self.bridge.register("tarotGameScore", self.tarotScore, "plugin")
-        self.bridge.register("tarotGameCardsPlayed", self.tarotCardsPlayed, "plugin")
-        self.bridge.register("tarotGameInvalidCards", self.tarotInvalidCards, "plugin")
-        self.bridge.register("quizGameStarted", self.quizGameStarted, "plugin")
-        self.bridge.register("quizGameNew", self.quizGameNew, "plugin")
-        self.bridge.register("quizGameQuestion", self.quizGameQuestion, "plugin")
-        self.bridge.register("quizGamePlayerBuzzed", self.quizGamePlayerBuzzed, "plugin")
-        self.bridge.register("quizGamePlayerSays", self.quizGamePlayerSays, "plugin")
-        self.bridge.register("quizGameAnswerResult", self.quizGameAnswerResult, "plugin")
-        self.bridge.register("quizGameTimerExpired", self.quizGameTimerExpired, "plugin")
-        self.bridge.register("quizGameTimerRestarted", self.quizGameTimerRestarted, "plugin")
-        self.bridge.register("chatStateReceived", self.chatStateReceived, "plugin")
+        self.registerSignal("connected")
+        self.registerSignal("disconnected")
+        self.registerSignal("newContact")
+        self.registerSignal("newMessage", self._newMessage)
+        self.registerSignal("newAlert")
+        self.registerSignal("presenceUpdate")
+        self.registerSignal("subscribe")
+        self.registerSignal("paramUpdate")
+        self.registerSignal("contactDeleted")
+        self.registerSignal("entityDataUpdated")
+        self.registerSignal("askConfirmation")
+        self.registerSignal("actionResult")
+        self.registerSignal("actionResultExt", self.actionResultHandler)
+        self.registerSignal("roomJoined", iface="plugin")
+        self.registerSignal("roomLeft", iface="plugin")
+        self.registerSignal("roomUserJoined", iface="plugin")
+        self.registerSignal("roomUserLeft", iface="plugin")
+        self.registerSignal("roomUserChangedNick", iface="plugin")
+        self.registerSignal("roomNewSubject", iface="plugin")
+        self.registerSignal("tarotGameStarted", iface="plugin")
+        self.registerSignal("tarotGameNew", iface="plugin")
+        self.registerSignal("tarotGameChooseContrat", iface="plugin")
+        self.registerSignal("tarotGameShowCards", iface="plugin")
+        self.registerSignal("tarotGameYourTurn", iface="plugin")
+        self.registerSignal("tarotGameScore", iface="plugin")
+        self.registerSignal("tarotGameCardsPlayed", iface="plugin")
+        self.registerSignal("tarotGameInvalidCards", iface="plugin")
+        self.registerSignal("quizGameStarted", iface="plugin")
+        self.registerSignal("quizGameNew", iface="plugin")
+        self.registerSignal("quizGameQuestion", iface="plugin")
+        self.registerSignal("quizGamePlayerBuzzed", iface="plugin")
+        self.registerSignal("quizGamePlayerSays", iface="plugin")
+        self.registerSignal("quizGameAnswerResult", iface="plugin")
+        self.registerSignal("quizGameTimerExpired", iface="plugin")
+        self.registerSignal("quizGameTimerRestarted", iface="plugin")
+        self.registerSignal("chatStateReceived", iface="plugin")
 
         self.current_action_ids = set()
         self.current_action_ids_cb = {}
         self.media_dir = self.bridge.getConfig('', 'media_dir')
 
+    def registerSignal(self, functionName, handler=None, iface="core"):
+        """Register a handler for a signal
+
+        @param functionName: name of the signal to handle
+        @param handler: method to call when the signal arrive, None for calling an automaticaly named handler (functionName + 'Handler')
+        @param iface: interface of the bridge to use
+
+        """
+        if handler is None:
+            handler = getattr(self, "%s%s" % (functionName, 'Handler'))
+        def signalReceived(*args, **kwargs):
+            profile = kwargs.get('profile', None)
+            if profile is not None and not self.check_profile(profile):
+                return # we ignore signal for profiles we don't manage
+            handler(*args, **kwargs)
+        self.bridge.register(functionName, signalReceived, iface)
+
     def check_profile(self, profile):
         """Tell if the profile is currently followed by the application"""
         return profile in self.profiles.keys()
@@ -189,7 +206,7 @@
 
             ### now we fill the contact list ###
             for contact in self.bridge.getContacts(profile):
-                self.newContact(*contact, profile=profile)
+                self.newContactHandler(*contact, profile=profile)
 
             presences = self.bridge.getPresenceStatuses(profile)
             for contact in presences:
@@ -198,27 +215,27 @@
                     show = presences[contact][res][0]
                     priority = presences[contact][res][1]
                     statuses = presences[contact][res][2]
-                    self.presenceUpdate(jabber_id, show, priority, statuses, profile)
+                    self.presenceUpdateHandler(jabber_id, show, priority, statuses, profile)
                 data = self.bridge.getEntityData(contact, ['avatar', 'nick'], profile)
                 for key in ('avatar', 'nick'):
                     if key in data:
-                        self.entityDataUpdated(contact, key, data[key], profile)
+                        self.entityDataUpdatedHandler(contact, key, data[key], profile)
 
             #The waiting subscription requests
             waitingSub = self.bridge.getWaitingSub(profile)
             for sub in waitingSub:
-                self.subscribe(waitingSub[sub], sub, profile)
+                self.subscribeHandler(waitingSub[sub], sub, profile)
 
             #Now we open the MUC window where we already are:
             for room_args in self.bridge.getRoomsJoined(profile):
-                self.roomJoined(*room_args, profile=profile)
+                self.roomJoinedHandler(*room_args, profile=profile)
 
             for subject_args in self.bridge.getRoomsSubjects(profile):
-                self.roomNewSubject(*subject_args, profile=profile)
+                self.roomNewSubjectHandler(*subject_args, profile=profile)
 
             #Finaly, we get the waiting confirmation requests
             for confirm_id, confirm_type, data in self.bridge.getWaitingConf(profile):
-                self.askConfirmation(confirm_id, confirm_type, data, profile)
+                self.askConfirmationHandler(confirm_id, confirm_type, data, profile)
 
     def unplug_profile(self, profile):
         """Tell the application to not follow anymore the profile"""
@@ -230,24 +247,18 @@
     def clear_profile(self):
         self.profiles.clear()
 
-    def connected(self, profile):
+    def connectedHandler(self, profile):
         """called when the connection is made"""
-        if not self.check_profile(profile):
-            return
         log.debug(_("Connected"))
         self.setStatusOnline(True)
 
-    def disconnected(self, profile):
+    def disconnectedHandler(self, profile):
         """called when the connection is closed"""
-        if not self.check_profile(profile):
-            return
         log.debug(_("Disconnected"))
         self.contact_list.clearContacts()
         self.setStatusOnline(False)
 
-    def newContact(self, JabberId, attributes, groups, profile):
-        if not self.check_profile(profile):
-            return
+    def newContactHandler(self, JabberId, attributes, groups, profile):
         entity = JID(JabberId)
         _groups = list(groups)
         self.contact_list.replace(entity, _groups, attributes)
@@ -255,8 +266,6 @@
     def _newMessage(self, from_jid_s, msg, _type, to_jid_s, extra, profile):
         """newMessage premanagement: a dirty hack to manage private messages
         if a private MUC message is detected, from_jid or to_jid is prefixed and resource is escaped"""
-        if not self.check_profile(profile):
-            return
         from_jid = JID(from_jid_s)
         to_jid = JID(to_jid_s)
 
@@ -276,9 +285,9 @@
             if new_jid not in self.contact_list:
                 self.contact_list.add(new_jid, [C.GROUP_NOT_IN_ROSTER])
 
-        self.newMessage(from_jid, to_jid, msg, _type, extra, profile)
+        self.newMessageHandler(from_jid, to_jid, msg, _type, extra, profile)
 
-    def newMessage(self, from_jid, to_jid, msg, _type, extra, profile):
+    def newMessageHandler(self, from_jid, to_jid, msg, _type, extra, profile):
         from_me = from_jid.bare == self.profiles[profile]['whoami'].bare
         win = to_jid if from_me else from_jid
 
@@ -298,18 +307,14 @@
             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)
 
-    def newAlert(self, msg, title, alert_type, profile):
-        if not self.check_profile(profile):
-            return
+    def newAlertHandler(self, msg, title, alert_type, profile):
         assert alert_type in ['INFO', 'ERROR']
         self.showDialog(unicode(msg), unicode(title), alert_type.lower())
 
     def setStatusOnline(self, online=True, show="", statuses={}):
         raise NotImplementedError
 
-    def presenceUpdate(self, jabber_id, show, priority, statuses, profile):
-        if not self.check_profile(profile):
-            return
+    def presenceUpdateHandler(self, jabber_id, show, priority, statuses, profile):
 
         log.debug(_("presence update for %(jid)s (show=%(show)s, priority=%(priority)s, statuses=%(statuses)s) [profile:%(profile)s]")
               % {'jid': jabber_id, 'show': show, 'priority': priority, 'statuses': statuses, 'profile': profile})
@@ -356,10 +361,8 @@
             # case 2: update (or confirm) with the values of the resource which takes precedence
             self.contact_list.updatePresence(from_jid, show, priority, statuses)
 
-    def roomJoined(self, room_jid, room_nicks, user_nick, profile):
+    def roomJoinedHandler(self, room_jid, room_nicks, user_nick, profile):
         """Called when a MUC room is joined"""
-        if not self.check_profile(profile):
-            return
         log.debug(_("Room [%(room_jid)s] joined by %(profile)s, users presents:%(users)s") % {'room_jid': room_jid, 'profile': profile, 'users': room_nicks})
         self.chat_wins[room_jid].setUserNick(user_nick)
         self.chat_wins[room_jid].setType("group")
@@ -367,171 +370,127 @@
         self.chat_wins[room_jid].setPresents(list(set([user_nick] + room_nicks)))
         self.contact_list.setSpecial(JID(room_jid), "MUC", show=True)
 
-    def roomLeft(self, room_jid_s, profile):
+    def roomLeftHandler(self, room_jid_s, profile):
         """Called when a MUC room is left"""
-        if not self.check_profile(profile):
-            return
         log.debug(_("Room [%(room_jid)s] left by %(profile)s") % {'room_jid': room_jid_s, 'profile': profile})
         del self.chat_wins[room_jid_s]
         self.contact_list.remove(JID(room_jid_s))
 
-    def roomUserJoined(self, room_jid, user_nick, user_data, profile):
+    def roomUserJoinedHandler(self, room_jid, user_nick, user_data, profile):
         """Called when an user joined a MUC room"""
-        if not self.check_profile(profile):
-            return
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].replaceUser(user_nick)
             log.debug(_("user [%(user_nick)s] joined room [%(room_jid)s]") % {'user_nick': user_nick, 'room_jid': room_jid})
 
-    def roomUserLeft(self, room_jid, user_nick, user_data, profile):
+    def roomUserLeftHandler(self, room_jid, user_nick, user_data, profile):
         """Called when an user joined a MUC room"""
-        if not self.check_profile(profile):
-            return
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].removeUser(user_nick)
             log.debug(_("user [%(user_nick)s] left room [%(room_jid)s]") % {'user_nick': user_nick, 'room_jid': room_jid})
 
-    def roomUserChangedNick(self, room_jid, old_nick, new_nick, profile):
+    def roomUserChangedNickHandler(self, room_jid, old_nick, new_nick, profile):
         """Called when an user joined a MUC room"""
-        if not self.check_profile(profile):
-            return
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].changeUserNick(old_nick, new_nick)
             log.debug(_("user [%(old_nick)s] is now known as [%(new_nick)s] in room [%(room_jid)s]") % {'old_nick': old_nick, 'new_nick': new_nick, 'room_jid': room_jid})
 
-    def roomNewSubject(self, room_jid, subject, profile):
+    def roomNewSubjectHandler(self, room_jid, subject, profile):
         """Called when subject of MUC room change"""
-        if not self.check_profile(profile):
-            return
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].setSubject(subject)
             log.debug(_("new subject for room [%(room_jid)s]: %(subject)s") % {'room_jid': room_jid, "subject": subject})
 
-    def tarotGameStarted(self, room_jid, referee, players, profile):
-        if not self.check_profile(profile):
-            return
+    def tarotGameStartedHandler(self, room_jid, referee, players, profile):
         log.debug(_("Tarot Game Started \o/"))
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].startGame("Tarot", referee, players)
             log.debug(_("new Tarot game started by [%(referee)s] in room [%(room_jid)s] with %(players)s") % {'referee': referee, 'room_jid': room_jid, 'players': [str(player) for player in players]})
 
-    def tarotGameNew(self, room_jid, hand, profile):
-        if not self.check_profile(profile):
-            return
+    def tarotGameNewHandler(self, room_jid, hand, profile):
         log.debug(_("New Tarot Game"))
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].getGame("Tarot").newGame(hand)
 
-    def tarotChooseContrat(self, room_jid, xml_data, profile):
+    def tarotGameChooseContratHandler(self, room_jid, xml_data, profile):
         """Called when the player has to select his contrat"""
-        if not self.check_profile(profile):
-            return
         log.debug(_("Tarot: need to select a contrat"))
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].getGame("Tarot").chooseContrat(xml_data)
 
-    def tarotShowCards(self, room_jid, game_stage, cards, data, profile):
-        if not self.check_profile(profile):
-            return
+    def tarotGameShowCardsHandler(self, room_jid, game_stage, cards, data, profile):
         log.debug(_("Show cards"))
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].getGame("Tarot").showCards(game_stage, cards, data)
 
-    def tarotMyTurn(self, room_jid, profile):
-        if not self.check_profile(profile):
-            return
+    def tarotGameYourTurnHandler(self, room_jid, profile):
         log.debug(_("My turn to play"))
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].getGame("Tarot").myTurn()
 
-    def tarotScore(self, room_jid, xml_data, winners, loosers, profile):
+    def tarotGameScoreHandler(self, room_jid, xml_data, winners, loosers, profile):
         """Called when the game is finished and the score are updated"""
-        if not self.check_profile(profile):
-            return
         log.debug(_("Tarot: score received"))
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].getGame("Tarot").showScores(xml_data, winners, loosers)
 
-    def tarotCardsPlayed(self, room_jid, player, cards, profile):
-        if not self.check_profile(profile):
-            return
+    def tarotGameCardsPlayedHandler(self, room_jid, player, cards, profile):
         log.debug(_("Card(s) played (%(player)s): %(cards)s") % {"player": player, "cards": cards})
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].getGame("Tarot").cardsPlayed(player, cards)
 
-    def tarotInvalidCards(self, room_jid, phase, played_cards, invalid_cards, profile):
-        if not self.check_profile(profile):
-            return
+    def tarotGameInvalidCardsHandler(self, room_jid, phase, played_cards, invalid_cards, profile):
         log.debug(_("Cards played are not valid: %s") % invalid_cards)
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].getGame("Tarot").invalidCards(phase, played_cards, invalid_cards)
 
-    def quizGameStarted(self, room_jid, referee, players, profile):
-        if not self.check_profile(profile):
-            return
+    def quizGameStartedHandler(self, room_jid, referee, players, profile):
         log.debug(_("Quiz Game Started \o/"))
         if room_jid in self.chat_wins:
             self.chat_wins[room_jid].startGame("Quiz", referee, players)
             log.debug(_("new Quiz game started by [%(referee)s] in room [%(room_jid)s] with %(players)s") % {'referee': referee, 'room_jid': room_jid, 'players': [str(player) for player in players]})
 
-    def quizGameNew(self, room_jid, data, profile):
-        if not self.check_profile(profile):
-            return
+    def quizGameNewHandler(self, room_jid, data, profile):
         log.debug(_("New Quiz Game"))
         if room_jid in self.chat_wins:
-            self.chat_wins[room_jid].getGame("Quiz").quizGameNew(data)
+            self.chat_wins[room_jid].getGame("Quiz").quizGameNewHandler(data)
 
-    def quizGameQuestion(self, room_jid, question_id, question, timer, profile):
+    def quizGameQuestionHandler(self, room_jid, question_id, question, timer, profile):
         """Called when a new question is asked"""
-        if not self.check_profile(profile):
-            return
         log.debug(_(u"Quiz: new question: %s") % question)
         if room_jid in self.chat_wins:
-            self.chat_wins[room_jid].getGame("Quiz").quizGameQuestion(question_id, question, timer)
+            self.chat_wins[room_jid].getGame("Quiz").quizGameQuestionHandler(question_id, question, timer)
 
-    def quizGamePlayerBuzzed(self, room_jid, player, pause, profile):
+    def quizGamePlayerBuzzedHandler(self, room_jid, player, pause, profile):
         """Called when a player pushed the buzzer"""
-        if not self.check_profile(profile):
-            return
         if room_jid in self.chat_wins:
-            self.chat_wins[room_jid].getGame("Quiz").quizGamePlayerBuzzed(player, pause)
+            self.chat_wins[room_jid].getGame("Quiz").quizGamePlayerBuzzedHandler(player, pause)
 
-    def quizGamePlayerSays(self, room_jid, player, text, delay, profile):
+    def quizGamePlayerSaysHandler(self, room_jid, player, text, delay, profile):
         """Called when a player say something"""
-        if not self.check_profile(profile):
-            return
         if room_jid in self.chat_wins:
-            self.chat_wins[room_jid].getGame("Quiz").quizGamePlayerSays(player, text, delay)
+            self.chat_wins[room_jid].getGame("Quiz").quizGamePlayerSaysHandler(player, text, delay)
 
-    def quizGameAnswerResult(self, room_jid, player, good_answer, score, profile):
+    def quizGameAnswerResultHandler(self, room_jid, player, good_answer, score, profile):
         """Called when a player say something"""
-        if not self.check_profile(profile):
-            return
         if room_jid in self.chat_wins:
-            self.chat_wins[room_jid].getGame("Quiz").quizGameAnswerResult(player, good_answer, score)
+            self.chat_wins[room_jid].getGame("Quiz").quizGameAnswerResultHandler(player, good_answer, score)
 
-    def quizGameTimerExpired(self, room_jid, profile):
+    def quizGameTimerExpiredHandler(self, room_jid, profile):
         """Called when nobody answered the question in time"""
-        if not self.check_profile(profile):
-            return
         if room_jid in self.chat_wins:
-            self.chat_wins[room_jid].getGame("Quiz").quizGameTimerExpired()
+            self.chat_wins[room_jid].getGame("Quiz").quizGameTimerExpiredHandler()
 
-    def quizGameTimerRestarted(self, room_jid, time_left, profile):
+    def quizGameTimerRestartedHandler(self, room_jid, time_left, profile):
         """Called when the question is not answered, and we still have time"""
-        if not self.check_profile(profile):
-            return
         if room_jid in self.chat_wins:
-            self.chat_wins[room_jid].getGame("Quiz").quizGameTimerRestarted(time_left)
+            self.chat_wins[room_jid].getGame("Quiz").quizGameTimerRestartedHandler(time_left)
 
-    def chatStateReceived(self, from_jid_s, state, profile):
+    def chatStateReceivedHandler(self, from_jid_s, state, profile):
         """Callback when a new chat state is received.
         @param from_jid_s: JID of the contact who sent his state, or '@ALL@'
         @param state: new state (string)
         @profile: current profile
         """
-        if not self.check_profile(profile):
-            return
 
         if from_jid_s == '@ALL@':
             target = '@ALL@'
@@ -556,10 +515,8 @@
         else:
             self.bridge.subscription("unsubscribed", entity.bare, profile_key=profile)
 
-    def subscribe(self, type, raw_jid, profile):
+    def subscribeHandler(self, type, raw_jid, profile):
         """Called when a subsciption management signal is received"""
-        if not self.check_profile(profile):
-            return
         entity = JID(raw_jid)
         if type == "subscribed":
             # this is a subscription confirmation, we just have to inform user
@@ -577,9 +534,7 @@
     def showAlert(self, message):
         pass  #FIXME
 
-    def paramUpdate(self, name, value, namespace, profile):
-        if not self.check_profile(profile):
-            return
+    def paramUpdateHandler(self, name, value, namespace, profile):
         log.debug(_("param update: [%(namespace)s] %(name)s = %(value)s") % {'namespace': namespace, 'name': name, 'value': value})
         if (namespace, name) == ("Connection", "JabberID"):
             log.debug(_("Changing JID to %s") % value)
@@ -587,9 +542,7 @@
         elif (namespace, name) == ("Misc", "Watched"):
             self.profiles[profile]['watched'] = value.split()
 
-    def contactDeleted(self, jid, profile):
-        if not self.check_profile(profile):
-            return
+    def contactDeletedHandler(self, jid, profile):
         target = JID(jid)
         self.contact_list.remove(target)
         try:
@@ -597,9 +550,7 @@
         except KeyError:
             pass
 
-    def entityDataUpdated(self, jid_str, key, value, profile):
-        if not self.check_profile(profile):
-            return
+    def entityDataUpdatedHandler(self, jid_str, key, value, profile):
         jid = JID(jid_str)
         if key == "nick":
             if jid in self.contact_list:
@@ -611,10 +562,10 @@
                 self.contact_list.setCache(jid, 'avatar', filename)
                 self.contact_list.replace(jid)
 
-    def askConfirmation(self, confirm_id, confirm_type, data, profile):
+    def askConfirmationHandler(self, confirm_id, confirm_type, data, profile):
         raise NotImplementedError
 
-    def actionResult(self, type, id, data):
+    def actionResultHandler(self, type, id, data):
         raise NotImplementedError
 
     def launchAction(self, callback_id, data=None, profile_key="@NONE@"):