Mercurial > libervia-backend
view frontends/src/primitivus/xmlui.py @ 297:c5554e2939dd
plugin XEP 0277: author for in request + author, updated management for out request
- a workaround is now used to parse "nick" tag (Jappix behaviour)
- author and updated can now be used in data when sendind microblog. Is no author is given, user jid is used, if no updated is given, current timestamp is used
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 18 Feb 2011 22:32:02 +0100 |
parents | b1794cbb88e5 |
children | cf005701624b |
line wrap: on
line source
#!/usr/bin/python # -*- coding: utf-8 -*- """ Primitivus: a SAT frontend Copyright (C) 2009, 2010, 2011 Jérôme Poisson (goffi@goffi.org) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. """ import urwid from urwid_satext import sat_widgets from logging import debug, info, warning, error from xml.dom import minidom class Pairs(urwid.WidgetWrap): def __init__(self, weight_0='1', weight_1='1'): self.idx = 0 self.weight_0 = weight_0 self.weight_1 = weight_1 columns = urwid.Columns([urwid.Text(''), urwid.Text('')]) #XXX: empty Text hack needed because Pile doesn't support empty list urwid.WidgetWrap.__init__(self,columns) def append(self, widget): pile = self._w.widget_list[self.idx] if isinstance(pile, urwid.Text): self._w.widget_list[self.idx] = urwid.Pile([widget]) if self.idx == 1: self._w.set_focus(1) else: pile.widget_list.append(widget) pile.item_types.append(('weight',getattr(self,'weight_'+str(self.idx)))) self.idx = (self.idx + 1) % 2 class InvalidXMLUI(Exception): pass class XMLUI(urwid.WidgetWrap): def __init__(self, host, xml_data, title = None, options = [], misc={}): self.host = host self.title = title self.options = options self.misc = misc self.__dest = "window" self.ctrl_list = {} # usefull to access ctrl widget = self.constructUI(xml_data) urwid.WidgetWrap.__init__(self,widget) def __parseElems(self, node, parent): """Parse elements inside a <layout> tags, and add them to the parent""" for elem in node.childNodes: if elem.nodeName != "elem": message=_("Unmanaged tag") error(message) raise Exception(message) 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 = urwid.Text('') elif type=="text": try: value = elem.childNodes[0].wholeText except IndexError: warning (_("text node has no child !")) ctrl = urwid.Text(value) elif type=="label": ctrl = urwid.Text(value+": ") elif type=="string": ctrl = sat_widgets.AdvancedEdit(edit_text = value) self.ctrl_list[name] = ({'type':type, 'control':ctrl}) elif type=="password": ctrl = sat_widgets.Password(edit_text = value) self.ctrl_list[name] = ({'type':type, 'control':ctrl}) elif type=="textbox": ctrl = sat_widgets.AdvancedEdit(edit_text = value, multiline=True) self.ctrl_list[name] = ({'type':type, 'control':ctrl}) elif type=="bool": ctrl = urwid.CheckBox('', state = value=="true") self.ctrl_list[name] = ({'type':type, 'control':ctrl}) elif type=="list": style=[] if elem.getAttribute("multi")=='yes' else ['single'] ctrl = sat_widgets.List(options=[option.getAttribute("value") for option in elem.getElementsByTagName("option")], style=style) self.ctrl_list[name] = ({'type':type, 'control':ctrl}) elif type=="button": callback_id = elem.getAttribute("callback_id") ctrl = sat_widgets.CustomButton(value, on_press=self.onButtonPress) ctrl.param_id = (callback_id,[field.getAttribute('name') for field in elem.getElementsByTagName("field_back")]) else: error(_("FIXME FIXME FIXME: type [%s] is not implemented") % type) #FIXME ! raise NotImplementedError if self.type == 'param': if isinstance(ctrl,urwid.Edit) or isinstance(ctrl,urwid.CheckBox): urwid.connect_signal(ctrl,'change',self.onParamChange) ctrl._param_category = self._current_category ctrl._param_name = name parent.append(ctrl) def __parseChilds(self, current, elem, wanted = ['layout'], data = None): """Recursively parse childNodes of an elemen @param current: widget container with 'append' method @param elem: 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""" for node in elem.childNodes: if wanted and not node.nodeName in wanted: raise InvalidXMLUI if node.nodeName == "layout": type = node.getAttribute('type') if type == "tabs": tab_cont = sat_widgets.TabsContainer() self.__parseChilds(current, node, ['category'], tab_cont) current.append(tab_cont) elif type == "vertical": self.__parseElems(node, current) elif type == "pairs": pairs = Pairs() self.__parseElems(node, pairs) current.append(pairs) else: warning(_("Unknown layout, using default one")) self.__parseElems(node, current) elif node.nodeName == "category": name = node.getAttribute('name') label = node.getAttribute('label') if not name or not isinstance(data,sat_widgets.TabsContainer): raise InvalidXMLUI if self.type == 'param': self._current_category = name #XXX: awful hack because params need category and we don't keep parent tab_cont = data listbox = tab_cont.addTab(label or name) self.__parseChilds(listbox.body, node, ['layout']) else: message=_("Unknown tag") error(message) raise NotImplementedError def constructUI(self, xml_data): ret_wid = urwid.ListBox(urwid.SimpleListWalker([])) cat_dom = minidom.parseString(xml_data.encode('utf-8')) top=cat_dom.documentElement self.type = top.getAttribute("type") self.title = top.getAttribute("title") or self.title if top.nodeName != "sat_xmlui" or not self.type in ['form', 'param', 'window']: raise InvalidXMLUI if self.type == 'param': self.param_changed = set() self.__parseChilds(ret_wid.body, cat_dom.documentElement) assert ret_wid.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 self.type == 'form': buttons = [] buttons.append(urwid.Button(_('Submit'),self.onFormSubmitted)) if not 'NO_CANCEL' in self.options: 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) elif self.type == 'param': assert(isinstance(ret_wid,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 def show(self,show_type = 'popup'): """Show the constructed UI @param show_type: how to show the UI: - popup - window""" self.__dest = "popup" decorated = sat_widgets.LabelLine(self, sat_widgets.SurroundedText(self.title or '')) if show_type == 'popup': self.host.showPopUp(decorated) elif show_type == 'window': self.host.addWindow(decorated) else: error(_('INTERNAL ERROR: Unmanaged show_type (%s)') % show_type) assert(False) self.host.redraw() ##EVENTS## def onButtonPress(self, button): callback_id, fields = button.param_id data = {"callback_id":callback_id} for field in fields: ctrl = self.ctrl_list[field] if isinstance(ctrl['control'],sat_widgets.List): data[field] = '\t'.join(ctrl['control'].getSelectedValues()) else: data[field] = ctrl['control'].getValue() id = self.host.bridge.launchAction("button", data, profile_key = self.host.profile) self.host.current_action_ids.add(id) def onParamChange(self, widget, extra=None): """Called when type is param and a widget to save is modified""" assert(self.type == "param") self.param_changed.add(widget) def onFormSubmitted(self, button): data = [] for ctrl_name in self.ctrl_list: ctrl = self.ctrl_list[ctrl_name] if isinstance(ctrl['control'], sat_widgets.List): data.append((ctrl_name, ctrl['control'].getSelectedValue())) elif isinstance(ctrl['control'], urwid.CheckBox): data.append((ctrl_name, "true" if ctrl['control'].get_state() else "false")) else: data.append((ctrl_name, ctrl['control'].get_edit_text())) if self.misc.has_key('action_back'): #FIXME FIXME FIXME: WTF ! Must be cleaned raise NotImplementedError self.host.debug() elif self.misc.has_key('callback'): self.misc['callback'](data) else: warning (_("The form data is not sent back, the type is not managed properly")) self.host.removePopUp() def onFormCancelled(self, button): if self.__dest == 'window': self.host.removeWindow() else: self.host.removePopUp() def onSaveParams(self, button): for ctrl in self.param_changed: if isinstance(ctrl, urwid.CheckBox): value = "true" if ctrl.get_state() else "false" else: value = ctrl.get_edit_text() self.host.bridge.setParam(ctrl._param_name, value, ctrl._param_category, profile_key = self.host.profile) self.host.removeWindow()