tools, frontends, memory: param definition and XMLUI handle multi-selection for list widgets:
- we need to update urwid_satext to revision 79
- no more "value" attribute value in the "list" element, use
HTML-style "select" attribute in the "option" elements instead
- /!\ param saving do not handle multiple values yet!
This commit is contained in:
parent
8fa0b7b8c2
commit
608e2ba9fa
8 changed files with 82 additions and 39 deletions
|
|
@ -102,13 +102,13 @@ class PrimitivusTextBoxWidget(xmlui.TextBoxWidget, sat_widgets.AdvancedEdit, Pri
|
|||
sat_widgets.AdvancedEdit.__init__(self, edit_text=value, multiline=True)
|
||||
|
||||
def _xmluiGetValue(self):
|
||||
return self.getValue()
|
||||
return self.get_edit_text()
|
||||
|
||||
|
||||
class PrimitivusBoolWidget(xmlui.BoolWidget, urwid.CheckBox, PrimitivusEvents):
|
||||
|
||||
def __init__(self, parent, state):
|
||||
urwid.CheckBox.__init__(self, '', state = state)
|
||||
urwid.CheckBox.__init__(self, '', state=state)
|
||||
|
||||
def _xmluiGetValue(self):
|
||||
return "true" if self.get_state() else "false"
|
||||
|
|
@ -122,12 +122,16 @@ class PrimitivusButtonWidget(xmlui.ButtonWidget, sat_widgets.CustomButton, Primi
|
|||
|
||||
class PrimitivusListWidget(xmlui.ListWidget, sat_widgets.List, PrimitivusEvents):
|
||||
|
||||
def __init__(self, parent, options, flags):
|
||||
def __init__(self, parent, options, selected, flags):
|
||||
sat_widgets.List.__init__(self, options=options, style=flags)
|
||||
self._xmluiSelectValues(selected)
|
||||
|
||||
def _xmluiSelectValue(self, value):
|
||||
return self.selectValue(value)
|
||||
|
||||
def _xmluiSelectValues(self, values):
|
||||
return self.selectValues(values)
|
||||
|
||||
def _xmluiGetSelectedValues(self):
|
||||
return [option.value for option in self.getSelectedValues()]
|
||||
|
||||
|
|
|
|||
|
|
@ -301,16 +301,16 @@ class XMLUI(object):
|
|||
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']
|
||||
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})
|
||||
_selected = [option.getAttribute("value") for option in node.getElementsByTagName("option") if option.getAttribute('selected') == 'true']
|
||||
ctrl = self.widget_factory.createListWidget(parent, _options, _selected, style)
|
||||
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")])
|
||||
ctrl._xmlui_param_id = (callback_id, [field.getAttribute('name') for field in node.getElementsByTagName("field_back")])
|
||||
else:
|
||||
print(_("FIXME FIXME FIXME: widget type [%s] is not implemented") % type_)
|
||||
raise NotImplementedError(_("FIXME FIXME FIXME: type [%s] is not implemented") % type_)
|
||||
|
|
@ -408,7 +408,7 @@ class XMLUI(object):
|
|||
escaped = self.escape(field)
|
||||
ctrl = self.ctrl_list[field]
|
||||
if isinstance(ctrl['control'], ListWidget):
|
||||
data[escaped] = u'\t'.join(ctrl['control']._xmluiGetSelected())
|
||||
data[escaped] = u'\t'.join(ctrl['control']._xmluiGetSelectedValues())
|
||||
else:
|
||||
data[escaped] = ctrl['control']._xmluiGetValue()
|
||||
self._xmluiLaunchAction(callback_id, data)
|
||||
|
|
|
|||
|
|
@ -122,14 +122,16 @@ class ButtonWidget(EventWidget, WixWidget, xmlui.ButtonWidget, wx.Button):
|
|||
self._xmlui_click_callback(event.GetEventObject())
|
||||
event.Skip()
|
||||
|
||||
|
||||
class ListWidget(EventWidget, WixWidget, xmlui.ListWidget, wx.ListBox):
|
||||
_xmlui_change_event = wx.EVT_LISTBOX
|
||||
|
||||
def __init__(self, parent, options, flags):
|
||||
def __init__(self, parent, options, selected, flags):
|
||||
styles = wx.LB_MULTIPLE if not 'single' in flags else wx.LB_SINGLE
|
||||
wx.ListBox.__init__(self, parent, -1, choices=[option[1] for option in options], style=styles)
|
||||
self._xmlui_attr_map = {label: value for value, label in options}
|
||||
self._xmlui_proportion = 1
|
||||
self._xmluiSelectValues(selected)
|
||||
|
||||
def _xmluiSelectValue(self, value):
|
||||
try:
|
||||
|
|
@ -140,6 +142,10 @@ class ListWidget(EventWidget, WixWidget, xmlui.ListWidget, wx.ListBox):
|
|||
for idx in xrange(self.GetCount()):
|
||||
self.SetSelection(idx, self.GetString(idx) == label)
|
||||
|
||||
def _xmluiSelectValues(self, values):
|
||||
for value in values:
|
||||
self._xmluiSelectValue(value)
|
||||
|
||||
def _xmluiGetSelectedValues(self):
|
||||
ret = []
|
||||
labels = [self.GetString(idx) for idx in self.GetSelections()]
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ from sat.core.i18n import _
|
|||
|
||||
from sat.core import exceptions
|
||||
from sat.core.constants import Const as C
|
||||
from xml.dom import minidom
|
||||
from xml.dom import minidom, NotFoundErr
|
||||
from logging import debug, info, warning, error
|
||||
from twisted.internet import defer
|
||||
from twisted.python.failure import Failure
|
||||
|
|
@ -494,7 +494,17 @@ class Params(object):
|
|||
cache=profile_cache, profile=profile)
|
||||
if profile_value is not None:
|
||||
# there is a value for this profile, we must change the default
|
||||
dest_params[name].setAttribute('value', profile_value)
|
||||
if dest_params[name].getAttribute('type') == 'list':
|
||||
for option in dest_params[name].getElementsByTagName("option"):
|
||||
if option.getAttribute('value') == profile_value:
|
||||
option.setAttribute('selected', 'true')
|
||||
else:
|
||||
try:
|
||||
option.removeAttribute('selected')
|
||||
except NotFoundErr:
|
||||
pass
|
||||
else:
|
||||
dest_params[name].setAttribute('value', profile_value)
|
||||
if new_node:
|
||||
prof_xml.documentElement.appendChild(dest_cat)
|
||||
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ class CS_Plugin(object):
|
|||
interface.addText(_("G'day %(name)s, you have %(nb_message)i unread message%(plural_mess)s and %(unread_CR_mess)s unread couch request message%(plural_CR)s\nIf you want to send a message, select the recipient(s) in the list below") % {'name': user_name, 'nb_message': unread_mess, 'plural_mess': 's' if unread_mess > 1 else '', 'unread_CR_mess': unread_CR_mess, 'plural_CR': 's' if unread_CR_mess > 1 else ''})
|
||||
if unread_mess:
|
||||
interface.addButton('plugin_CS_showUnreadMessages', 'showUnreadMessages', _('Show unread message%(plural)s in external web browser') % {'plural': 's' if unread_mess > 1 else ''})
|
||||
interface.addList(friends_list, 'friends', style=['multi'])
|
||||
interface.addList(friends_list, 'friends', None, style=['multi'])
|
||||
interface.changeLayout('pairs')
|
||||
interface.addLabel(_("Subject"))
|
||||
interface.addString('subject')
|
||||
|
|
|
|||
|
|
@ -77,8 +77,7 @@ class TextSyntaxes(object):
|
|||
<params>
|
||||
<individual>
|
||||
<category name="%(category_name)s" label="%(category_label)s">
|
||||
<param name="%(name)s" label="%(label)s"
|
||||
value="%(default)s" type="list" security="0">
|
||||
<param name="%(name)s" label="%(label)s" type="list" security="0">
|
||||
%(options)s
|
||||
</param>
|
||||
</category>
|
||||
|
|
@ -91,7 +90,6 @@ class TextSyntaxes(object):
|
|||
'category_label': _(CATEGORY),
|
||||
'name': NAME,
|
||||
'label': _(NAME),
|
||||
'default': _SYNTAX_XHTML,
|
||||
'syntaxes': {},
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +126,8 @@ class TextSyntaxes(object):
|
|||
options = []
|
||||
|
||||
for syntax in syntaxes:
|
||||
options.append(u'<option value="%s" />' % syntax)
|
||||
selected = 'selected="true"' if syntax == _SYNTAX_XHTML else ''
|
||||
options.append(u'<option value="%s" %s/>' % (syntax, selected))
|
||||
|
||||
TextSyntaxes.params_data["options"] = u'\n'.join(options)
|
||||
self.host.memory.updateParams(TextSyntaxes.params % TextSyntaxes.params_data)
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class XEP_0249(object):
|
|||
<params>
|
||||
<individual>
|
||||
<category name="%(category_name)s" label="%(category_label)s">
|
||||
<param name="%(param_name)s" label="%(param_label)s" value="%(param_default)s" type="list" security="0">
|
||||
<param name="%(param_name)s" label="%(param_label)s" type="list" security="0">
|
||||
%(param_options)s
|
||||
</param>
|
||||
</category>
|
||||
|
|
@ -70,8 +70,9 @@ class XEP_0249(object):
|
|||
'category_label': _("Misc"),
|
||||
'param_name': AUTOJOIN_NAME,
|
||||
'param_label': _("Auto-join MUC on invitation"),
|
||||
'param_default': AUTOJOIN_VALUES[0],
|
||||
'param_options': ['<option value="%s"/>' % value for value in AUTOJOIN_VALUES]
|
||||
'param_options': '\n'.join(['<option value="%s" %s/>' % \
|
||||
(value, 'selected="true"' if value == AUTOJOIN_VALUES[0] else '') \
|
||||
for value in AUTOJOIN_VALUES])
|
||||
}
|
||||
|
||||
def __init__(self, host):
|
||||
|
|
|
|||
|
|
@ -207,8 +207,9 @@ def paramsXML2XMLUI(xml):
|
|||
callback_id = param.getAttribute('callback_id') or None
|
||||
|
||||
if type_ == 'list':
|
||||
options = _getParamListOptions(param)
|
||||
options, selected = _getParamListOptions(param)
|
||||
widget_kwargs['options'] = options
|
||||
widget_kwargs['selected'] = selected
|
||||
|
||||
if type_ in ("button", "text"):
|
||||
param_ui.addEmpty()
|
||||
|
|
@ -230,16 +231,16 @@ def paramsXML2XMLUI(xml):
|
|||
|
||||
|
||||
def _getParamListOptions(param):
|
||||
"""Retrieve the options for list element. Allow listing the <option/>
|
||||
tags directly in <param/> or in an intermediate <options/> tag."""
|
||||
elems = param.getElementsByTagName("options")
|
||||
if len(elems) == 0:
|
||||
elems = param.getElementsByTagName("option")
|
||||
else:
|
||||
elems = elems.item(0).getElementsByTagName("option")
|
||||
"""Retrieve the options for list element. The <option/> tags
|
||||
must be direct children of <param/>."""
|
||||
if len(param.getElementsByTagName("options")) > 0:
|
||||
raise exceptions.DataError(_("The 'options' tag is not allowed in parameter of type 'list'!"))
|
||||
elems = param.getElementsByTagName("option")
|
||||
if len(elems) == 0:
|
||||
return []
|
||||
return [elem.getAttribute("value") for elem in elems]
|
||||
options = [elem.getAttribute("value") for elem in elems]
|
||||
selected = [elem.getAttribute("value") for elem in elems if elem.getAttribute("selected") == 'true']
|
||||
return (options, selected)
|
||||
|
||||
|
||||
## XMLUI Elements
|
||||
|
|
@ -302,7 +303,13 @@ class OptionElement(Element):
|
|||
"""" Used by ListWidget to specify options """
|
||||
type = 'option'
|
||||
|
||||
def __init__(self, parent, option):
|
||||
def __init__(self, parent, option, selected=False):
|
||||
"""
|
||||
|
||||
@param parent
|
||||
@param option (string, tuple)
|
||||
@param selected (boolean)
|
||||
"""
|
||||
assert(isinstance(parent, ListWidget))
|
||||
super(OptionElement, self).__init__(parent.xmlui, parent)
|
||||
if isinstance(option, basestring):
|
||||
|
|
@ -311,6 +318,8 @@ class OptionElement(Element):
|
|||
value, label = option
|
||||
self.elem.setAttribute('value', value)
|
||||
self.elem.setAttribute('label', label)
|
||||
if selected:
|
||||
self.elem.setAttribute('selected', 'true')
|
||||
|
||||
|
||||
class RowElement(Element):
|
||||
|
|
@ -609,13 +618,24 @@ class ButtonWidget(Widget):
|
|||
if value:
|
||||
self.elem.setAttribute('value', value)
|
||||
for field in fields_back:
|
||||
fback_el = FieldBackElement(self, field)
|
||||
FieldBackElement(self, field)
|
||||
|
||||
|
||||
class ListWidget(InputWidget):
|
||||
type = 'list'
|
||||
|
||||
def __init__(self, xmlui, options, value=None, style=None, name=None, parent=None):
|
||||
def __init__(self, xmlui, options, selected=None, style=None, name=None, parent=None):
|
||||
"""
|
||||
|
||||
@param xmlui
|
||||
@param options (list[string, tuple]): each option can be given as:
|
||||
- a string if the label and the value are the same
|
||||
- a couple if the label and the value differ
|
||||
@param selected (list[string]): list of the selected values
|
||||
@param style (string)
|
||||
@param name (string)
|
||||
@param parent
|
||||
"""
|
||||
if style is None:
|
||||
style = set()
|
||||
styles = set(style)
|
||||
|
|
@ -624,16 +644,19 @@ class ListWidget(InputWidget):
|
|||
if not styles.issubset(['multi']):
|
||||
raise exceptions.DataError(_("invalid styles"))
|
||||
super(ListWidget, self).__init__(xmlui, name, parent)
|
||||
self.addOptions(options)
|
||||
if value:
|
||||
self.elem.setAttribute('value', value)
|
||||
self.addOptions(options, selected)
|
||||
for style in styles:
|
||||
self.elem.setAttribute(style, 'yes')
|
||||
|
||||
def addOptions(self, options):
|
||||
"""i Add options to a multi-values element (e.g. list) """
|
||||
def addOptions(self, options, selected=None):
|
||||
"""Add options to a multi-values element (e.g. list) """
|
||||
if selected:
|
||||
if isinstance(selected, basestring):
|
||||
selected = [selected]
|
||||
else:
|
||||
selected = []
|
||||
for option in options:
|
||||
OptionElement(self, option)
|
||||
OptionElement(self, option, option in selected)
|
||||
|
||||
|
||||
## XMLUI main class
|
||||
|
|
|
|||
Loading…
Reference in a new issue