core (xmlui): added JidsListWidget to manage editable list of jids:

- can be used to manage XEP-0004's jid-multi
    - can be used in the future for search result to display found entities (need a read-only style)
    - generaly usefull to manage list of entites
    - implemented in params too
This commit is contained in:
Goffi 2015-08-20 18:33:52 +02:00
commit 8e37cf55ed

View file

@ -25,6 +25,7 @@ log = getLogger(__name__)
from xml.dom import minidom, NotFoundErr
from wokkel import data_form
from twisted.words.xish import domish
from twisted.words.protocols.jabber import jid
from sat.core import exceptions
@ -254,6 +255,7 @@ def paramsXML2XMLUI(xml):
@param xml (unicode)
@return: XMLUI
"""
# TODO: refactor params and use Twisted directly to parse XML
params_doc = minidom.parseString(xml.encode('utf-8'))
top = params_doc.documentElement
if top.nodeName != 'params':
@ -281,9 +283,11 @@ def paramsXML2XMLUI(xml):
callback_id = param.getAttribute('callback_id') or None
if type_ == 'list':
options, selected = _getParamListOptions(param)
options, selected = _paramsGetListOptions(param)
widget_kwargs['options'] = options
widget_kwargs['selected'] = selected
elif type_ == 'jids_list':
widget_kwargs['jids'] = _paramsGetListJids(param)
if type_ in ("button", "text"):
param_ui.addEmpty()
@ -308,7 +312,7 @@ def paramsXML2XMLUI(xml):
return param_ui.toXml()
def _getParamListOptions(param):
def _paramsGetListOptions(param):
"""Retrieve the options for list element.
The <option/> tags must be direct children of <param/>.
@ -324,8 +328,21 @@ def _getParamListOptions(param):
selected = [elem.getAttribute("value") for elem in elems if elem.getAttribute("selected") == 'true']
return (options, selected)
def _paramsGetListJids(param):
"""Retrive jids from a jids_list element.
## XMLUI Elements
the <jid/> tags must be direct children of <param/>
@param param (domish.Element): element
@return: a list of jids
"""
elems = param.getElementsByTagName("jid")
jids = [elem.firstChild.data for elem in elems
if elem.firstChild is not None
and elem.firstChild.nodeType == elem.TEXT_NODE]
return jids
### XMLUI Elements ###
class Element(object):
@ -427,6 +444,26 @@ class OptionElement(Element):
self.elem.setAttribute('selected', 'true')
class JidElement(Element):
"""" Used by JidsListWidget to specify jids"""
type = 'jid'
def __init__(self, parent, jid_):
"""
@param jid_(jid.JID, unicode): jid to append
"""
assert isinstance(parent, JidsListWidget)
super(JidElement, self).__init__(parent.xmlui, parent)
if isinstance(jid_, jid.JID):
value = jid.full
elif isinstance(jid_, basestring):
value = unicode(jid_)
else:
raise NotImplementedError
jid_txt = self.xmlui.doc.createTextNode(value)
self.elem.appendChild(jid_txt)
class RowElement(Element):
"""" Used by AdvancedListContainer """
type = 'row'
@ -462,6 +499,9 @@ class HeaderElement(Element):
self.elem.setAttribute('description', description)
## Containers ##
class Container(Element):
""" And Element which contains other ones and has a layout """
type = None
@ -603,6 +643,9 @@ class AdvancedListContainer(Container):
self.xmlui.changeContainer(parent_container)
## Widgets ##
class Widget(Element):
type = None
@ -798,7 +841,7 @@ class ButtonWidget(Widget):
class ListWidget(InputWidget):
type = 'list'
def __init__(self, xmlui, options, selected=None, style=None, name=None, parent=None):
def __init__(self, xmlui, options, selected=None, styles=None, name=None, parent=None):
"""
@param xmlui
@ -806,13 +849,15 @@ class ListWidget(InputWidget):
- a single string if the label and the value are the same
- a tuple with a couple of string (value,label) if the label and the value differ
@param selected (list[string]): list of the selected values
@param style (string)
@param styles (iterable[string]): flags to set the behaviour of the list
@param name (string)
@param parent
"""
if style is None:
style = set()
styles = set(style)
styles = set() if styles is None else set(styles)
if styles is None:
styles = set()
else:
styles = set(styles)
if not options:
log.warning(_('empty "options" list'))
if not styles.issubset(['multi']):
@ -834,6 +879,34 @@ class ListWidget(InputWidget):
value = option if isinstance(option, basestring) else option[0]
OptionElement(self, option, value in selected)
class JidsListWidget(InputWidget):
"""A list of text or jids where elements can be added/removed or modified"""
type = 'jids_list'
def __init__(self, xmlui, jids, styles=None, name=None, parent=None):
"""
@param xmlui
@param jids (list[jid.JID]): base jids
@param styles (iterable[string]): flags to set the behaviour of the list
@param name (string)
@param parent
"""
super(JidsListWidget, self).__init__(xmlui, name, parent)
styles = set() if styles is None else set(styles)
if not styles.issubset([]): # TODO
raise exceptions.DataError(_("invalid styles"))
for style in styles:
self.elem.setAttribute(style, 'yes')
if not jids:
log.debug('empty jids list')
else:
self.addJids(jids)
def addJids(self, jids):
for jid_ in jids:
JidElement(self, jid_)
## Dialog Elements ##