Mercurial > libervia-backend
diff frontends/src/tools/xmlui.py @ 977:d2e612a45e76
tools, frontends (xmlui): add Widget.setInternalCallback:
- to add UI callback not communication with the bridge
- a list of predefined actions can be used to copy, move, select values
- extra data can be passed within the 'internal_data' element
TODO: frontend side operation to retrieve the data from node to data structure should be generic
author | souliane <souliane@mailoo.org> |
---|---|
date | Thu, 03 Apr 2014 14:56:16 +0200 |
parents | b37b1d183ac3 |
children | 7a39ae3950f7 |
line wrap: on
line diff
--- a/frontends/src/tools/xmlui.py Thu Apr 03 14:49:05 2014 +0200 +++ b/frontends/src/tools/xmlui.py Thu Apr 03 14:56:16 2014 +0200 @@ -191,7 +191,6 @@ raise ValueError(_("XMLUI can have only one main container")) self._main_cont = value - def _parseChilds(self, parent, current_node, wanted = ('container',), data = None): """ Recursively parse childNodes of an elemen @param parent: widget container with '_xmluiAppend' method @@ -315,14 +314,25 @@ print(_("FIXME FIXME FIXME: widget type [%s] is not implemented") % type_) raise NotImplementedError(_("FIXME FIXME FIXME: type [%s] is not implemented") % type_) - if self.type == 'param' and type_ != 'text': + if self.type == 'param' and type_ not in ('text', 'button'): try: ctrl._xmluiOnChange(self.onParamChange) ctrl._param_category = self._current_category - except (AttributeError, TypeError): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError + except (AttributeError, TypeError): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError if not isinstance(ctrl, (EmptyWidget, TextWidget, LabelWidget, JidWidget)): print(_("No change listener on [%s]") % ctrl) + if type_ != 'text': + callback = node.getAttribute("internal_callback") or None + if callback: + fields = [field.getAttribute('name') for field in node.getElementsByTagName("internal_field")] + data = self.getInternalCallbackData(callback, node) + ctrl._xmlui_param_internal = (callback, fields, data) + if type_ == 'button': + ctrl._xmluiOnClick(self.onChangeInternal) + else: + ctrl._xmluiOnChange(self.onChangeInternal) + ctrl._xmlui_name = name parent._xmluiAppend(ctrl) @@ -403,6 +413,8 @@ """ callback_id, fields = button._xmlui_param_id + if not callback_id: # the button is probably bound to an internal action + return data = {} for field in fields: escaped = self.escape(field) @@ -413,6 +425,85 @@ data[escaped] = ctrl['control']._xmluiGetValue() self._xmluiLaunchAction(callback_id, data) + def onChangeInternal(self, ctrl): + """ Called when a widget that has been bound to an internal callback is changed. + + This is used to perform some UI actions without communicating with the backend. + See sat.tools.xml_tools.Widget.setInternalCallback for more details. + @param ctrl: widget modified + """ + action, fields, data = ctrl._xmlui_param_internal + if action not in ('copy', 'move', 'groups_of_contact'): + raise NotImplementedError(_("FIXME: XMLUI internal action [%s] is not implemented") % action) + + def copy_move(source, target): + """Depending of 'action' value, copy or move from source to target.""" + if isinstance(target, ListWidget): + if isinstance(source, ListWidget): + values = source._xmluiGetSelectedValues() + else: + values = [source._xmluiGetValue()] + if action == 'move': + source._xmluiSetValue('') + values = [value for value in values if value] + if values: + target._xmluiAddValues(values, select=True) + else: + if isinstance(source, ListWidget): + value = u', '.join(source._xmluiGetSelectedValues()) + else: + value = source._xmluiGetValue() + if action == 'move': + source._xmluiSetValue('') + target._xmluiSetValue(value) + + def groups_of_contact(source, target): + """Select in target the groups of the contact which is selected in source.""" + assert(isinstance(source, ListWidget)) + assert(isinstance(target, ListWidget)) + try: + contact_jid_s = source._xmluiGetSelectedValues()[0] + except IndexError: + return + target._xmluiSelectValues(data[contact_jid_s]) + pass + + source = None + for field in fields: + widget = self.ctrl_list[field]['control'] + if not source: + source = widget + continue + if action in ('copy', 'move'): + copy_move(source, widget) + elif action == 'groups_of_contact': + groups_of_contact(source, widget) + source = None + + def getInternalCallbackData(self, action, node): + """Retrieve from node the data needed to perform given action. + + TODO: it would be better to not have a specific way to retrieve + data for each action, but instead to have a generic method to + extract any kind of data structure from the 'internal_data' element. + + @param action (string): a value from the one that can be passed to the + 'callback' parameter of sat.tools.xml_tools.Widget.setInternalCallback + @param node (DOM Element): the node of the widget that triggers the callback + """ + try: # data is stored in the first 'internal_data' element of the node + data_elts = node.getElementsByTagName('internal_data')[0].childNodes + except IndexError: + return None + data = {} + if action == 'groups_of_contact': # return a dict(key: string, value: list[string]) + for elt in data_elts: + jid_s = elt.getAttribute('name') + data[jid_s] = [] + for value_elt in elt.childNodes: + data[jid_s].append(value_elt.getAttribute('name')) + return data + def onFormSubmitted(self, ignore=None): """ An XMLUI form has been submited call the submit action associated with this form