# HG changeset patch # User Goffi # Date 1391534340 -3600 # Node ID 9007bb1330097b9dbb792efdb66244703e9b9abe # Parent 02ee9ef952770ca12ffb2b10170fb0e609b9a3a4 core, frontends: XMLUI refactoring: - XMLUI now use objects with 2 main classes: widgets (button, label, etc), and container which contain widgets according to a layout - widgets and containers classes are found through introspection, thereby it's really easy to add a new one - there is still the AddWidgetName helper, for example AddText('jid', 'test@example.net') will add a StringWidget with name "jid" and default value "test@example.net" - container can be inside other containers. changeContainer change the first parent container diff -r 02ee9ef95277 -r 9007bb133009 frontends/src/primitivus/xmlui.py --- a/frontends/src/primitivus/xmlui.py Tue Feb 04 18:06:12 2014 +0100 +++ b/frontends/src/primitivus/xmlui.py Tue Feb 04 18:19:00 2014 +0100 @@ -103,12 +103,6 @@ return [option.value for option in self.getSelectedValues()] -class PrimitivusAdvancedListWidget(PrimitivusListWidget, PrimitivusEvents): - - def __init__(self, parent, options, flags): - sat_widgets.List.__init__(self, options=options, style=flags, max_height=20) - - class PrimitivusPairsContainer(xmlui.PairsContainer, urwid.WidgetWrap): def __init__(self, parent, weight_0='1', weight_1='1'): @@ -148,7 +142,6 @@ class PrimitivusVerticalContainer(xmlui.VerticalContainer, urwid.ListBox): - def __init__(self, parent): urwid.ListBox.__init__(self, urwid.SimpleListWalker([])) @@ -169,13 +162,14 @@ def __init__(self, host, xml_data, title = None, flags = None): self._dest = "window" xmlui.XMLUI.__init__(self, host, xml_data, title, flags) + urwid.WidgetWrap.__init__(self, self.main_cont) def constructUI(self, xml_data): - def postTreat(ret_wid): - assert ret_wid.body + def postTreat(): + assert self.main_cont.body - if isinstance(ret_wid.body[0],sat_widgets.TabsContainer): - ret_wid = ret_wid.body[0] #xxx: awfull hack cause TabsContainer is a BoxWidget, can't be inside a ListBox + if isinstance(self.main_cont.body[0],sat_widgets.TabsContainer): + self._main_cont = self.main_cont.body[0] #xxx: awfull hack cause TabsContainer is a BoxWidget, can't be inside a ListBox if self.type == 'form': buttons = [] @@ -184,19 +178,18 @@ buttons.append(urwid.Button(_('Cancel'),self.onFormCancelled)) max_len = max([len(button.get_label()) for button in buttons]) grid_wid = urwid.GridFlow(buttons,max_len+4,1,0,'center') - ret_wid.body.append(grid_wid) + self.main_cont.body.append(grid_wid) elif self.type == 'param': - assert(isinstance(ret_wid,sat_widgets.TabsContainer)) + assert(isinstance(self.main_cont,sat_widgets.TabsContainer)) buttons = [] buttons.append(sat_widgets.CustomButton(_('Save'),self.onSaveParams)) buttons.append(sat_widgets.CustomButton(_('Cancel'),lambda x:self.host.removeWindow())) max_len = max([button.getSize() for button in buttons]) grid_wid = urwid.GridFlow(buttons,max_len,1,0,'center') - ret_wid.addFooter(grid_wid) - return ret_wid + self.main_cont.addFooter(grid_wid) - widget = super(XMLUI, self).constructUI(xml_data, postTreat) - urwid.WidgetWrap.__init__(self, widget) + super(XMLUI, self).constructUI(xml_data, postTreat) + urwid.WidgetWrap.__init__(self, self.main_cont) def show(self, show_type='popup', valign='middle'): """Show the constructed UI diff -r 02ee9ef95277 -r 9007bb133009 frontends/src/tools/xmlui.py --- a/frontends/src/tools/xmlui.py Tue Feb 04 18:06:12 2014 +0100 +++ b/frontends/src/tools/xmlui.py Tue Feb 04 18:19:00 2014 +0100 @@ -89,9 +89,6 @@ """ A widget able to show/choose one or several strings in a list """ -class AdvancedListWidget(Widget): - pass #TODO - class Container(Widget): """ Widget which can contain other ones with a specific layout """ @@ -157,103 +154,60 @@ flags = [] self.flags = flags self.ctrl_list = {} # usefull to access ctrl + self._main_cont = None self.constructUI(xml_data) - def _parseElems(self, node, parent, post_treat=None): - """ Parse elements inside a tags, and add them to the parent - @param node: current XMLUI node - @param parent: parent container - @param post_treat: frontend specific treatments do to on each element + @property + def main_cont(self): + return self._main_cont - """ - for elem in node.childNodes: - if elem.nodeName != "elem": - raise NotImplementedError(_('Unknown tag [%s]') % elem.nodeName) - id_ = elem.getAttribute("id") - name = elem.getAttribute("name") - type_ = elem.getAttribute("type") - value = elem.getAttribute("value") if elem.hasAttribute('value') else u'' - if type_=="empty": - ctrl = self.widget_factory.createEmptyWidget(parent) - elif type_=="text": - try: - value = elem.childNodes[0].wholeText - except IndexError: - warning (_("text node has no child !")) - ctrl = self.widget_factory.createTextWidget(parent, value) - elif type_=="label": - ctrl = self.widget_factory.createTextWidget(parent, value+": ") - elif type_=="string": - ctrl = self.widget_factory.createStringWidget(parent, value) - self.ctrl_list[name] = ({'type':type_, 'control':ctrl}) - elif type_=="password": - ctrl = self.widget_factory.createPasswordWidget(parent, value) - self.ctrl_list[name] = ({'type':type_, 'control':ctrl}) - elif type_=="textbox": - ctrl = self.widget_factory.createTextBoxWidget(parent, value) - self.ctrl_list[name] = ({'type':type_, 'control':ctrl}) - elif type_=="bool": - ctrl = self.widget_factory.createBoolWidget(parent, value=='true') - self.ctrl_list[name] = ({'type':type_, 'control':ctrl}) - elif type_=="list": - style=[] if elem.getAttribute("multi")=='yes' else ['single'] - _options = [(option.getAttribute("value"), option.getAttribute("label")) for option in elem.getElementsByTagName("option")] - ctrl = self.widget_factory.createListWidget(parent, _options, style) - ctrl._xmluiSelectValue(elem.getAttribute("value")) - self.ctrl_list[name] = ({'type':type_, 'control':ctrl}) - elif type_=="button": - callback_id = elem.getAttribute("callback") - ctrl = self.widget_factory.createButtonWidget(parent, value, self.onButtonPress) - ctrl._xmlui_param_id = (callback_id,[field.getAttribute('name') for field in elem.getElementsByTagName("field_back")]) - elif type_=="advanced_list": - _options = [getText(txt_elt) for txt_elt in elem.getElementsByTagName("text")] - ctrl = self.widget_factory.createListWidget(parent, _options, ['can_select_none']) - ctrl._xmluiSelectValue(elem.getAttribute("value")) - self.ctrl_list[name] = ({'type':type_, 'control':ctrl}) - else: - error(_("FIXME FIXME FIXME: type [%s] is not implemented") % type_) - raise NotImplementedError(_("FIXME FIXME FIXME: type [%s] is not implemented") % type_) + @main_cont.setter + def main_cont(self, value): + if self._main_cont is not None: + raise ValueError(_("XMLUI can have only one main container")) + self._main_cont = value - if self.type == 'param': - try: - ctrl._xmluiOnChange(self.onParamChange) - ctrl._param_category = self._current_category - ctrl._param_name = name.split(Const.SAT_PARAM_SEPARATOR)[1] - except AttributeError: - if not isinstance(ctrl, (EmptyWidget, TextWidget)): - warning(_("No change listener on [%s]" % ctrl)) - if post_treat is not None: - post_treat(ctrl, id_, name, type_, value) - parent._xmluiAppend(ctrl) - - def _parseChilds(self, current, elem, wanted = ['layout'], data = None): + def _parseChilds(self, parent, current_node, wanted = ('container',), data = None): """ Recursively parse childNodes of an elemen - @param current: widget container with '_xmluiAppend' method - @param elem: element from which childs will be parsed + @param parent: widget container with '_xmluiAppend' method + @param current_node: element from which childs will be parsed @param wanted: list of tag names that can be present in the childs to be SàT XMLUI compliant @param data: additionnal data which are needed in some cases """ - for node in elem.childNodes: + for node in current_node.childNodes: if wanted and not node.nodeName in wanted: raise InvalidXMLUI - if node.nodeName == "layout": + + if node.nodeName == "container": type_ = node.getAttribute('type') + if parent is self and type_ != 'vertical': + # main container is not a VerticalContainer and we want one, so we create one to wrap it + parent = self.widget_factory.createVerticalContainer(self) + self.main_cont = parent if type_ == "tabs": - tab_cont = self.widget_factory.createTabsContainer(current) - self._parseChilds(current, node, ['category'], tab_cont) - current._xmluiAppend(tab_cont) + cont = self.widget_factory.createTabsContainer(parent) + self._parseChilds(parent, node, ('tab',), cont) elif type_ == "vertical": - self._parseElems(node, current) + cont = self.widget_factory.createVerticalContainer(parent) + self._parseChilds(cont, node, ('widget', 'container')) elif type_ == "pairs": - pairs = self.widget_factory.createPairsContainer(current) - self._parseElems(node, pairs) - current._xmluiAppend(pairs) + cont = self.widget_factory.createPairsContainer(parent) + self._parseChilds(cont, node, ('widget', 'container')) else: - warning(_("Unknown layout [%s], using default one") % type_) - self._parseElems(node, current) - elif node.nodeName == "category": + warning(_("Unknown container [%s], using default one") % type_) + cont = self.widget_factory.createVerticalContainer(parent) + self._parseChilds(cont, node, ('widget', 'container')) + try: + parent._xmluiAppend(cont) + except AttributeError: + if parent is self: + self.main_cont = cont + else: + raise Exception(_("Internal Error, container has not _xmluiAppend method")) + + elif node.nodeName == "tab": name = node.getAttribute('name') label = node.getAttribute('label') if not name or not isinstance(data, TabsContainer): @@ -262,9 +216,62 @@ self._current_category = name #XXX: awful hack because params need category and we don't keep parent tab_cont = data new_tab = tab_cont._xmluiAddTab(label or name) - self._parseChilds(new_tab, node, ['layout']) + self._parseChilds(new_tab, node, ('widget', 'container')) + + elif node.nodeName == "widget": + id_ = node.getAttribute("id") + name = node.getAttribute("name") + type_ = node.getAttribute("type") + value = node.getAttribute("value") if node.hasAttribute('value') else u'' + if type_=="empty": + ctrl = self.widget_factory.createEmptyWidget(parent) + elif type_=="text": + try: + value = node.childNodes[0].wholeText + except IndexError: + warning (_("text node has no child !")) + ctrl = self.widget_factory.createTextWidget(parent, value) + elif type_=="label": + ctrl = self.widget_factory.createTextWidget(parent, value+": ") + elif type_=="string": + ctrl = self.widget_factory.createStringWidget(parent, value) + self.ctrl_list[name] = ({'type':type_, 'control':ctrl}) + elif type_=="password": + ctrl = self.widget_factory.createPasswordWidget(parent, value) + self.ctrl_list[name] = ({'type':type_, 'control':ctrl}) + elif type_=="textbox": + ctrl = self.widget_factory.createTextBoxWidget(parent, value) + self.ctrl_list[name] = ({'type':type_, 'control':ctrl}) + elif type_=="bool": + ctrl = self.widget_factory.createBoolWidget(parent, value=='true') + self.ctrl_list[name] = ({'type':type_, 'control':ctrl}) + elif type_=="list": + style=[] if node.getAttribute("multi")=='yes' else ['single'] + _options = [(option.getAttribute("value"), option.getAttribute("label")) for option in node.getElementsByTagName("option")] + ctrl = self.widget_factory.createListWidget(parent, _options, style) + ctrl._xmluiSelectValue(node.getAttribute("value")) + self.ctrl_list[name] = ({'type':type_, 'control':ctrl}) + elif type_=="button": + callback_id = node.getAttribute("callback") + ctrl = self.widget_factory.createButtonWidget(parent, value, self.onButtonPress) + ctrl._xmlui_param_id = (callback_id,[field.getAttribute('name') for field in node.getElementsByTagName("field_back")]) + else: + error(_("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': + try: + ctrl._xmluiOnChange(self.onParamChange) + ctrl._param_category = self._current_category + ctrl._param_name = name.split(Const.SAT_PARAM_SEPARATOR)[1] + except AttributeError: + if not isinstance(ctrl, (EmptyWidget, TextWidget)): + warning(_("No change listener on [%s]" % ctrl)) + + parent._xmluiAppend(ctrl) + else: - raise NotImplementedError(_('Unknown tag')) + raise NotImplementedError(_('Unknown tag [%s]') % node.nodeName) def constructUI(self, xml_data, post_treat=None): """ Actually construct the UI @@ -272,8 +279,6 @@ @param post_treat: frontend specific treatments to do once the UI is constructed @return: constructed widget """ - ret_wid = self.widget_factory.createVerticalContainer(self) - cat_dom = self.dom_parse(xml_data) top=cat_dom.documentElement self.type = top.getAttribute("type") @@ -286,16 +291,13 @@ if self.type == 'param': self.param_changed = set() - self._parseChilds(ret_wid, cat_dom.documentElement) + self._parseChilds(self, cat_dom.documentElement) if post_treat is not None: - ret_wid = post_treat(ret_wid) + post_treat() self.dom_free(cat_dom) - return ret_wid - - def _xmluiClose(self): """ Close the window/popup/... where the constructeur XMLUI is this method must be overrided diff -r 02ee9ef95277 -r 9007bb133009 frontends/src/wix/main_window.py --- a/frontends/src/wix/main_window.py Tue Feb 04 18:06:12 2014 +0100 +++ b/frontends/src/wix/main_window.py Tue Feb 04 18:19:00 2014 +0100 @@ -160,7 +160,7 @@ help_string = self.bridge.getMenuHelp(id_, '') current_menu.Append(item_id, name, help=help_string) #now we register the event - def event_answer(e): + def event_answer(e, id_=id_): self.launchAction(id_, None, profile_key = self.profile) wx.EVT_MENU(self, item_id, event_answer) diff -r 02ee9ef95277 -r 9007bb133009 frontends/src/wix/xmlui.py --- a/frontends/src/wix/xmlui.py Tue Feb 04 18:06:12 2014 +0100 +++ b/frontends/src/wix/xmlui.py Tue Feb 04 18:19:00 2014 +0100 @@ -131,13 +131,6 @@ return ret -class AdvancedListWidget(ListWidget): - #TODO - - def __init__(self, parent, options, flags): - super(ListWidget, self).__init__(parent, options, flags) - - class WixContainer(object): _xmlui_proportion = 1 @@ -185,7 +178,7 @@ return cls -class XMLUI(xmlui.XMLUI, wx.Frame, WixContainer): +class XMLUI(xmlui.XMLUI, wx.Frame): """Create an user interface from a SàT XML""" widget_factory = WidgetFactory() @@ -199,26 +192,25 @@ self.sizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(self.sizer) - def postTreat(ret_wid): + def postTreat(): if self.title: self.SetTitle(self.title) if self.type == 'form': dialogButtons = wx.StdDialogButtonSizer() - submitButton = wx.Button(ret_wid,wx.ID_OK, label=_("Submit")) + submitButton = wx.Button(self.main_cont,wx.ID_OK, label=_("Submit")) dialogButtons.AddButton(submitButton) - ret_wid.Bind(wx.EVT_BUTTON, self.onFormSubmitted, submitButton) + self.main_cont.Bind(wx.EVT_BUTTON, self.onFormSubmitted, submitButton) if not 'NO_CANCEL' in self.flags: - cancelButton = wx.Button(ret_wid,wx.ID_CANCEL) + cancelButton = wx.Button(self.main_cont,wx.ID_CANCEL) dialogButtons.AddButton(cancelButton) - ret_wid.Bind(wx.EVT_BUTTON, self.onFormCancelled, cancelButton) + self.main_cont.Bind(wx.EVT_BUTTON, self.onFormCancelled, cancelButton) dialogButtons.Realize() - ret_wid.sizer.Add(dialogButtons, flag=wx.ALIGN_CENTER_HORIZONTAL) + self.main_cont.sizer.Add(dialogButtons, flag=wx.ALIGN_CENTER_HORIZONTAL) - self._xmluiAppend(ret_wid) + self.sizer.Add(self.main_cont, 1, flag=wx.EXPAND) self.sizer.Fit(self) self.Show() - return ret_wid super(XMLUI, self).constructUI(xml_data, postTreat) if not 'NO_CANCEL' in self.flags: @@ -251,5 +243,7 @@ debug(_("close")) if self.type == 'param': self.onSaveParams() + else: + self._xmluiClose() event.Skip() diff -r 02ee9ef95277 -r 9007bb133009 src/memory/memory.py --- a/src/memory/memory.py Tue Feb 04 18:06:12 2014 +0100 +++ b/src/memory/memory.py Tue Feb 04 18:19:00 2014 +0100 @@ -29,7 +29,7 @@ from twisted.internet import defer, reactor from twisted.words.protocols.jabber import jid from twisted.python.failure import Failure -from sat.tools.xml_tools import paramsXml2xmlUI +from sat.tools.xml_tools import paramsXML2XMLUI from sat.core.default_config import default_config from sat.memory.sqlite import SqliteStorage from sat.memory.persistent import PersistentDict @@ -130,7 +130,7 @@ - + @@ -621,7 +621,7 @@ error(_("Asking params for inexistant profile")) return "" d = self.getParams(security_limit, app, profile) - return d.addCallback(lambda param_xml: paramsXml2xmlUI(param_xml)) + return d.addCallback(lambda param_xml: paramsXML2XMLUI(param_xml)) def getParams(self, security_limit, app, profile_key): """Construct xml for asked profile, take params xml as skeleton diff -r 02ee9ef95277 -r 9007bb133009 src/plugins/plugin_xep_0050.py --- a/src/plugins/plugin_xep_0050.py Tue Feb 04 18:06:12 2014 +0100 +++ b/src/plugins/plugin_xep_0050.py Tue Feb 04 18:19:00 2014 +0100 @@ -234,7 +234,7 @@ form_ui.addText(_("Please select a command"), 'instructions') options = [(item.nodeIdentifier, item.name) for item in items] - form_ui.addList(options, "node") + form_ui.addList("node", options) return form_ui def _commandsAnswer2XMLUI(self, iq_elt, session_id, session_data): @@ -329,7 +329,7 @@ """ form_ui = xml_tools.XMLUI("form", submit_id=self.__requesting_id) form_ui.addText(_("Please enter target jid"), 'instructions') - form_ui.changeLayout("pairs") + form_ui.changeContainer("pairs") form_ui.addLabel("jid") form_ui.addString("jid") return {'xmlui': form_ui.toXml()} diff -r 02ee9ef95277 -r 9007bb133009 src/plugins/plugin_xep_0055.py --- a/src/plugins/plugin_xep_0055.py Tue Feb 04 18:06:12 2014 +0100 +++ b/src/plugins/plugin_xep_0055.py Tue Feb 04 18:19:00 2014 +0100 @@ -75,7 +75,7 @@ """ form_ui = xml_tools.XMLUI("form", title=_("Search directory"), submit_id=self.__menu_cb_id) form_ui.addText(_("Please enter the search jid"), 'instructions') - form_ui.changeLayout("pairs") + form_ui.changeContainer("pairs") form_ui.addLabel("jid") form_ui.addString("jid", value="users.jabberfr.org") # TODO: replace users.jabberfr.org by any XEP-0055 compatible service discovered on current server return {'xmlui': form_ui.toXml()} diff -r 02ee9ef95277 -r 9007bb133009 src/tools/xml_tools.py --- a/src/tools/xml_tools.py Tue Feb 04 18:06:12 2014 +0100 +++ b/src/tools/xml_tools.py Tue Feb 04 18:19:00 2014 +0100 @@ -29,9 +29,47 @@ SAT_FORM_PREFIX = "SAT_FORM_" SAT_PARAM_SEPARATOR = "_XMLUI_PARAM_" # used to have unique elements names + +# Helper functions + +def _dataFormField2XMLUIData(field): + """ Get data needed to create an XMLUI's Widget from Wokkel's data_form's Field + @param field: data_form.Field (it uses field.value, field.fieldType, field.label and field.var) + @return: widget_type, widget_args, widget_kwargs + + """ + widget_args = [field.value] + widget_kwargs = {} + if field.fieldType == 'fixed' or field.fieldType is None: + widget_type = 'text' + elif field.fieldType == 'text-single': + widget_type = "string" + elif field.fieldType == 'text-private': + widget_type = "password" + elif field.fieldType == 'boolean': + widget_type = "bool" + if widget_args[0] is None: + widget_args[0] = 'false' + elif field.fieldType == 'list-single': + widget_type = "list" + del widget_args[0] + widget_kwargs["options"] = [option.value for option in field.options] + else: + error(u"FIXME FIXME FIXME: Type [%s] is not managed yet by SàT" % field.fieldType) + widget_type = "string" + + if field.var: + widget_kwargs["name"] = field.var + + return widget_type, widget_args, widget_kwargs + + def dataForm2XMLUI(form, submit_id, session_id=None): - """Take a data form (xep-0004, Wokkel's implementation) and convert it to a SàT xml""" + """Take a data form (xep-0004, Wokkel's implementation) and convert it to a SàT XML + @param submit_id: callback id to call when submitting form + @param session_id: id to return with the data + """ form_ui = XMLUI("form", "vertical", submit_id=submit_id, session_id=session_id) if form.instructions: @@ -40,32 +78,18 @@ labels = [field for field in form.fieldList if field.label] if labels: # if there is no label, we don't need to use pairs - form_ui.changeLayout("pairs") + form_ui.changeContainer("pairs") for field in form.fieldList: - if field.fieldType == 'fixed': - __field_type = 'text' - elif field.fieldType == 'text-single': - __field_type = "string" - elif field.fieldType == 'text-private': - __field_type = "password" - elif field.fieldType == 'boolean': - __field_type = "bool" - if field.value is None: - field.value = "false" - elif field.fieldType == 'list-single': - __field_type = "list" - else: - error(u"FIXME FIXME FIXME: Type [%s] is not managed yet by SàT" % field.fieldType) - __field_type = "string" - + widget_type, widget_args, widget_kwargs = _dataFormField2XMLUIData(field) if labels: if field.label: form_ui.addLabel(field.label) else: form_ui.addEmpty() - form_ui.addElement(__field_type, field.var, field.value, [option.value for option in field.options]) + form_ui.addWidget(widget_type, *widget_args, **widget_kwargs) + return form_ui def dataFormResult2AdvancedList(form_ui, form_xml): @@ -75,8 +99,7 @@ @param form_xml: domish.Element of the data form @return: AdvancedList element """ - headers = [] - items = [] + headers = {} try: reported_elt = form_xml.elements('jabber:x:data', 'reported').next() except StopIteration: @@ -87,30 +110,28 @@ raise exceptions.DataError("Unexpected tag") name = elt["var"] label = elt.attributes.get('label','') - type_ = elt.attributes.get('type','') # TODO - headers.append(Header(name, label)) + type_ = elt.attributes.get('type') + headers[name] = (label, type_) if not headers: raise exceptions.DataError("No reported fields (see XEP-0004 §3.4)") + adv_list = AdvancedListContainer(form_ui, headers=headers, columns=len(headers), parent=form_ui.current_container) + form_ui.changeContainer(adv_list) + item_elts = form_xml.elements('jabber:x:data', 'item') for item_elt in item_elts: - fields = [] for elt in item_elt.elements(): if elt.name != 'field': warning("Unexpected tag (%s)" % elt.name) continue - name = elt['var'] - child_elt = elt.firstChildElement() - if child_elt.name != "value": - raise exceptions.DataError('Was expecting tag') - value = unicode(child_elt) - fields.append(Field(name, value)) - items.append(Item(' | '.join((field.value for field in fields if field)), fields)) + field = data_form.Field.fromElement(elt) - return form_ui.addAdvancedList(None, headers, items) + widget_type, widget_args, widget_kwargs = _dataFormField2XMLUIData(field) + form_ui.addWidget(widget_type, *widget_args, **widget_kwargs) + return form_ui def dataFormResult2XMLUI(form_xml, session_id=None): """Take a raw data form (not parsed by XEP-0004) and convert it to a SàT XMLUI @@ -147,41 +168,57 @@ return form -def paramsXml2xmlUI(xml): +def paramsXML2XMLUI(xml): """Convert the xml for parameter to a SàT XML User Interface""" params_doc = minidom.parseString(xml.encode('utf-8')) top = params_doc.documentElement if top.nodeName != 'params': - error(_('INTERNAL ERROR: parameters xml not valid')) - assert(False) + raise exceptions.DataError(_('INTERNAL ERROR: parameters xml not valid')) + param_ui = XMLUI("param", "tabs") + tabs_cont = param_ui.current_container + for category in top.getElementsByTagName("category"): category_name = category.getAttribute('name') label = category.getAttribute('label') if not category_name: - error(_('INTERNAL ERROR: params categories must have a name')) - assert(False) - param_ui.addCategory(category_name, 'pairs', label=label) + raise exceptions.DataError(_('INTERNAL ERROR: params categories must have a name')) + tabs_cont.addTab(category_name, label=label, container=PairsContainer) for param in category.getElementsByTagName("param"): + widget_kwargs = {} + param_name = param.getAttribute('name') - label = param.getAttribute('label') + param_label = param.getAttribute('label') if not param_name: - error(_('INTERNAL ERROR: params must have a name')) - assert(False) + raise exceptions.DataError(_('INTERNAL ERROR: params must have a name')) + type_ = param.getAttribute('type') value = param.getAttribute('value') or None - options = getOptions(param) callback_id = param.getAttribute('callback_id') or None + + if type_ == 'list': + options = _getParamListOptions(param) + widget_kwargs['options'] = options + if type_ == "button": param_ui.addEmpty() else: - param_ui.addLabel(label or param_name) - param_ui.addElement(name="%s%s%s" % (category_name, SAT_PARAM_SEPARATOR, param_name), type_=type_, value=value, options=options, callback_id=callback_id) + param_ui.addLabel(param_label or param_name) + + if value: + widget_kwargs["value"] = value + + if callback_id: + widget_kwargs['callback_id'] = callback_id + + widget_kwargs['name'] = "%s%s%s" % (category_name, SAT_PARAM_SEPARATOR, param_name) + + param_ui.addWidget(type_, **widget_kwargs) return param_ui.toXml() -def getOptions(param): +def _getParamListOptions(param): """Retrieve the options for list element. Allow listing the