# HG changeset patch # User Goffi # Date 1553069327 -3600 # Node ID b2e898384c25ab1ab129b500e7ef80ea3a7b0c2d # Parent e9e33e05d1433891de0bf60d4bb3e7ff47589e94 quick_frontend (app): progress callbacks handling: in addition to listeners, a frontend can now register progression callback and errback which are called when the given progressing action is finished. Those callbacks can be registered using registerProgressCbs or specified in actionManager. diff -r e9e33e05d143 -r b2e898384c25 sat_frontends/quick_frontend/quick_app.py --- a/sat_frontends/quick_frontend/quick_app.py Wed Mar 20 09:08:47 2019 +0100 +++ b/sat_frontends/quick_frontend/quick_app.py Wed Mar 20 09:08:47 2019 +0100 @@ -313,7 +313,7 @@ # widget currently selected (must be filled by frontend) self.selected_widget = None - # listeners + # listeners are callable watching events self._listeners = {} # key: listener type ("avatar", "selected", etc), # value: list of callbacks @@ -328,12 +328,20 @@ if connect_bridge: self.connectBridge() + # frontend notifications self._notif_id = 0 self._notifications = OrderedDict() + # watched progresses and associated callbacks + self._progress_ids = {} + # available features + # FIXME: features are profile specific, to be checked self.features = None - self.ns_map = {} # map of short name to namespaces + #: map of short name to namespaces + self.ns_map = {} + #: available encryptions self.encryption_plugins = [] - self._sync = True # state of synchronisation with backend + # state of synchronisation with backend + self._sync = True def connectBridge(self): self.bridge.bridgeConnect(callback=self._bridgeCb, errback=self._bridgeEb) @@ -436,7 +444,7 @@ @property def sync(self): - """Get synchronization flag + """Synchronization flag True if this frontend is synchronised with backend """ @@ -1042,15 +1050,44 @@ else: log.warning("Unmanaged PubSub event type {}".format(event_type)) + def registerProgressCbs(self, progress_id, callback, errback): + """Register progression callbacks + + @param progress_id(unicode): id of the progression to check + @param callback(callable, None): method to call when progressing action + successfuly finished. + None to ignore + @param errback(callable, None): method to call when progressions action failed + None to ignore + """ + callbacks = self._progress_ids.setdefault(progress_id, []) + callbacks.append((callback, errback)) + def progressStartedHandler(self, pid, metadata, profile): log.info(u"Progress {} started".format(pid)) def progressFinishedHandler(self, pid, metadata, profile): log.info(u"Progress {} finished".format(pid)) + try: + callbacks = self._progress_ids.pop(pid) + except KeyError: + pass + else: + for callback, __ in callbacks: + if callback is not None: + callback(metadata, profile=profile) self.callListeners("progressFinished", pid, metadata, profile=profile) def progressErrorHandler(self, pid, err_msg, profile): log.warning(u"Progress {pid} error: {err_msg}".format(pid=pid, err_msg=err_msg)) + try: + callbacks = self._progress_ids.pop(pid) + except KeyError: + pass + else: + for __, errback in callbacks: + if errback is not None: + errback(err_msg, profile=profile) self.callListeners("progressError", pid, err_msg, profile=profile) def _subscribe_cb(self, answer, data): @@ -1166,7 +1203,7 @@ self.getAvatar(entity, ignore_cache=True, profile=profile) def actionManager(self, action_data, callback=None, ui_show_cb=None, user_action=True, - profile=C.PROF_KEY_NONE): + progress_cb=None, progress_eb=None, profile=C.PROF_KEY_NONE): """Handle backend action @param action_data(dict): action dict as sent by launchAction or returned by an @@ -1174,7 +1211,14 @@ @param callback(None, callback): if not None, callback to use on XMLUI answer @param ui_show_cb(None, callback): if not None, method to call to show the XMLUI @param user_action(bool): if True, the action is a result of a user interaction - else the action come from backend direclty (i.e. actionNew) + else the action come from backend direclty (i.e. actionNew). + This is useful to know if the frontend can display a popup immediately (if + True) or if it should add it to a queue that the user can activate later. + @param progress_cb(None, callable): method to call when progression is finished. + Only make sense if a progress is expected in this action + @param progress_eb(None, callable): method to call when something went wrong + during progression. + Only make sense if a progress is expected in this action """ try: xmlui = action_data.pop("xmlui") @@ -1198,6 +1242,8 @@ except KeyError: pass else: + if progress_cb or progress_eb: + self.registerProgressCbs(progress_id, progress_cb, progress_eb) self.progressIdHandler(progress_id, profile) # we ignore metadata