comparison sat_frontends/jp/xmlui_manager.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 53a8b50d69ca
children 2594e1951cf7
comparison
equal deleted inserted replaced
4036:c4464d7ae97b 4037:524856bd7b19
72 72
73 must be overriden by subclasses 73 must be overriden by subclasses
74 """ 74 """
75 raise NotImplementedError(self.__class__) 75 raise NotImplementedError(self.__class__)
76 76
77 def verboseName(self, elems=None, value=None): 77 def verbose_name(self, elems=None, value=None):
78 """add name in color to the elements 78 """add name in color to the elements
79 79
80 helper method to display name which can then be used to automate commands 80 helper method to display name which can then be used to automate commands
81 elems is only modified if verbosity is > 0 81 elems is only modified if verbosity is > 0
82 @param elems(list[unicode], None): elements to display 82 @param elems(list[unicode], None): elements to display
112 class InputWidget(ValueWidget): 112 class InputWidget(ValueWidget):
113 def __init__(self, xmlui_parent, value, read_only=False): 113 def __init__(self, xmlui_parent, value, read_only=False):
114 super(InputWidget, self).__init__(xmlui_parent, value) 114 super(InputWidget, self).__init__(xmlui_parent, value)
115 self.read_only = read_only 115 self.read_only = read_only
116 116
117 def _xmluiGetValue(self): 117 def _xmlui_get_value(self):
118 return self.value 118 return self.value
119 119
120 120
121 class OptionsWidget(Widget): 121 class OptionsWidget(Widget):
122 def __init__(self, xmlui_parent, options, selected, style): 122 def __init__(self, xmlui_parent, options, selected, style):
139 139
140 @value.setter 140 @value.setter
141 def value(self, value): 141 def value(self, value):
142 self.selected = [value] 142 self.selected = [value]
143 143
144 def _xmluiSelectValue(self, value): 144 def _xmlui_select_value(self, value):
145 self.value = value 145 self.value = value
146 146
147 def _xmluiSelectValues(self, values): 147 def _xmlui_select_values(self, values):
148 self.values = values 148 self.values = values
149 149
150 def _xmluiGetSelectedValues(self): 150 def _xmlui_get_selected_values(self):
151 return self.values 151 return self.values
152 152
153 @property 153 @property
154 def labels(self): 154 def labels(self):
155 """return only labels from self.items""" 155 """return only labels from self.items"""
217 async def show(self): 217 async def show(self):
218 if self.read_only or self.root.read_only: 218 if self.read_only or self.root.read_only:
219 self.disp(self.value) 219 self.disp(self.value)
220 else: 220 else:
221 elems = [] 221 elems = []
222 self.verboseName(elems) 222 self.verbose_name(elems)
223 if self.value: 223 if self.value:
224 elems.append(_("(enter: {value})").format(value=self.value)) 224 elems.append(_("(enter: {value})").format(value=self.value))
225 elems.extend([C.A_HEADER, "> "]) 225 elems.extend([C.A_HEADER, "> "])
226 value = await self.host.ainput(A.color(*elems)) 226 value = await self.host.ainput(A.color(*elems))
227 if value: 227 if value:
241 class TextBoxWidget(xmlui_base.TextWidget, StringWidget): 241 class TextBoxWidget(xmlui_base.TextWidget, StringWidget):
242 type = "textbox" 242 type = "textbox"
243 # TODO: use a more advanced input method 243 # TODO: use a more advanced input method
244 244
245 async def show(self): 245 async def show(self):
246 self.verboseName() 246 self.verbose_name()
247 if self.read_only or self.root.read_only: 247 if self.read_only or self.root.read_only:
248 self.disp(self.value) 248 self.disp(self.value)
249 else: 249 else:
250 if self.value: 250 if self.value:
251 self.disp( 251 self.disp(
273 273
274 async def show(self): 274 async def show(self):
275 # FIXME: we use bridge in a blocking way as permitted by python-dbus 275 # FIXME: we use bridge in a blocking way as permitted by python-dbus
276 # this only for now to make it simpler, it must be refactored 276 # this only for now to make it simpler, it must be refactored
277 # to use async when jp will be fully async (expected for 0.8) 277 # to use async when jp will be fully async (expected for 0.8)
278 self.value = await self.host.bridge.syntaxConvert( 278 self.value = await self.host.bridge.syntax_convert(
279 self.value, C.SYNTAX_XHTML, "markdown", False, self.host.profile 279 self.value, C.SYNTAX_XHTML, "markdown", False, self.host.profile
280 ) 280 )
281 await super(XHTMLBoxWidget, self).show() 281 await super(XHTMLBoxWidget, self).show()
282 282
283 283
292 return 292 return
293 if not self.options: 293 if not self.options:
294 return 294 return
295 295
296 # list display 296 # list display
297 self.verboseName() 297 self.verbose_name()
298 298
299 for idx, (value, label) in enumerate(self.options): 299 for idx, (value, label) in enumerate(self.options):
300 elems = [] 300 elems = []
301 if not self.root.read_only: 301 if not self.root.read_only:
302 elems.extend([C.A_SUBHEADER, str(idx), A.RESET, ": "]) 302 elems.extend([C.A_SUBHEADER, str(idx), A.RESET, ": "])
303 elems.append(label) 303 elems.append(label)
304 self.verboseName(elems, value) 304 self.verbose_name(elems, value)
305 self.disp(A.color(*elems)) 305 self.disp(A.color(*elems))
306 306
307 if self.root.read_only: 307 if self.root.read_only:
308 return 308 return
309 309
348 A.color(C.A_HEADER, "1: ", disp_true, A.RESET, " *" if self.value else "") 348 A.color(C.A_HEADER, "1: ", disp_true, A.RESET, " *" if self.value else "")
349 ) 349 )
350 choice = None 350 choice = None
351 while choice not in ("0", "1"): 351 while choice not in ("0", "1"):
352 elems = [C.A_HEADER, _("your choice (0,1): ")] 352 elems = [C.A_HEADER, _("your choice (0,1): ")]
353 self.verboseName(elems) 353 self.verbose_name(elems)
354 choice = await self.host.ainput(A.color(*elems)) 354 choice = await self.host.ainput(A.color(*elems))
355 self.value = bool(int(choice)) 355 self.value = bool(int(choice))
356 self.disp("") 356 self.disp("")
357 357
358 def _xmluiGetValue(self): 358 def _xmlui_get_value(self):
359 return C.boolConst(self.value) 359 return C.bool_const(self.value)
360 360
361 ## Containers ## 361 ## Containers ##
362 362
363 363
364 class Container(Base): 364 class Container(Base):
369 self.children = [] 369 self.children = []
370 370
371 def __iter__(self): 371 def __iter__(self):
372 return iter(self.children) 372 return iter(self.children)
373 373
374 def _xmluiAppend(self, widget): 374 def _xmlui_append(self, widget):
375 self.children.append(widget) 375 self.children.append(widget)
376 376
377 def _xmluiRemove(self, widget): 377 def _xmlui_remove(self, widget):
378 self.children.remove(widget) 378 self.children.remove(widget)
379 379
380 async def show(self): 380 async def show(self):
381 for child in self.children: 381 for child in self.children:
382 await child.show() 382 await child.show()
484 input_ = None 484 input_ = None
485 while input_ not in ("y", "n"): 485 while input_ not in ("y", "n"):
486 input_ = await self.host.ainput(f"{self.message} (y/n)? ") 486 input_ = await self.host.ainput(f"{self.message} (y/n)? ")
487 input_ = input_.lower() 487 input_ = input_.lower()
488 if input_ == "y": 488 if input_ == "y":
489 self._xmluiValidated() 489 self._xmlui_validated()
490 else: 490 else:
491 self._xmluiCancelled() 491 self._xmlui_cancelled()
492 492
493 ## Factory ## 493 ## Factory ##
494 494
495 495
496 class WidgetFactory(object): 496 class WidgetFactory(object):
500 return cls 500 return cls
501 501
502 502
503 class XMLUIPanel(xmlui_base.AIOXMLUIPanel): 503 class XMLUIPanel(xmlui_base.AIOXMLUIPanel):
504 widget_factory = WidgetFactory() 504 widget_factory = WidgetFactory()
505 _actions = 0 # use to keep track of bridge's launchAction calls 505 _actions = 0 # use to keep track of bridge's action_launch calls
506 read_only = False 506 read_only = False
507 values_only = False 507 values_only = False
508 workflow = None 508 workflow = None
509 _submit_cb = None 509 _submit_cb = None
510 510
555 if self.values_only: 555 if self.values_only:
556 self.read_only = True 556 self.read_only = True
557 if workflow: 557 if workflow:
558 XMLUIPanel.workflow = workflow 558 XMLUIPanel.workflow = workflow
559 if XMLUIPanel.workflow: 559 if XMLUIPanel.workflow:
560 await self.runWorkflow() 560 await self.run_workflow()
561 else: 561 else:
562 await self.main_cont.show() 562 await self.main_cont.show()
563 563
564 async def runWorkflow(self): 564 async def run_workflow(self):
565 """loop into workflow commands and execute commands 565 """loop into workflow commands and execute commands
566 566
567 SUBMIT will interrupt workflow (which will be continue on callback) 567 SUBMIT will interrupt workflow (which will be continue on callback)
568 @param workflow(list): same as [show] 568 @param workflow(list): same as [show]
569 """ 569 """
572 try: 572 try:
573 cmd = workflow.pop(0) 573 cmd = workflow.pop(0)
574 except IndexError: 574 except IndexError:
575 break 575 break
576 if cmd == SUBMIT: 576 if cmd == SUBMIT:
577 await self.onFormSubmitted() 577 await self.on_form_submitted()
578 self.submit_id = None # avoid double submit 578 self.submit_id = None # avoid double submit
579 return 579 return
580 elif isinstance(cmd, list): 580 elif isinstance(cmd, list):
581 name, value = cmd 581 name, value = cmd
582 widget = self.widgets[name] 582 widget = self.widgets[name]
583 if widget.type == "bool": 583 if widget.type == "bool":
584 value = C.bool(value) 584 value = C.bool(value)
585 widget.value = value 585 widget.value = value
586 await self.show() 586 await self.show()
587 587
588 async def submitForm(self, callback=None): 588 async def submit_form(self, callback=None):
589 XMLUIPanel._submit_cb = callback 589 XMLUIPanel._submit_cb = callback
590 await self.onFormSubmitted() 590 await self.on_form_submitted()
591 591
592 async def onFormSubmitted(self, ignore=None): 592 async def on_form_submitted(self, ignore=None):
593 # self.submitted is a Q&D workaround to avoid 593 # self.submitted is a Q&D workaround to avoid
594 # double submit when a workflow is set 594 # double submit when a workflow is set
595 if self.submitted: 595 if self.submitted:
596 return 596 return
597 self.submitted = True 597 self.submitted = True
598 await super(XMLUIPanel, self).onFormSubmitted(ignore) 598 await super(XMLUIPanel, self).on_form_submitted(ignore)
599 599
600 def _xmluiClose(self): 600 def _xmlui_close(self):
601 pass 601 pass
602 602
603 async def _launchActionCb(self, data): 603 async def _launch_action_cb(self, data):
604 XMLUIPanel._actions -= 1 604 XMLUIPanel._actions -= 1
605 assert XMLUIPanel._actions >= 0 605 assert XMLUIPanel._actions >= 0
606 if "xmlui" in data: 606 if "xmlui" in data:
607 xmlui_raw = data["xmlui"] 607 xmlui_raw = data["xmlui"]
608 xmlui = create(self.host, xmlui_raw) 608 xmlui = create(self.host, xmlui_raw)
609 await xmlui.show() 609 await xmlui.show()
610 if xmlui.submit_id: 610 if xmlui.submit_id:
611 await xmlui.onFormSubmitted() 611 await xmlui.on_form_submitted()
612 # TODO: handle data other than XMLUI 612 # TODO: handle data other than XMLUI
613 if not XMLUIPanel._actions: 613 if not XMLUIPanel._actions:
614 if self._submit_cb is None: 614 if self._submit_cb is None:
615 self.host.quit() 615 self.host.quit()
616 else: 616 else:
617 self._submit_cb() 617 self._submit_cb()
618 618
619 async def _xmluiLaunchAction(self, action_id, data): 619 async def _xmlui_launch_action(self, action_id, data):
620 XMLUIPanel._actions += 1 620 XMLUIPanel._actions += 1
621 try: 621 try:
622 data = await self.host.bridge.launchAction( 622 data = await self.host.bridge.action_launch(
623 action_id, 623 action_id,
624 data, 624 data,
625 self.profile, 625 self.profile,
626 ) 626 )
627 except Exception as e: 627 except Exception as e:
628 self.disp(f"can't launch XMLUI action: {e}", error=True) 628 self.disp(f"can't launch XMLUI action: {e}", error=True)
629 self.host.quit(C.EXIT_BRIDGE_ERRBACK) 629 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
630 else: 630 else:
631 await self._launchActionCb(data) 631 await self._launch_action_cb(data)
632 632
633 633
634 class XMLUIDialog(xmlui_base.XMLUIDialog): 634 class XMLUIDialog(xmlui_base.XMLUIDialog):
635 type = "dialog" 635 type = "dialog"
636 dialog_factory = WidgetFactory() 636 dialog_factory = WidgetFactory()
637 read_only = False 637 read_only = False
638 638
639 async def show(self, __=None): 639 async def show(self, __=None):
640 await self.dlg.show() 640 await self.dlg.show()
641 641
642 def _xmluiClose(self): 642 def _xmlui_close(self):
643 pass 643 pass
644 644
645 645
646 create = partial( 646 create = partial(
647 xmlui_base.create, 647 xmlui_base.create,