comparison sat_frontends/tools/xmlui.py @ 4037:524856bd7b19

massive refactoring to switch from camelCase to snake_case: historically, Libervia (SàT before) was using camelCase as allowed by PEP8 when using a pre-PEP8 code, to use the same coding style as in Twisted. However, snake_case is more readable and it's better to follow PEP8 best practices, so it has been decided to move on full snake_case. Because Libervia has a huge codebase, this ended with a ugly mix of camelCase and snake_case. To fix that, this patch does a big refactoring by renaming every function and method (including bridge) that are not coming from Twisted or Wokkel, to use fully snake_case. This is a massive change, and may result in some bugs.
author Goffi <goffi@goffi.org>
date Sat, 08 Apr 2023 13:54:42 +0200
parents be6d91572633
children 4b842c1fb686
comparison
equal deleted inserted replaced
4036:c4464d7ae97b 4037:524856bd7b19
38 38
39 class ClassNotRegistedError(Exception): 39 class ClassNotRegistedError(Exception):
40 pass 40 pass
41 41
42 42
43 # FIXME: this method is duplicated in frontends.tools.xmlui.getText 43 # FIXME: this method is duplicated in frontends.tools.xmlui.get_text
44 def getText(node): 44 def get_text(node):
45 """Get child text nodes 45 """Get child text nodes
46 @param node: dom Node 46 @param node: dom Node
47 @return: joined unicode text of all nodes 47 @return: joined unicode text of all nodes
48 48
49 """ 49 """
166 166
167 class Container(Widget): 167 class Container(Widget):
168 """Widget which can contain other ones with a specific layout""" 168 """Widget which can contain other ones with a specific layout"""
169 169
170 @classmethod 170 @classmethod
171 def _xmluiAdapt(cls, instance): 171 def _xmlui_adapt(cls, instance):
172 """Make cls as instance.__class__ 172 """Make cls as instance.__class__
173 173
174 cls must inherit from original instance class 174 cls must inherit from original instance class
175 Usefull when you get a class from UI toolkit 175 Usefull when you get a class from UI toolkit
176 """ 176 """
215 """base dialog""" 215 """base dialog"""
216 216
217 def __init__(self, _xmlui_parent): 217 def __init__(self, _xmlui_parent):
218 self._xmlui_parent = _xmlui_parent 218 self._xmlui_parent = _xmlui_parent
219 219
220 def _xmluiValidated(self, data=None): 220 def _xmlui_validated(self, data=None):
221 if data is None: 221 if data is None:
222 data = {} 222 data = {}
223 self._xmluiSetData(C.XMLUI_STATUS_VALIDATED, data) 223 self._xmlui_set_data(C.XMLUI_STATUS_VALIDATED, data)
224 self._xmluiSubmit(data) 224 self._xmlui_submit(data)
225 225
226 def _xmluiCancelled(self): 226 def _xmlui_cancelled(self):
227 data = {C.XMLUI_DATA_CANCELLED: C.BOOL_TRUE} 227 data = {C.XMLUI_DATA_CANCELLED: C.BOOL_TRUE}
228 self._xmluiSetData(C.XMLUI_STATUS_CANCELLED, data) 228 self._xmlui_set_data(C.XMLUI_STATUS_CANCELLED, data)
229 self._xmluiSubmit(data) 229 self._xmlui_submit(data)
230 230
231 def _xmluiSubmit(self, data): 231 def _xmlui_submit(self, data):
232 if self._xmlui_parent.submit_id is None: 232 if self._xmlui_parent.submit_id is None:
233 log.debug(_("Nothing to submit")) 233 log.debug(_("Nothing to submit"))
234 else: 234 else:
235 self._xmlui_parent.submit(data) 235 self._xmlui_parent.submit(data)
236 236
237 def _xmluiSetData(self, status, data): 237 def _xmlui_set_data(self, status, data):
238 pass 238 pass
239 239
240 240
241 class MessageDialog(Dialog): 241 class MessageDialog(Dialog):
242 """Dialog with a OK/Cancel type configuration""" 242 """Dialog with a OK/Cancel type configuration"""
251 251
252 252
253 class ConfirmDialog(Dialog): 253 class ConfirmDialog(Dialog):
254 """Dialog with a OK/Cancel type configuration""" 254 """Dialog with a OK/Cancel type configuration"""
255 255
256 def _xmluiSetData(self, status, data): 256 def _xmlui_set_data(self, status, data):
257 if status == C.XMLUI_STATUS_VALIDATED: 257 if status == C.XMLUI_STATUS_VALIDATED:
258 data[C.XMLUI_DATA_ANSWER] = C.BOOL_TRUE 258 data[C.XMLUI_DATA_ANSWER] = C.BOOL_TRUE
259 elif status == C.XMLUI_STATUS_CANCELLED: 259 elif status == C.XMLUI_STATUS_CANCELLED:
260 data[C.XMLUI_DATA_ANSWER] = C.BOOL_FALSE 260 data[C.XMLUI_DATA_ANSWER] = C.BOOL_FALSE
261 261
281 @param title: force the title, or use XMLUI one if None 281 @param title: force the title, or use XMLUI one if None
282 @param flags: list of string which can be: 282 @param flags: list of string which can be:
283 - NO_CANCEL: the UI can't be cancelled 283 - NO_CANCEL: the UI can't be cancelled
284 - FROM_BACKEND: the UI come from backend (i.e. it's not the direct result of 284 - FROM_BACKEND: the UI come from backend (i.e. it's not the direct result of
285 user operation) 285 user operation)
286 @param callback(callable, None): if not None, will be used with launchAction: 286 @param callback(callable, None): if not None, will be used with action_launch:
287 - if None is used, default behaviour will be used (closing the dialog and 287 - if None is used, default behaviour will be used (closing the dialog and
288 calling host.actionManager) 288 calling host.action_manager)
289 - if a callback is provided, it will be used instead, so you'll have to manage 289 - if a callback is provided, it will be used instead, so you'll have to manage
290 dialog closing or new xmlui to display, or other action (you can call 290 dialog closing or new xmlui to display, or other action (you can call
291 host.actionManager) 291 host.action_manager)
292 The callback will have data, callback_id and profile as arguments 292 The callback will have data, callback_id and profile as arguments
293 """ 293 """
294 self.host = host 294 self.host = host
295 top = parsed_dom.documentElement 295 top = parsed_dom.documentElement
296 self.session_id = top.getAttribute("session_id") or None 296 self.session_id = top.getAttribute("session_id") or None
298 self.xmlui_title = title or top.getAttribute("title") or "" 298 self.xmlui_title = title or top.getAttribute("title") or ""
299 self.hidden = {} 299 self.hidden = {}
300 if flags is None: 300 if flags is None:
301 flags = [] 301 flags = []
302 self.flags = flags 302 self.flags = flags
303 self.callback = callback or self._defaultCb 303 self.callback = callback or self._default_cb
304 self.profile = profile 304 self.profile = profile
305 305
306 @property 306 @property
307 def user_action(self): 307 def user_action(self):
308 return "FROM_BACKEND" not in self.flags 308 return "FROM_BACKEND" not in self.flags
309 309
310 def _defaultCb(self, data, cb_id, profile): 310 def _default_cb(self, data, cb_id, profile):
311 # TODO: when XMLUI updates will be managed, the _xmluiClose 311 # TODO: when XMLUI updates will be managed, the _xmlui_close
312 # must be called only if there is no update 312 # must be called only if there is no update
313 self._xmluiClose() 313 self._xmlui_close()
314 self.host.actionManager(data, profile=profile) 314 self.host.action_manager(data, profile=profile)
315 315
316 def _isAttrSet(self, name, node): 316 def _is_attr_set(self, name, node):
317 """Return widget boolean attribute status 317 """Return widget boolean attribute status
318 318
319 @param name: name of the attribute (e.g. "read_only") 319 @param name: name of the attribute (e.g. "read_only")
320 @param node: Node instance 320 @param node: Node instance
321 @return (bool): True if widget's attribute is set (C.BOOL_TRUE) 321 @return (bool): True if widget's attribute is set (C.BOOL_TRUE)
322 """ 322 """
323 read_only = node.getAttribute(name) or C.BOOL_FALSE 323 read_only = node.getAttribute(name) or C.BOOL_FALSE
324 return read_only.lower().strip() == C.BOOL_TRUE 324 return read_only.lower().strip() == C.BOOL_TRUE
325 325
326 def _getChildNode(self, node, name): 326 def _get_child_node(self, node, name):
327 """Return the first child node with the given name 327 """Return the first child node with the given name
328 328
329 @param node: Node instance 329 @param node: Node instance
330 @param name: name of the wanted node 330 @param name: name of the wanted node
331 331
335 if child.nodeName == name: 335 if child.nodeName == name:
336 return child 336 return child
337 return None 337 return None
338 338
339 def submit(self, data): 339 def submit(self, data):
340 self._xmluiClose() 340 self._xmlui_close()
341 if self.submit_id is None: 341 if self.submit_id is None:
342 raise ValueError("Can't submit is self.submit_id is not set") 342 raise ValueError("Can't submit is self.submit_id is not set")
343 if "session_id" in data: 343 if "session_id" in data:
344 raise ValueError( 344 raise ValueError(
345 "session_id must no be used in data, it is automaticaly filled with " 345 "session_id must no be used in data, it is automaticaly filled with "
346 "self.session_id if present" 346 "self.session_id if present"
347 ) 347 )
348 if self.session_id is not None: 348 if self.session_id is not None:
349 data["session_id"] = self.session_id 349 data["session_id"] = self.session_id
350 self._xmluiLaunchAction(self.submit_id, data) 350 self._xmlui_launch_action(self.submit_id, data)
351 351
352 def _xmluiLaunchAction(self, action_id, data): 352 def _xmlui_launch_action(self, action_id, data):
353 self.host.launchAction( 353 self.host.action_launch(
354 action_id, data, callback=self.callback, profile=self.profile 354 action_id, data, callback=self.callback, profile=self.profile
355 ) 355 )
356 356
357 def _xmluiClose(self): 357 def _xmlui_close(self):
358 """Close the window/popup/... where the constructor XMLUI is 358 """Close the window/popup/... where the constructor XMLUI is
359 359
360 this method must be overrided 360 this method must be overrided
361 """ 361 """
362 raise NotImplementedError 362 raise NotImplementedError
425 "ignore and whitelist must not be used at the same time" 425 "ignore and whitelist must not be used at the same time"
426 ) 426 )
427 self._whitelist = whitelist 427 self._whitelist = whitelist
428 else: 428 else:
429 self._whitelist = None 429 self._whitelist = None
430 self.constructUI(parsed_dom) 430 self.construct_ui(parsed_dom)
431 431
432 @staticmethod 432 @staticmethod
433 def escape(name): 433 def escape(name):
434 """Return escaped name for forms""" 434 """Return escaped name for forms"""
435 return "%s%s" % (C.SAT_FORM_PREFIX, name) 435 return "%s%s" % (C.SAT_FORM_PREFIX, name)
447 def main_cont(self, value): 447 def main_cont(self, value):
448 if self._main_cont is not None: 448 if self._main_cont is not None:
449 raise ValueError(_("XMLUI can have only one main container")) 449 raise ValueError(_("XMLUI can have only one main container"))
450 self._main_cont = value 450 self._main_cont = value
451 451
452 def _parseChilds(self, _xmlui_parent, current_node, wanted=("container",), data=None): 452 def _parse_childs(self, _xmlui_parent, current_node, wanted=("container",), data=None):
453 """Recursively parse childNodes of an element 453 """Recursively parse childNodes of an element
454 454
455 @param _xmlui_parent: widget container with '_xmluiAppend' method 455 @param _xmlui_parent: widget container with '_xmlui_append' method
456 @param current_node: element from which childs will be parsed 456 @param current_node: element from which childs will be parsed
457 @param wanted: list of tag names that can be present in the childs to be SàT XMLUI 457 @param wanted: list of tag names that can be present in the childs to be SàT XMLUI
458 compliant 458 compliant
459 @param data(None, dict): additionnal data which are needed in some cases 459 @param data(None, dict): additionnal data which are needed in some cases
460 """ 460 """
471 # so we create one to wrap it 471 # so we create one to wrap it
472 _xmlui_parent = self.widget_factory.createVerticalContainer(self) 472 _xmlui_parent = self.widget_factory.createVerticalContainer(self)
473 self.main_cont = _xmlui_parent 473 self.main_cont = _xmlui_parent
474 if type_ == "tabs": 474 if type_ == "tabs":
475 cont = self.widget_factory.createTabsContainer(_xmlui_parent) 475 cont = self.widget_factory.createTabsContainer(_xmlui_parent)
476 self._parseChilds(_xmlui_parent, node, ("tab",), {"tabs_cont": cont}) 476 self._parse_childs(_xmlui_parent, node, ("tab",), {"tabs_cont": cont})
477 elif type_ == "vertical": 477 elif type_ == "vertical":
478 cont = self.widget_factory.createVerticalContainer(_xmlui_parent) 478 cont = self.widget_factory.createVerticalContainer(_xmlui_parent)
479 self._parseChilds(cont, node, ("widget", "container")) 479 self._parse_childs(cont, node, ("widget", "container"))
480 elif type_ == "pairs": 480 elif type_ == "pairs":
481 cont = self.widget_factory.createPairsContainer(_xmlui_parent) 481 cont = self.widget_factory.createPairsContainer(_xmlui_parent)
482 self._parseChilds(cont, node, ("widget", "container")) 482 self._parse_childs(cont, node, ("widget", "container"))
483 elif type_ == "label": 483 elif type_ == "label":
484 cont = self.widget_factory.createLabelContainer(_xmlui_parent) 484 cont = self.widget_factory.createLabelContainer(_xmlui_parent)
485 self._parseChilds( 485 self._parse_childs(
486 # FIXME: the "None" value for CURRENT_LABEL doesn't seem 486 # FIXME: the "None" value for CURRENT_LABEL doesn't seem
487 # used or even useful, it should probably be removed 487 # used or even useful, it should probably be removed
488 # and all "is not None" tests for it should be removed too 488 # and all "is not None" tests for it should be removed too
489 # to be checked for 0.8 489 # to be checked for 0.8
490 cont, node, ("widget", "container"), {CURRENT_LABEL: None} 490 cont, node, ("widget", "container"), {CURRENT_LABEL: None}
505 if selectable == "no": 505 if selectable == "no":
506 raise ValueError( 506 raise ValueError(
507 "can't have selectable=='no' and callback_id at the same time" 507 "can't have selectable=='no' and callback_id at the same time"
508 ) 508 )
509 cont._xmlui_callback_id = callback_id 509 cont._xmlui_callback_id = callback_id
510 cont._xmluiOnSelect(self.onAdvListSelect) 510 cont._xmlui_on_select(self.on_adv_list_select)
511 511
512 self._parseChilds(cont, node, ("row",), data) 512 self._parse_childs(cont, node, ("row",), data)
513 else: 513 else:
514 log.warning(_("Unknown container [%s], using default one") % type_) 514 log.warning(_("Unknown container [%s], using default one") % type_)
515 cont = self.widget_factory.createVerticalContainer(_xmlui_parent) 515 cont = self.widget_factory.createVerticalContainer(_xmlui_parent)
516 self._parseChilds(cont, node, ("widget", "container")) 516 self._parse_childs(cont, node, ("widget", "container"))
517 try: 517 try:
518 xmluiAppend = _xmlui_parent._xmluiAppend 518 xmluiAppend = _xmlui_parent._xmlui_append
519 except ( 519 except (
520 AttributeError, 520 AttributeError,
521 TypeError, 521 TypeError,
522 ): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError 522 ): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError
523 if _xmlui_parent is self: 523 if _xmlui_parent is self:
524 self.main_cont = cont 524 self.main_cont = cont
525 else: 525 else:
526 raise Exception( 526 raise Exception(
527 _("Internal Error, container has not _xmluiAppend method") 527 _("Internal Error, container has not _xmlui_append method")
528 ) 528 )
529 else: 529 else:
530 xmluiAppend(cont) 530 xmluiAppend(cont)
531 531
532 elif node.nodeName == "tab": 532 elif node.nodeName == "tab":
538 if self.type == "param": 538 if self.type == "param":
539 self._current_category = ( 539 self._current_category = (
540 name 540 name
541 ) # XXX: awful hack because params need category and we don't keep parent 541 ) # XXX: awful hack because params need category and we don't keep parent
542 tab_cont = data["tabs_cont"] 542 tab_cont = data["tabs_cont"]
543 new_tab = tab_cont._xmluiAddTab(label or name, selected) 543 new_tab = tab_cont._xmlui_add_tab(label or name, selected)
544 self._parseChilds(new_tab, node, ("widget", "container")) 544 self._parse_childs(new_tab, node, ("widget", "container"))
545 545
546 elif node.nodeName == "row": 546 elif node.nodeName == "row":
547 try: 547 try:
548 index = str(data["index"]) 548 index = str(data["index"])
549 except KeyError: 549 except KeyError:
550 index = node.getAttribute("index") or None 550 index = node.getAttribute("index") or None
551 else: 551 else:
552 data["index"] += 1 552 data["index"] += 1
553 _xmlui_parent._xmluiAddRow(index) 553 _xmlui_parent._xmlui_add_row(index)
554 self._parseChilds(_xmlui_parent, node, ("widget", "container")) 554 self._parse_childs(_xmlui_parent, node, ("widget", "container"))
555 555
556 elif node.nodeName == "widget": 556 elif node.nodeName == "widget":
557 name = node.getAttribute("name") 557 name = node.getAttribute("name")
558 if name and ( 558 if name and (
559 name in self._ignore 559 name in self._ignore
563 # current widget is ignored, but there may be already a label 563 # current widget is ignored, but there may be already a label
564 if CURRENT_LABEL in data: 564 if CURRENT_LABEL in data:
565 curr_label = data.pop(CURRENT_LABEL) 565 curr_label = data.pop(CURRENT_LABEL)
566 if curr_label is not None: 566 if curr_label is not None:
567 # if so, we remove it from parent 567 # if so, we remove it from parent
568 _xmlui_parent._xmluiRemove(curr_label) 568 _xmlui_parent._xmlui_remove(curr_label)
569 continue 569 continue
570 type_ = node.getAttribute("type") 570 type_ = node.getAttribute("type")
571 value_elt = self._getChildNode(node, "value") 571 value_elt = self._get_child_node(node, "value")
572 if value_elt is not None: 572 if value_elt is not None:
573 value = getText(value_elt) 573 value = get_text(value_elt)
574 else: 574 else:
575 value = ( 575 value = (
576 node.getAttribute("value") if node.hasAttribute("value") else "" 576 node.getAttribute("value") if node.hasAttribute("value") else ""
577 ) 577 )
578 if type_ == "empty": 578 if type_ == "empty":
595 elif type_ == "divider": 595 elif type_ == "divider":
596 style = node.getAttribute("style") or "line" 596 style = node.getAttribute("style") or "line"
597 ctrl = self.widget_factory.createDividerWidget(_xmlui_parent, style) 597 ctrl = self.widget_factory.createDividerWidget(_xmlui_parent, style)
598 elif type_ == "string": 598 elif type_ == "string":
599 ctrl = self.widget_factory.createStringWidget( 599 ctrl = self.widget_factory.createStringWidget(
600 _xmlui_parent, value, self._isAttrSet("read_only", node) 600 _xmlui_parent, value, self._is_attr_set("read_only", node)
601 ) 601 )
602 self.ctrl_list[name] = {"type": type_, "control": ctrl} 602 self.ctrl_list[name] = {"type": type_, "control": ctrl}
603 elif type_ == "jid_input": 603 elif type_ == "jid_input":
604 ctrl = self.widget_factory.createJidInputWidget( 604 ctrl = self.widget_factory.createJidInputWidget(
605 _xmlui_parent, value, self._isAttrSet("read_only", node) 605 _xmlui_parent, value, self._is_attr_set("read_only", node)
606 ) 606 )
607 self.ctrl_list[name] = {"type": type_, "control": ctrl} 607 self.ctrl_list[name] = {"type": type_, "control": ctrl}
608 elif type_ == "password": 608 elif type_ == "password":
609 ctrl = self.widget_factory.createPasswordWidget( 609 ctrl = self.widget_factory.createPasswordWidget(
610 _xmlui_parent, value, self._isAttrSet("read_only", node) 610 _xmlui_parent, value, self._is_attr_set("read_only", node)
611 ) 611 )
612 self.ctrl_list[name] = {"type": type_, "control": ctrl} 612 self.ctrl_list[name] = {"type": type_, "control": ctrl}
613 elif type_ == "textbox": 613 elif type_ == "textbox":
614 ctrl = self.widget_factory.createTextBoxWidget( 614 ctrl = self.widget_factory.createTextBoxWidget(
615 _xmlui_parent, value, self._isAttrSet("read_only", node) 615 _xmlui_parent, value, self._is_attr_set("read_only", node)
616 ) 616 )
617 self.ctrl_list[name] = {"type": type_, "control": ctrl} 617 self.ctrl_list[name] = {"type": type_, "control": ctrl}
618 elif type_ == "xhtmlbox": 618 elif type_ == "xhtmlbox":
619 ctrl = self.widget_factory.createXHTMLBoxWidget( 619 ctrl = self.widget_factory.createXHTMLBoxWidget(
620 _xmlui_parent, value, self._isAttrSet("read_only", node) 620 _xmlui_parent, value, self._is_attr_set("read_only", node)
621 ) 621 )
622 self.ctrl_list[name] = {"type": type_, "control": ctrl} 622 self.ctrl_list[name] = {"type": type_, "control": ctrl}
623 elif type_ == "bool": 623 elif type_ == "bool":
624 ctrl = self.widget_factory.createBoolWidget( 624 ctrl = self.widget_factory.createBoolWidget(
625 _xmlui_parent, 625 _xmlui_parent,
626 value == C.BOOL_TRUE, 626 value == C.BOOL_TRUE,
627 self._isAttrSet("read_only", node), 627 self._is_attr_set("read_only", node),
628 ) 628 )
629 self.ctrl_list[name] = {"type": type_, "control": ctrl} 629 self.ctrl_list[name] = {"type": type_, "control": ctrl}
630 elif type_ == "int": 630 elif type_ == "int":
631 ctrl = self.widget_factory.createIntWidget( 631 ctrl = self.widget_factory.createIntWidget(
632 _xmlui_parent, value, self._isAttrSet("read_only", node) 632 _xmlui_parent, value, self._is_attr_set("read_only", node)
633 ) 633 )
634 self.ctrl_list[name] = {"type": type_, "control": ctrl} 634 self.ctrl_list[name] = {"type": type_, "control": ctrl}
635 elif type_ == "list": 635 elif type_ == "list":
636 style = [] if node.getAttribute("multi") == "yes" else ["single"] 636 style = [] if node.getAttribute("multi") == "yes" else ["single"]
637 for attr in ("noselect", "extensible", "reducible", "inline"): 637 for attr in ("noselect", "extensible", "reducible", "inline"):
650 _xmlui_parent, _options, _selected, style 650 _xmlui_parent, _options, _selected, style
651 ) 651 )
652 self.ctrl_list[name] = {"type": type_, "control": ctrl} 652 self.ctrl_list[name] = {"type": type_, "control": ctrl}
653 elif type_ == "jids_list": 653 elif type_ == "jids_list":
654 style = [] 654 style = []
655 jids = [getText(jid_) for jid_ in node.getElementsByTagName("jid")] 655 jids = [get_text(jid_) for jid_ in node.getElementsByTagName("jid")]
656 ctrl = self.widget_factory.createJidsListWidget( 656 ctrl = self.widget_factory.createJidsListWidget(
657 _xmlui_parent, jids, style 657 _xmlui_parent, jids, style
658 ) 658 )
659 self.ctrl_list[name] = {"type": type_, "control": ctrl} 659 self.ctrl_list[name] = {"type": type_, "control": ctrl}
660 elif type_ == "button": 660 elif type_ == "button":
661 callback_id = node.getAttribute("callback") 661 callback_id = node.getAttribute("callback")
662 ctrl = self.widget_factory.createButtonWidget( 662 ctrl = self.widget_factory.createButtonWidget(
663 _xmlui_parent, value, self.onButtonPress 663 _xmlui_parent, value, self.on_button_press
664 ) 664 )
665 ctrl._xmlui_param_id = ( 665 ctrl._xmlui_param_id = (
666 callback_id, 666 callback_id,
667 [ 667 [
668 field.getAttribute("name") 668 field.getAttribute("name")
681 if name: 681 if name:
682 self.widgets[name] = ctrl 682 self.widgets[name] = ctrl
683 683
684 if self.type == "param" and type_ not in ("text", "button"): 684 if self.type == "param" and type_ not in ("text", "button"):
685 try: 685 try:
686 ctrl._xmluiOnChange(self.onParamChange) 686 ctrl._xmlui_on_change(self.on_param_change)
687 ctrl._param_category = self._current_category 687 ctrl._param_category = self._current_category
688 except ( 688 except (
689 AttributeError, 689 AttributeError,
690 TypeError, 690 TypeError,
691 ): # XXX: TypeError is here because pyjamas raise a TypeError instead 691 ): # XXX: TypeError is here because pyjamas raise a TypeError instead
700 if callback: 700 if callback:
701 fields = [ 701 fields = [
702 field.getAttribute("name") 702 field.getAttribute("name")
703 for field in node.getElementsByTagName("internal_field") 703 for field in node.getElementsByTagName("internal_field")
704 ] 704 ]
705 cb_data = self.getInternalCallbackData(callback, node) 705 cb_data = self.get_internal_callback_data(callback, node)
706 ctrl._xmlui_param_internal = (callback, fields, cb_data) 706 ctrl._xmlui_param_internal = (callback, fields, cb_data)
707 if type_ == "button": 707 if type_ == "button":
708 ctrl._xmluiOnClick(self.onChangeInternal) 708 ctrl._xmlui_on_click(self.on_change_internal)
709 else: 709 else:
710 ctrl._xmluiOnChange(self.onChangeInternal) 710 ctrl._xmlui_on_change(self.on_change_internal)
711 711
712 ctrl._xmlui_name = name 712 ctrl._xmlui_name = name
713 _xmlui_parent._xmluiAppend(ctrl) 713 _xmlui_parent._xmlui_append(ctrl)
714 if CURRENT_LABEL in data and not isinstance(ctrl, LabelWidget): 714 if CURRENT_LABEL in data and not isinstance(ctrl, LabelWidget):
715 curr_label = data.pop(CURRENT_LABEL) 715 curr_label = data.pop(CURRENT_LABEL)
716 if curr_label is not None: 716 if curr_label is not None:
717 # this key is set in LabelContainer, when present 717 # this key is set in LabelContainer, when present
718 # we can associate the label with the widget it is labelling 718 # we can associate the label with the widget it is labelling
719 curr_label._xmlui_for_name = name 719 curr_label._xmlui_for_name = name
720 720
721 else: 721 else:
722 raise NotImplementedError(_("Unknown tag [%s]") % node.nodeName) 722 raise NotImplementedError(_("Unknown tag [%s]") % node.nodeName)
723 723
724 def constructUI(self, parsed_dom, post_treat=None): 724 def construct_ui(self, parsed_dom, post_treat=None):
725 """Actually construct the UI 725 """Actually construct the UI
726 726
727 @param parsed_dom: main parsed dom 727 @param parsed_dom: main parsed dom
728 @param post_treat: frontend specific treatments to do once the UI is constructed 728 @param post_treat: frontend specific treatments to do once the UI is constructed
729 @return: constructed widget 729 @return: constructed widget
739 raise InvalidXMLUI 739 raise InvalidXMLUI
740 740
741 if self.type == "param": 741 if self.type == "param":
742 self.param_changed = set() 742 self.param_changed = set()
743 743
744 self._parseChilds(self, parsed_dom.documentElement) 744 self._parse_childs(self, parsed_dom.documentElement)
745 745
746 if post_treat is not None: 746 if post_treat is not None:
747 post_treat() 747 post_treat()
748 748
749 def _xmluiSetParam(self, name, value, category): 749 def _xmlui_set_param(self, name, value, category):
750 self.host.bridge.setParam(name, value, category, profile_key=self.profile) 750 self.host.bridge.param_set(name, value, category, profile_key=self.profile)
751 751
752 ##EVENTS## 752 ##EVENTS##
753 753
754 def onParamChange(self, ctrl): 754 def on_param_change(self, ctrl):
755 """Called when type is param and a widget to save is modified 755 """Called when type is param and a widget to save is modified
756 756
757 @param ctrl: widget modified 757 @param ctrl: widget modified
758 """ 758 """
759 assert self.type == "param" 759 assert self.type == "param"
760 self.param_changed.add(ctrl) 760 self.param_changed.add(ctrl)
761 761
762 def onAdvListSelect(self, ctrl): 762 def on_adv_list_select(self, ctrl):
763 data = {} 763 data = {}
764 widgets = ctrl._xmluiGetSelectedWidgets() 764 widgets = ctrl._xmlui_get_selected_widgets()
765 for wid in widgets: 765 for wid in widgets:
766 try: 766 try:
767 name = self.escape(wid._xmlui_name) 767 name = self.escape(wid._xmlui_name)
768 value = wid._xmluiGetValue() 768 value = wid._xmlui_get_value()
769 data[name] = value 769 data[name] = value
770 except ( 770 except (
771 AttributeError, 771 AttributeError,
772 TypeError, 772 TypeError,
773 ): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError 773 ): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError
774 pass 774 pass
775 idx = ctrl._xmluiGetSelectedIndex() 775 idx = ctrl._xmlui_get_selected_index()
776 if idx is not None: 776 if idx is not None:
777 data["index"] = idx 777 data["index"] = idx
778 callback_id = ctrl._xmlui_callback_id 778 callback_id = ctrl._xmlui_callback_id
779 if callback_id is None: 779 if callback_id is None:
780 log.info(_("No callback_id found")) 780 log.info(_("No callback_id found"))
781 return 781 return
782 self._xmluiLaunchAction(callback_id, data) 782 self._xmlui_launch_action(callback_id, data)
783 783
784 def onButtonPress(self, button): 784 def on_button_press(self, button):
785 """Called when an XMLUI button is clicked 785 """Called when an XMLUI button is clicked
786 786
787 Launch the action associated to the button 787 Launch the action associated to the button
788 @param button: the button clicked 788 @param button: the button clicked
789 """ 789 """
793 data = {} 793 data = {}
794 for field in fields: 794 for field in fields:
795 escaped = self.escape(field) 795 escaped = self.escape(field)
796 ctrl = self.ctrl_list[field] 796 ctrl = self.ctrl_list[field]
797 if isinstance(ctrl["control"], ListWidget): 797 if isinstance(ctrl["control"], ListWidget):
798 data[escaped] = "\t".join(ctrl["control"]._xmluiGetSelectedValues()) 798 data[escaped] = "\t".join(ctrl["control"]._xmlui_get_selected_values())
799 else: 799 else:
800 data[escaped] = ctrl["control"]._xmluiGetValue() 800 data[escaped] = ctrl["control"]._xmlui_get_value()
801 self._xmluiLaunchAction(callback_id, data) 801 self._xmlui_launch_action(callback_id, data)
802 802
803 def onChangeInternal(self, ctrl): 803 def on_change_internal(self, ctrl):
804 """Called when a widget that has been bound to an internal callback is changed. 804 """Called when a widget that has been bound to an internal callback is changed.
805 805
806 This is used to perform some UI actions without communicating with the backend. 806 This is used to perform some UI actions without communicating with the backend.
807 See sat.tools.xml_tools.Widget.setInternalCallback for more details. 807 See sat.tools.xml_tools.Widget.set_internal_callback for more details.
808 @param ctrl: widget modified 808 @param ctrl: widget modified
809 """ 809 """
810 action, fields, data = ctrl._xmlui_param_internal 810 action, fields, data = ctrl._xmlui_param_internal
811 if action not in ("copy", "move", "groups_of_contact"): 811 if action not in ("copy", "move", "groups_of_contact"):
812 raise NotImplementedError( 812 raise NotImplementedError(
815 815
816 def copy_move(source, target): 816 def copy_move(source, target):
817 """Depending of 'action' value, copy or move from source to target.""" 817 """Depending of 'action' value, copy or move from source to target."""
818 if isinstance(target, ListWidget): 818 if isinstance(target, ListWidget):
819 if isinstance(source, ListWidget): 819 if isinstance(source, ListWidget):
820 values = source._xmluiGetSelectedValues() 820 values = source._xmlui_get_selected_values()
821 else: 821 else:
822 values = [source._xmluiGetValue()] 822 values = [source._xmlui_get_value()]
823 if action == "move": 823 if action == "move":
824 source._xmluiSetValue("") 824 source._xmlui_set_value("")
825 values = [value for value in values if value] 825 values = [value for value in values if value]
826 if values: 826 if values:
827 target._xmluiAddValues(values, select=True) 827 target._xmlui_add_values(values, select=True)
828 else: 828 else:
829 if isinstance(source, ListWidget): 829 if isinstance(source, ListWidget):
830 value = ", ".join(source._xmluiGetSelectedValues()) 830 value = ", ".join(source._xmlui_get_selected_values())
831 else: 831 else:
832 value = source._xmluiGetValue() 832 value = source._xmlui_get_value()
833 if action == "move": 833 if action == "move":
834 source._xmluiSetValue("") 834 source._xmlui_set_value("")
835 target._xmluiSetValue(value) 835 target._xmlui_set_value(value)
836 836
837 def groups_of_contact(source, target): 837 def groups_of_contact(source, target):
838 """Select in target the groups of the contact which is selected in source.""" 838 """Select in target the groups of the contact which is selected in source."""
839 assert isinstance(source, ListWidget) 839 assert isinstance(source, ListWidget)
840 assert isinstance(target, ListWidget) 840 assert isinstance(target, ListWidget)
841 try: 841 try:
842 contact_jid_s = source._xmluiGetSelectedValues()[0] 842 contact_jid_s = source._xmlui_get_selected_values()[0]
843 except IndexError: 843 except IndexError:
844 return 844 return
845 target._xmluiSelectValues(data[contact_jid_s]) 845 target._xmlui_select_values(data[contact_jid_s])
846 pass 846 pass
847 847
848 source = None 848 source = None
849 for field in fields: 849 for field in fields:
850 widget = self.ctrl_list[field]["control"] 850 widget = self.ctrl_list[field]["control"]
855 copy_move(source, widget) 855 copy_move(source, widget)
856 elif action == "groups_of_contact": 856 elif action == "groups_of_contact":
857 groups_of_contact(source, widget) 857 groups_of_contact(source, widget)
858 source = None 858 source = None
859 859
860 def getInternalCallbackData(self, action, node): 860 def get_internal_callback_data(self, action, node):
861 """Retrieve from node the data needed to perform given action. 861 """Retrieve from node the data needed to perform given action.
862 862
863 @param action (string): a value from the one that can be passed to the 863 @param action (string): a value from the one that can be passed to the
864 'callback' parameter of sat.tools.xml_tools.Widget.setInternalCallback 864 'callback' parameter of sat.tools.xml_tools.Widget.set_internal_callback
865 @param node (DOM Element): the node of the widget that triggers the callback 865 @param node (DOM Element): the node of the widget that triggers the callback
866 """ 866 """
867 # TODO: it would be better to not have a specific way to retrieve 867 # TODO: it would be better to not have a specific way to retrieve
868 # data for each action, but instead to have a generic method to 868 # data for each action, but instead to have a generic method to
869 # extract any kind of data structure from the 'internal_data' element. 869 # extract any kind of data structure from the 'internal_data' element.
881 data[jid_s] = [] 881 data[jid_s] = []
882 for value_elt in elt.childNodes: 882 for value_elt in elt.childNodes:
883 data[jid_s].append(value_elt.getAttribute("name")) 883 data[jid_s].append(value_elt.getAttribute("name"))
884 return data 884 return data
885 885
886 def onFormSubmitted(self, ignore=None): 886 def on_form_submitted(self, ignore=None):
887 """An XMLUI form has been submited 887 """An XMLUI form has been submited
888 888
889 call the submit action associated with this form 889 call the submit action associated with this form
890 """ 890 """
891 selected_values = [] 891 selected_values = []
892 for ctrl_name in self.ctrl_list: 892 for ctrl_name in self.ctrl_list:
893 escaped = self.escape(ctrl_name) 893 escaped = self.escape(ctrl_name)
894 ctrl = self.ctrl_list[ctrl_name] 894 ctrl = self.ctrl_list[ctrl_name]
895 if isinstance(ctrl["control"], ListWidget): 895 if isinstance(ctrl["control"], ListWidget):
896 selected_values.append( 896 selected_values.append(
897 (escaped, "\t".join(ctrl["control"]._xmluiGetSelectedValues())) 897 (escaped, "\t".join(ctrl["control"]._xmlui_get_selected_values()))
898 ) 898 )
899 else: 899 else:
900 selected_values.append((escaped, ctrl["control"]._xmluiGetValue())) 900 selected_values.append((escaped, ctrl["control"]._xmlui_get_value()))
901 data = dict(selected_values) 901 data = dict(selected_values)
902 for key, value in self.hidden.items(): 902 for key, value in self.hidden.items():
903 data[self.escape(key)] = value 903 data[self.escape(key)] = value
904 904
905 if self.submit_id is not None: 905 if self.submit_id is not None:
906 self.submit(data) 906 self.submit(data)
907 else: 907 else:
908 log.warning( 908 log.warning(
909 _("The form data is not sent back, the type is not managed properly") 909 _("The form data is not sent back, the type is not managed properly")
910 ) 910 )
911 self._xmluiClose() 911 self._xmlui_close()
912 912
913 def onFormCancelled(self, *__): 913 def on_form_cancelled(self, *__):
914 """Called when a form is cancelled""" 914 """Called when a form is cancelled"""
915 log.debug(_("Cancelling form")) 915 log.debug(_("Cancelling form"))
916 if self.submit_id is not None: 916 if self.submit_id is not None:
917 data = {C.XMLUI_DATA_CANCELLED: C.BOOL_TRUE} 917 data = {C.XMLUI_DATA_CANCELLED: C.BOOL_TRUE}
918 self.submit(data) 918 self.submit(data)
919 else: 919 else:
920 log.warning( 920 log.warning(
921 _("The form data is not sent back, the type is not managed properly") 921 _("The form data is not sent back, the type is not managed properly")
922 ) 922 )
923 self._xmluiClose() 923 self._xmlui_close()
924 924
925 def onSaveParams(self, ignore=None): 925 def on_save_params(self, ignore=None):
926 """Params are saved, we send them to backend 926 """Params are saved, we send them to backend
927 927
928 self.type must be param 928 self.type must be param
929 """ 929 """
930 assert self.type == "param" 930 assert self.type == "param"
931 for ctrl in self.param_changed: 931 for ctrl in self.param_changed:
932 if isinstance(ctrl, ListWidget): 932 if isinstance(ctrl, ListWidget):
933 value = "\t".join(ctrl._xmluiGetSelectedValues()) 933 value = "\t".join(ctrl._xmlui_get_selected_values())
934 else: 934 else:
935 value = ctrl._xmluiGetValue() 935 value = ctrl._xmlui_get_value()
936 param_name = ctrl._xmlui_name.split(C.SAT_PARAM_SEPARATOR)[1] 936 param_name = ctrl._xmlui_name.split(C.SAT_PARAM_SEPARATOR)[1]
937 self._xmluiSetParam(param_name, value, ctrl._param_category) 937 self._xmlui_set_param(param_name, value, ctrl._param_category)
938 938
939 self._xmluiClose() 939 self._xmlui_close()
940 940
941 def show(self, *args, **kwargs): 941 def show(self, *args, **kwargs):
942 pass 942 pass
943 943
944 944
945 class AIOXMLUIPanel(XMLUIPanel): 945 class AIOXMLUIPanel(XMLUIPanel):
946 """Asyncio compatible version of XMLUIPanel""" 946 """Asyncio compatible version of XMLUIPanel"""
947 947
948 async def onFormSubmitted(self, ignore=None): 948 async def on_form_submitted(self, ignore=None):
949 """An XMLUI form has been submited 949 """An XMLUI form has been submited
950 950
951 call the submit action associated with this form 951 call the submit action associated with this form
952 """ 952 """
953 selected_values = [] 953 selected_values = []
954 for ctrl_name in self.ctrl_list: 954 for ctrl_name in self.ctrl_list:
955 escaped = self.escape(ctrl_name) 955 escaped = self.escape(ctrl_name)
956 ctrl = self.ctrl_list[ctrl_name] 956 ctrl = self.ctrl_list[ctrl_name]
957 if isinstance(ctrl["control"], ListWidget): 957 if isinstance(ctrl["control"], ListWidget):
958 selected_values.append( 958 selected_values.append(
959 (escaped, "\t".join(ctrl["control"]._xmluiGetSelectedValues())) 959 (escaped, "\t".join(ctrl["control"]._xmlui_get_selected_values()))
960 ) 960 )
961 else: 961 else:
962 selected_values.append((escaped, ctrl["control"]._xmluiGetValue())) 962 selected_values.append((escaped, ctrl["control"]._xmlui_get_value()))
963 data = dict(selected_values) 963 data = dict(selected_values)
964 for key, value in self.hidden.items(): 964 for key, value in self.hidden.items():
965 data[self.escape(key)] = value 965 data[self.escape(key)] = value
966 966
967 if self.submit_id is not None: 967 if self.submit_id is not None:
968 await self.submit(data) 968 await self.submit(data)
969 else: 969 else:
970 log.warning( 970 log.warning(
971 _("The form data is not sent back, the type is not managed properly") 971 _("The form data is not sent back, the type is not managed properly")
972 ) 972 )
973 self._xmluiClose() 973 self._xmlui_close()
974 974
975 async def onFormCancelled(self, *__): 975 async def on_form_cancelled(self, *__):
976 """Called when a form is cancelled""" 976 """Called when a form is cancelled"""
977 log.debug(_("Cancelling form")) 977 log.debug(_("Cancelling form"))
978 if self.submit_id is not None: 978 if self.submit_id is not None:
979 data = {C.XMLUI_DATA_CANCELLED: C.BOOL_TRUE} 979 data = {C.XMLUI_DATA_CANCELLED: C.BOOL_TRUE}
980 await self.submit(data) 980 await self.submit(data)
981 else: 981 else:
982 log.warning( 982 log.warning(
983 _("The form data is not sent back, the type is not managed properly") 983 _("The form data is not sent back, the type is not managed properly")
984 ) 984 )
985 self._xmluiClose() 985 self._xmlui_close()
986 986
987 async def submit(self, data): 987 async def submit(self, data):
988 self._xmluiClose() 988 self._xmlui_close()
989 if self.submit_id is None: 989 if self.submit_id is None:
990 raise ValueError("Can't submit is self.submit_id is not set") 990 raise ValueError("Can't submit is self.submit_id is not set")
991 if "session_id" in data: 991 if "session_id" in data:
992 raise ValueError( 992 raise ValueError(
993 "session_id must no be used in data, it is automaticaly filled with " 993 "session_id must no be used in data, it is automaticaly filled with "
994 "self.session_id if present" 994 "self.session_id if present"
995 ) 995 )
996 if self.session_id is not None: 996 if self.session_id is not None:
997 data["session_id"] = self.session_id 997 data["session_id"] = self.session_id
998 await self._xmluiLaunchAction(self.submit_id, data) 998 await self._xmlui_launch_action(self.submit_id, data)
999 999
1000 async def _xmluiLaunchAction(self, action_id, data): 1000 async def _xmlui_launch_action(self, action_id, data):
1001 await self.host.launchAction( 1001 await self.host.action_launch(
1002 action_id, data, callback=self.callback, profile=self.profile 1002 action_id, data, callback=self.callback, profile=self.profile
1003 ) 1003 )
1004 1004
1005 1005
1006 class XMLUIDialog(XMLUIBase): 1006 class XMLUIDialog(XMLUIBase):
1019 ): 1019 ):
1020 super(XMLUIDialog, self).__init__( 1020 super(XMLUIDialog, self).__init__(
1021 host, parsed_dom, title=title, flags=flags, callback=callback, profile=profile 1021 host, parsed_dom, title=title, flags=flags, callback=callback, profile=profile
1022 ) 1022 )
1023 top = parsed_dom.documentElement 1023 top = parsed_dom.documentElement
1024 dlg_elt = self._getChildNode(top, "dialog") 1024 dlg_elt = self._get_child_node(top, "dialog")
1025 if dlg_elt is None: 1025 if dlg_elt is None:
1026 raise ValueError("Invalid XMLUI: no Dialog element found !") 1026 raise ValueError("Invalid XMLUI: no Dialog element found !")
1027 dlg_type = dlg_elt.getAttribute("type") or C.XMLUI_DIALOG_MESSAGE 1027 dlg_type = dlg_elt.getAttribute("type") or C.XMLUI_DIALOG_MESSAGE
1028 try: 1028 try:
1029 mess_elt = self._getChildNode(dlg_elt, C.XMLUI_DATA_MESS) 1029 mess_elt = self._get_child_node(dlg_elt, C.XMLUI_DATA_MESS)
1030 message = getText(mess_elt) 1030 message = get_text(mess_elt)
1031 except ( 1031 except (
1032 TypeError, 1032 TypeError,
1033 AttributeError, 1033 AttributeError,
1034 ): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError 1034 ): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError
1035 message = "" 1035 message = ""
1043 self.dlg = self.dialog_factory.createNoteDialog( 1043 self.dlg = self.dialog_factory.createNoteDialog(
1044 self, self.xmlui_title, message, level 1044 self, self.xmlui_title, message, level
1045 ) 1045 )
1046 elif dlg_type == C.XMLUI_DIALOG_CONFIRM: 1046 elif dlg_type == C.XMLUI_DIALOG_CONFIRM:
1047 try: 1047 try:
1048 buttons_elt = self._getChildNode(dlg_elt, "buttons") 1048 buttons_elt = self._get_child_node(dlg_elt, "buttons")
1049 buttons_set = ( 1049 buttons_set = (
1050 buttons_elt.getAttribute("set") or C.XMLUI_DATA_BTNS_SET_DEFAULT 1050 buttons_elt.getAttribute("set") or C.XMLUI_DATA_BTNS_SET_DEFAULT
1051 ) 1051 )
1052 except ( 1052 except (
1053 TypeError, 1053 TypeError,
1057 self.dlg = self.dialog_factory.createConfirmDialog( 1057 self.dlg = self.dialog_factory.createConfirmDialog(
1058 self, self.xmlui_title, message, level, buttons_set 1058 self, self.xmlui_title, message, level, buttons_set
1059 ) 1059 )
1060 elif dlg_type == C.XMLUI_DIALOG_FILE: 1060 elif dlg_type == C.XMLUI_DIALOG_FILE:
1061 try: 1061 try:
1062 file_elt = self._getChildNode(dlg_elt, "file") 1062 file_elt = self._get_child_node(dlg_elt, "file")
1063 filetype = file_elt.getAttribute("type") or C.XMLUI_DATA_FILETYPE_DEFAULT 1063 filetype = file_elt.getAttribute("type") or C.XMLUI_DATA_FILETYPE_DEFAULT
1064 except ( 1064 except (
1065 TypeError, 1065 TypeError,
1066 AttributeError, 1066 AttributeError,
1067 ): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError 1067 ): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError
1071 ) 1071 )
1072 else: 1072 else:
1073 raise ValueError("Unknown dialog type [%s]" % dlg_type) 1073 raise ValueError("Unknown dialog type [%s]" % dlg_type)
1074 1074
1075 def show(self): 1075 def show(self):
1076 self.dlg._xmluiShow() 1076 self.dlg._xmlui_show()
1077 1077
1078 def _xmluiClose(self): 1078 def _xmlui_close(self):
1079 self.dlg._xmluiClose() 1079 self.dlg._xmlui_close()
1080 1080
1081 1081
1082 def registerClass(type_, class_): 1082 def register_class(type_, class_):
1083 """Register the class to use with the factory 1083 """Register the class to use with the factory
1084 1084
1085 @param type_: one of: 1085 @param type_: one of:
1086 CLASS_PANEL: classical XMLUI interface 1086 CLASS_PANEL: classical XMLUI interface
1087 CLASS_DIALOG: XMLUI dialog 1087 CLASS_DIALOG: XMLUI dialog
1088 @param class_: the class to use to instanciate given type 1088 @param class_: the class to use to instanciate given type
1089 """ 1089 """
1090 # TODO: remove this method, as there are seme use cases where different XMLUI 1090 # TODO: remove this method, as there are seme use cases where different XMLUI
1091 # classes can be used in the same frontend, so a global value is not good 1091 # classes can be used in the same frontend, so a global value is not good
1092 assert type_ in (CLASS_PANEL, CLASS_DIALOG) 1092 assert type_ in (CLASS_PANEL, CLASS_DIALOG)
1093 log.warning("registerClass for XMLUI is deprecated, please use partial with " 1093 log.warning("register_class for XMLUI is deprecated, please use partial with "
1094 "xmlui.create and class_map instead") 1094 "xmlui.create and class_map instead")
1095 if type_ in _class_map: 1095 if type_ in _class_map:
1096 log.debug(_("XMLUI class already registered for {type_}, ignoring").format( 1096 log.debug(_("XMLUI class already registered for {type_}, ignoring").format(
1097 type_=type_)) 1097 type_=type_))
1098 return 1098 return
1130 cls = class_map[CLASS_PANEL] 1130 cls = class_map[CLASS_PANEL]
1131 else: 1131 else:
1132 cls = class_map[CLASS_DIALOG] 1132 cls = class_map[CLASS_DIALOG]
1133 except KeyError: 1133 except KeyError:
1134 raise ClassNotRegistedError( 1134 raise ClassNotRegistedError(
1135 _("You must register classes with registerClass before creating a XMLUI") 1135 _("You must register classes with register_class before creating a XMLUI")
1136 ) 1136 )
1137 1137
1138 xmlui = cls( 1138 xmlui = cls(
1139 host, 1139 host,
1140 parsed_dom, 1140 parsed_dom,