# HG changeset patch # User Goffi # Date 1391534369 -3600 # Node ID f100fd8d279f26d4c1fa5bee8615e900e89c2973 # Parent 9007bb1330097b9dbb792efdb66244703e9b9abe core, frontends: implementation of AdvancedListContainer first draft + misc: /!\ Urwid SàText must be updated as the new TableContainer is used /!\ - fixed button value in paramsXML2XMLUI - new Urwid SàText TabContainer is used in Primitivus for PairsContainer and AdvancedListContainer - fixed in core's XMLUI AdvanceListContainer diff -r 9007bb133009 -r f100fd8d279f frontends/src/primitivus/constants.py --- a/frontends/src/primitivus/constants.py Tue Feb 04 18:19:00 2014 +0100 +++ b/frontends/src/primitivus/constants.py Tue Feb 04 18:19:29 2014 +0100 @@ -69,6 +69,8 @@ ('show_xa_focus', 'dark red, bold', 'default'), ('status', 'yellow', 'default'), ('status_focus', 'yellow, bold', 'default'), + ('param_selected','default, bold', 'dark red'), + ('table_selected','default, bold', 'default'), ] PRESENCE = {"unavailable": (u'⨯', "show_disconnected"), "": (u'✔', "show_normal"), diff -r 9007bb133009 -r f100fd8d279f frontends/src/primitivus/xmlui.py --- a/frontends/src/primitivus/xmlui.py Tue Feb 04 18:19:00 2014 +0100 +++ b/frontends/src/primitivus/xmlui.py Tue Feb 04 18:19:29 2014 +0100 @@ -103,25 +103,31 @@ return [option.value for option in self.getSelectedValues()] -class PrimitivusPairsContainer(xmlui.PairsContainer, urwid.WidgetWrap): +class PrimitivusAdvancedListContainer(xmlui.AdvancedListContainer, sat_widgets.TableContainer): - def __init__(self, parent, 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 __init__(self, parent, columns): + options = {'ADAPT':(), 'HIGHLIGHT':()} + sat_widgets.TableContainer.__init__(self, columns=columns, options=options) def _xmluiAppend(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.contents.append((widget,('weight',getattr(self,'weight_'+str(self.idx))))) - self.idx = (self.idx + 1) % 2 + self.addWidget(widget) + + def _xmluiAddRow(self): + pass + +class PrimitivusPairsContainer(xmlui.PairsContainer, sat_widgets.TableContainer): + + def __init__(self, parent): + options = {'ADAPT':(0,), 'HIGHLIGHT':(0,)} + if self._xmlui_main.type == 'param': + options['FOCUS_ATTR'] = 'param_selected' + sat_widgets.TableContainer.__init__(self, columns=2, options=options) + + def _xmluiAppend(self, widget): + if isinstance(widget, PrimitivusEmptyWidget): + # we don't want highlight on empty widgets + widget = urwid.AttrMap(widget, 'default') + self.addWidget(widget) class PrimitivusTabsContainer(xmlui.TabsContainer, sat_widgets.TabsContainer): @@ -153,13 +159,15 @@ def __getattr__(self, attr): if attr.startswith("create"): - return globals()["Primitivus" + attr[6:]] # XXX: we prefix with "Primitivus" to work around an Urwid bug, WidgetMeta in Urwid don't manage multiple inheritance with same names - + cls = globals()["Primitivus" + attr[6:]] # XXX: we prefix with "Primitivus" to work around an Urwid bug, WidgetMeta in Urwid don't manage multiple inheritance with same names + cls._xmlui_main = self._xmlui_main + return cls class XMLUI(xmlui.XMLUI, urwid.WidgetWrap): widget_factory = WidgetFactory() def __init__(self, host, xml_data, title = None, flags = None): + self.widget_factory._xmlui_main = self self._dest = "window" xmlui.XMLUI.__init__(self, host, xml_data, title, flags) urwid.WidgetWrap.__init__(self, self.main_cont) diff -r 9007bb133009 -r f100fd8d279f frontends/src/tools/xmlui.py --- a/frontends/src/tools/xmlui.py Tue Feb 04 18:19:00 2014 +0100 +++ b/frontends/src/tools/xmlui.py Tue Feb 04 18:19:29 2014 +0100 @@ -120,6 +120,10 @@ pass +class AdvancedListContainer(Container): + """ Widgets are disposed in rows with advaned features """ + pass + class XMLUI(object): """ Base class to construct SàT XML User Interface New frontends can inherite this class to easily implement XMLUI @@ -178,7 +182,7 @@ """ for node in current_node.childNodes: if wanted and not node.nodeName in wanted: - raise InvalidXMLUI + raise InvalidXMLUI('Unexpected node: [%s]' % node.nodeName) if node.nodeName == "container": type_ = node.getAttribute('type') @@ -195,6 +199,13 @@ elif type_ == "pairs": cont = self.widget_factory.createPairsContainer(parent) self._parseChilds(cont, node, ('widget', 'container')) + elif type_ == "advanced_list": + try: + columns = int(node.getAttribute('columns')) + except (TypeError, ValueError): + raise DataError("Invalid columns") + cont = self.widget_factory.createAdvancedListContainer(parent, columns) + self._parseChilds(cont, node, ('row',)) else: warning(_("Unknown container [%s], using default one") % type_) cont = self.widget_factory.createVerticalContainer(parent) @@ -207,7 +218,7 @@ else: raise Exception(_("Internal Error, container has not _xmluiAppend method")) - elif node.nodeName == "tab": + elif node.nodeName == 'tab': name = node.getAttribute('name') label = node.getAttribute('label') if not name or not isinstance(data, TabsContainer): @@ -218,6 +229,10 @@ new_tab = tab_cont._xmluiAddTab(label or name) self._parseChilds(new_tab, node, ('widget', 'container')) + elif node.nodeName == 'row': + parent._xmluiAddRow() + self._parseChilds(parent, node, ('widget', 'container')) + elif node.nodeName == "widget": id_ = node.getAttribute("id") name = node.getAttribute("name") diff -r 9007bb133009 -r f100fd8d279f frontends/src/wix/xmlui.py --- a/frontends/src/wix/xmlui.py Tue Feb 04 18:19:00 2014 +0100 +++ b/frontends/src/wix/xmlui.py Tue Feb 04 18:19:29 2014 +0100 @@ -138,9 +138,20 @@ self.sizer.Add(widget, self._xmlui_proportion, flag=wx.EXPAND) +class AdvancedListContainer(WixContainer, xmlui.AdvancedListContainer, wx.Panel): + + def __init__(self, parent, columns): + wx.Panel.__init__(self, parent) + self.sizer = wx.FlexGridSizer(cols=columns) + self.SetSizer(self.sizer) + + def _xmluiAddRow(self): + pass + + class PairsContainer(WixContainer, xmlui.PairsContainer, wx.Panel): - def __init__(self, parent, weight_0='1', weight_1='1'): + def __init__(self, parent): wx.Panel.__init__(self, parent) self.sizer = wx.FlexGridSizer(cols=2) self.sizer.AddGrowableCol(1) #The growable column need most of time to be the right one in pairs diff -r 9007bb133009 -r f100fd8d279f src/tools/xml_tools.py --- a/src/tools/xml_tools.py Tue Feb 04 18:19:00 2014 +0100 +++ b/src/tools/xml_tools.py Tue Feb 04 18:19:29 2014 +0100 @@ -92,10 +92,10 @@ return form_ui -def dataFormResult2AdvancedList(form_ui, form_xml): +def dataFormResult2AdvancedList(xmlui, form_xml): """Take a raw data form (not parsed by XEP-0004) and convert it to an advanced list raw data form is used because Wokkel doesn't manage result items parsing yet - @param form_ui: the XMLUI where the AdvancedList will be added + @param xmlui: the XMLUI where the AdvancedList will be added @param form_xml: domish.Element of the data form @return: AdvancedList element """ @@ -116,8 +116,8 @@ 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) + adv_list = AdvancedListContainer(xmlui, headers=headers, columns=len(headers), parent=xmlui.current_container) + xmlui.changeContainer(adv_list) item_elts = form_xml.elements('jabber:x:data', 'item') @@ -129,9 +129,9 @@ field = data_form.Field.fromElement(elt) widget_type, widget_args, widget_kwargs = _dataFormField2XMLUIData(field) - form_ui.addWidget(widget_type, *widget_args, **widget_kwargs) + xmlui.addWidget(widget_type, *widget_args, **widget_kwargs) - return form_ui + return xmlui 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 @@ -140,9 +140,9 @@ @return: XMLUI interface """ - form_ui = XMLUI("window", "vertical", session_id=session_id) - dataFormResult2AdvancedList(form_ui, form_xml) - return form_ui + xmlui = XMLUI("window", "vertical", session_id=session_id) + dataFormResult2AdvancedList(xmlui, form_xml) + return xmlui def XMLUIResult2DataFormResult(xmlui_data): """ Extract form data from a XMLUI return @@ -202,6 +202,7 @@ if type_ == "button": param_ui.addEmpty() + value = param_label else: param_ui.addLabel(param_label or param_name) @@ -249,8 +250,7 @@ self.xmlui = xmlui if parent is not None: parent.append(self) - else: - self.parent = parent + self.parent = parent def append(self, child): self.elem.appendChild(child.elem) @@ -409,7 +409,7 @@ if columns is None: columns = len(items[0]) self._columns = columns - self._current_column = 0 + self._item_idx = 0 self.current_row = None if headers: if len(headers) != self._columns: @@ -417,6 +417,7 @@ self.addHeaders(headers) if items: self.addItems(items) + self.elem.setAttribute('columns', str(self._columns)) def addHeaders(self, headers): for header in headers: @@ -427,12 +428,15 @@ def addItems(self, items): for item in items: - self.addItem(item) + self.append(item) - def addItem(self, item): - if self._current_column % self._columns == 0: + def append(self, child): + if isinstance(child, RowElement): + return super(AdvancedListContainer, self).append(child) + if self._item_idx % self._columns == 0: self.current_row = RowElement(self) - self.current_row.append(item) + self.current_row.append(child) + self._item_idx += 1 def end(self): """ Called when we have finished list