Mercurial > libervia-backend
comparison sat_frontends/quick_frontend/quick_app.py @ 2862:b2e898384c25
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.
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 20 Mar 2019 09:08:47 +0100 |
parents | e9e33e05d143 |
children | c7c52c0dc13a |
comparison
equal
deleted
inserted
replaced
2861:e9e33e05d143 | 2862:b2e898384c25 |
---|---|
311 self.options = None | 311 self.options = None |
312 | 312 |
313 # widget currently selected (must be filled by frontend) | 313 # widget currently selected (must be filled by frontend) |
314 self.selected_widget = None | 314 self.selected_widget = None |
315 | 315 |
316 # listeners | 316 # listeners are callable watching events |
317 self._listeners = {} # key: listener type ("avatar", "selected", etc), | 317 self._listeners = {} # key: listener type ("avatar", "selected", etc), |
318 # value: list of callbacks | 318 # value: list of callbacks |
319 | 319 |
320 # triggers | 320 # triggers |
321 self.trigger = ( | 321 self.trigger = ( |
326 self.bridge = bridge_factory() | 326 self.bridge = bridge_factory() |
327 ProfileManager.bridge = self.bridge | 327 ProfileManager.bridge = self.bridge |
328 if connect_bridge: | 328 if connect_bridge: |
329 self.connectBridge() | 329 self.connectBridge() |
330 | 330 |
331 # frontend notifications | |
331 self._notif_id = 0 | 332 self._notif_id = 0 |
332 self._notifications = OrderedDict() | 333 self._notifications = OrderedDict() |
334 # watched progresses and associated callbacks | |
335 self._progress_ids = {} | |
336 # available features | |
337 # FIXME: features are profile specific, to be checked | |
333 self.features = None | 338 self.features = None |
334 self.ns_map = {} # map of short name to namespaces | 339 #: map of short name to namespaces |
340 self.ns_map = {} | |
341 #: available encryptions | |
335 self.encryption_plugins = [] | 342 self.encryption_plugins = [] |
336 self._sync = True # state of synchronisation with backend | 343 # state of synchronisation with backend |
344 self._sync = True | |
337 | 345 |
338 def connectBridge(self): | 346 def connectBridge(self): |
339 self.bridge.bridgeConnect(callback=self._bridgeCb, errback=self._bridgeEb) | 347 self.bridge.bridgeConnect(callback=self._bridgeCb, errback=self._bridgeEb) |
340 | 348 |
341 def _namespacesGetCb(self, ns_map): | 349 def _namespacesGetCb(self, ns_map): |
434 | 442 |
435 # backend state management | 443 # backend state management |
436 | 444 |
437 @property | 445 @property |
438 def sync(self): | 446 def sync(self): |
439 """Get synchronization flag | 447 """Synchronization flag |
440 | 448 |
441 True if this frontend is synchronised with backend | 449 True if this frontend is synchronised with backend |
442 """ | 450 """ |
443 return self._sync | 451 return self._sync |
444 | 452 |
1040 wid.deleteEntryIfPresent(service_s, node, data["id"], profile) | 1048 wid.deleteEntryIfPresent(service_s, node, data["id"], profile) |
1041 pass | 1049 pass |
1042 else: | 1050 else: |
1043 log.warning("Unmanaged PubSub event type {}".format(event_type)) | 1051 log.warning("Unmanaged PubSub event type {}".format(event_type)) |
1044 | 1052 |
1053 def registerProgressCbs(self, progress_id, callback, errback): | |
1054 """Register progression callbacks | |
1055 | |
1056 @param progress_id(unicode): id of the progression to check | |
1057 @param callback(callable, None): method to call when progressing action | |
1058 successfuly finished. | |
1059 None to ignore | |
1060 @param errback(callable, None): method to call when progressions action failed | |
1061 None to ignore | |
1062 """ | |
1063 callbacks = self._progress_ids.setdefault(progress_id, []) | |
1064 callbacks.append((callback, errback)) | |
1065 | |
1045 def progressStartedHandler(self, pid, metadata, profile): | 1066 def progressStartedHandler(self, pid, metadata, profile): |
1046 log.info(u"Progress {} started".format(pid)) | 1067 log.info(u"Progress {} started".format(pid)) |
1047 | 1068 |
1048 def progressFinishedHandler(self, pid, metadata, profile): | 1069 def progressFinishedHandler(self, pid, metadata, profile): |
1049 log.info(u"Progress {} finished".format(pid)) | 1070 log.info(u"Progress {} finished".format(pid)) |
1071 try: | |
1072 callbacks = self._progress_ids.pop(pid) | |
1073 except KeyError: | |
1074 pass | |
1075 else: | |
1076 for callback, __ in callbacks: | |
1077 if callback is not None: | |
1078 callback(metadata, profile=profile) | |
1050 self.callListeners("progressFinished", pid, metadata, profile=profile) | 1079 self.callListeners("progressFinished", pid, metadata, profile=profile) |
1051 | 1080 |
1052 def progressErrorHandler(self, pid, err_msg, profile): | 1081 def progressErrorHandler(self, pid, err_msg, profile): |
1053 log.warning(u"Progress {pid} error: {err_msg}".format(pid=pid, err_msg=err_msg)) | 1082 log.warning(u"Progress {pid} error: {err_msg}".format(pid=pid, err_msg=err_msg)) |
1083 try: | |
1084 callbacks = self._progress_ids.pop(pid) | |
1085 except KeyError: | |
1086 pass | |
1087 else: | |
1088 for __, errback in callbacks: | |
1089 if errback is not None: | |
1090 errback(err_msg, profile=profile) | |
1054 self.callListeners("progressError", pid, err_msg, profile=profile) | 1091 self.callListeners("progressError", pid, err_msg, profile=profile) |
1055 | 1092 |
1056 def _subscribe_cb(self, answer, data): | 1093 def _subscribe_cb(self, answer, data): |
1057 entity, profile = data | 1094 entity, profile = data |
1058 type_ = "subscribed" if answer else "unsubscribed" | 1095 type_ = "subscribed" if answer else "unsubscribed" |
1164 elif key == "avatar" and self.AVATARS_HANDLER: | 1201 elif key == "avatar" and self.AVATARS_HANDLER: |
1165 if value and entity in self.contact_lists[profile]: | 1202 if value and entity in self.contact_lists[profile]: |
1166 self.getAvatar(entity, ignore_cache=True, profile=profile) | 1203 self.getAvatar(entity, ignore_cache=True, profile=profile) |
1167 | 1204 |
1168 def actionManager(self, action_data, callback=None, ui_show_cb=None, user_action=True, | 1205 def actionManager(self, action_data, callback=None, ui_show_cb=None, user_action=True, |
1169 profile=C.PROF_KEY_NONE): | 1206 progress_cb=None, progress_eb=None, profile=C.PROF_KEY_NONE): |
1170 """Handle backend action | 1207 """Handle backend action |
1171 | 1208 |
1172 @param action_data(dict): action dict as sent by launchAction or returned by an | 1209 @param action_data(dict): action dict as sent by launchAction or returned by an |
1173 UI action | 1210 UI action |
1174 @param callback(None, callback): if not None, callback to use on XMLUI answer | 1211 @param callback(None, callback): if not None, callback to use on XMLUI answer |
1175 @param ui_show_cb(None, callback): if not None, method to call to show the XMLUI | 1212 @param ui_show_cb(None, callback): if not None, method to call to show the XMLUI |
1176 @param user_action(bool): if True, the action is a result of a user interaction | 1213 @param user_action(bool): if True, the action is a result of a user interaction |
1177 else the action come from backend direclty (i.e. actionNew) | 1214 else the action come from backend direclty (i.e. actionNew). |
1215 This is useful to know if the frontend can display a popup immediately (if | |
1216 True) or if it should add it to a queue that the user can activate later. | |
1217 @param progress_cb(None, callable): method to call when progression is finished. | |
1218 Only make sense if a progress is expected in this action | |
1219 @param progress_eb(None, callable): method to call when something went wrong | |
1220 during progression. | |
1221 Only make sense if a progress is expected in this action | |
1178 """ | 1222 """ |
1179 try: | 1223 try: |
1180 xmlui = action_data.pop("xmlui") | 1224 xmlui = action_data.pop("xmlui") |
1181 except KeyError: | 1225 except KeyError: |
1182 pass | 1226 pass |
1196 try: | 1240 try: |
1197 progress_id = action_data.pop("progress") | 1241 progress_id = action_data.pop("progress") |
1198 except KeyError: | 1242 except KeyError: |
1199 pass | 1243 pass |
1200 else: | 1244 else: |
1245 if progress_cb or progress_eb: | |
1246 self.registerProgressCbs(progress_id, progress_cb, progress_eb) | |
1201 self.progressIdHandler(progress_id, profile) | 1247 self.progressIdHandler(progress_id, profile) |
1202 | 1248 |
1203 # we ignore metadata | 1249 # we ignore metadata |
1204 action_data = { | 1250 action_data = { |
1205 k: v for k, v in action_data.iteritems() if not k.startswith("meta_") | 1251 k: v for k, v in action_data.iteritems() if not k.startswith("meta_") |