Mercurial > libervia-backend
comparison sat_frontends/jp/xmlui_manager.py @ 2624:56f94936df1e
code style reformatting using black
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 27 Jun 2018 20:14:46 +0200 |
parents | 26edcf3a30eb |
children | bdb8276fd2da |
comparison
equal
deleted
inserted
replaced
2623:49533de4540b | 2624:56f94936df1e |
---|---|
16 | 16 |
17 # You should have received a copy of the GNU Affero General Public License | 17 # You should have received a copy of the GNU Affero General Public License |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 |
20 from sat.core.log import getLogger | 20 from sat.core.log import getLogger |
21 | |
21 log = getLogger(__name__) | 22 log = getLogger(__name__) |
22 from sat_frontends.tools import xmlui as xmlui_manager | 23 from sat_frontends.tools import xmlui as xmlui_manager |
23 from sat_frontends.jp.constants import Const as C | 24 from sat_frontends.jp.constants import Const as C |
24 from sat.tools.common.ansi import ANSI as A | 25 from sat.tools.common.ansi import ANSI as A |
25 from sat.core.i18n import _ | 26 from sat.core.i18n import _ |
26 from functools import partial | 27 from functools import partial |
27 | 28 |
28 # workflow constants | 29 # workflow constants |
29 | 30 |
30 SUBMIT = 'SUBMIT' # submit form | 31 SUBMIT = "SUBMIT" # submit form |
31 | |
32 | 32 |
33 | 33 |
34 ## Widgets ## | 34 ## Widgets ## |
35 | |
35 | 36 |
36 class Base(object): | 37 class Base(object): |
37 """Base for Widget and Container""" | 38 """Base for Widget and Container""" |
39 | |
38 type = None | 40 type = None |
39 _root = None | 41 _root = None |
40 | 42 |
41 def __init__(self, xmlui_parent): | 43 def __init__(self, xmlui_parent): |
42 self.xmlui_parent = xmlui_parent | 44 self.xmlui_parent = xmlui_parent |
56 def disp(self, *args, **kwargs): | 58 def disp(self, *args, **kwargs): |
57 self.host.disp(*args, **kwargs) | 59 self.host.disp(*args, **kwargs) |
58 | 60 |
59 | 61 |
60 class Widget(Base): | 62 class Widget(Base): |
61 category = u'widget' | 63 category = u"widget" |
62 enabled = True | 64 enabled = True |
63 | 65 |
64 @property | 66 @property |
65 def name(self): | 67 def name(self): |
66 return self._xmlui_name | 68 return self._xmlui_name |
83 use self.name if None | 85 use self.name if None |
84 """ | 86 """ |
85 if value is None: | 87 if value is None: |
86 value = self.name | 88 value = self.name |
87 if self.host.verbosity: | 89 if self.host.verbosity: |
88 to_disp = [A.FG_MAGENTA, | 90 to_disp = [ |
89 u' ' if elems else u'', | 91 A.FG_MAGENTA, |
90 u'({})'.format(value), A.RESET] | 92 u" " if elems else u"", |
93 u"({})".format(value), | |
94 A.RESET, | |
95 ] | |
91 if elems is None: | 96 if elems is None: |
92 self.host.disp(A.color(*to_disp)) | 97 self.host.disp(A.color(*to_disp)) |
93 else: | 98 else: |
94 elems.extend(to_disp) | 99 elems.extend(to_disp) |
95 | 100 |
101 | |
96 class ValueWidget(Widget): | 102 class ValueWidget(Widget): |
97 | |
98 def __init__(self, xmlui_parent, value): | 103 def __init__(self, xmlui_parent, value): |
99 super(ValueWidget, self).__init__(xmlui_parent) | 104 super(ValueWidget, self).__init__(xmlui_parent) |
100 self.value = value | 105 self.value = value |
101 | 106 |
102 @property | 107 @property |
103 def values(self): | 108 def values(self): |
104 return [self.value] | 109 return [self.value] |
105 | 110 |
106 | 111 |
107 class InputWidget(ValueWidget): | 112 class InputWidget(ValueWidget): |
108 | |
109 def __init__(self, xmlui_parent, value, read_only=False): | 113 def __init__(self, xmlui_parent, value, read_only=False): |
110 super(InputWidget, self).__init__(xmlui_parent, value) | 114 super(InputWidget, self).__init__(xmlui_parent, value) |
111 self.read_only = read_only | 115 self.read_only = read_only |
112 | 116 |
113 def _xmluiGetValue(self): | 117 def _xmluiGetValue(self): |
114 return self.value | 118 return self.value |
115 | 119 |
116 | 120 |
117 class OptionsWidget(Widget): | 121 class OptionsWidget(Widget): |
118 | |
119 def __init__(self, xmlui_parent, options, selected, style): | 122 def __init__(self, xmlui_parent, options, selected, style): |
120 super(OptionsWidget, self).__init__(xmlui_parent) | 123 super(OptionsWidget, self).__init__(xmlui_parent) |
121 self.options = options | 124 self.options = options |
122 self.selected = selected | 125 self.selected = selected |
123 self.style = style | 126 self.style = style |
155 | 158 |
156 @property | 159 @property |
157 def items(self): | 160 def items(self): |
158 """return suitable items, according to style""" | 161 """return suitable items, according to style""" |
159 no_select = self.no_select | 162 no_select = self.no_select |
160 for value,label in self.options: | 163 for value, label in self.options: |
161 if no_select or value in self.selected: | 164 if no_select or value in self.selected: |
162 yield value,label | 165 yield value, label |
163 | 166 |
164 @property | 167 @property |
165 def inline(self): | 168 def inline(self): |
166 return u'inline' in self.style | 169 return u"inline" in self.style |
167 | 170 |
168 @property | 171 @property |
169 def no_select(self): | 172 def no_select(self): |
170 return u'noselect' in self.style | 173 return u"noselect" in self.style |
171 | 174 |
172 | 175 |
173 class EmptyWidget(xmlui_manager.EmptyWidget, Widget): | 176 class EmptyWidget(xmlui_manager.EmptyWidget, Widget): |
174 | |
175 def __init__(self, _xmlui_parent): | 177 def __init__(self, _xmlui_parent): |
176 Widget.__init__(self) | 178 Widget.__init__(self) |
177 | 179 |
178 | 180 |
179 class TextWidget(xmlui_manager.TextWidget, ValueWidget): | 181 class TextWidget(xmlui_manager.TextWidget, ValueWidget): |
191 try: | 193 try: |
192 return self._xmlui_for_name | 194 return self._xmlui_for_name |
193 except AttributeError: | 195 except AttributeError: |
194 return None | 196 return None |
195 | 197 |
196 def show(self, no_lf=False, ansi=u''): | 198 def show(self, no_lf=False, ansi=u""): |
197 """show label | 199 """show label |
198 | 200 |
199 @param no_lf(bool): same as for [JP.disp] | 201 @param no_lf(bool): same as for [JP.disp] |
200 @param ansi(unicode): ansi escape code to print before label | 202 @param ansi(unicode): ansi escape code to print before label |
201 """ | 203 """ |
210 self.disp(self.value) | 212 self.disp(self.value) |
211 else: | 213 else: |
212 elems = [] | 214 elems = [] |
213 self.verboseName(elems) | 215 self.verboseName(elems) |
214 if self.value: | 216 if self.value: |
215 elems.append(_(u'(enter: {default})').format(default=self.value)) | 217 elems.append(_(u"(enter: {default})").format(default=self.value)) |
216 elems.extend([C.A_HEADER, u'> ']) | 218 elems.extend([C.A_HEADER, u"> "]) |
217 value = raw_input(A.color(*elems)) | 219 value = raw_input(A.color(*elems)) |
218 if value: | 220 if value: |
219 # TODO: empty value should be possible | 221 # TODO: empty value should be possible |
220 # an escape key should be used for default instead of enter with empty value | 222 # an escape key should be used for default instead of enter with empty value |
221 self.value = value | 223 self.value = value |
222 | 224 |
223 | 225 |
224 | |
225 class JidInputWidget(xmlui_manager.JidInputWidget, StringWidget): | 226 class JidInputWidget(xmlui_manager.JidInputWidget, StringWidget): |
226 type = u'jid_input' | 227 type = u"jid_input" |
227 | 228 |
228 | 229 |
229 class TextBoxWidget(xmlui_manager.TextWidget, StringWidget): | 230 class TextBoxWidget(xmlui_manager.TextWidget, StringWidget): |
230 type = u"textbox" | 231 type = u"textbox" |
231 | 232 |
232 | 233 |
233 class ListWidget(xmlui_manager.ListWidget, OptionsWidget): | 234 class ListWidget(xmlui_manager.ListWidget, OptionsWidget): |
234 type = u'list' | 235 type = u"list" |
235 # TODO: handle flags, notably multi | 236 # TODO: handle flags, notably multi |
236 | 237 |
237 def show(self): | 238 def show(self): |
238 if self.root.values_only: | 239 if self.root.values_only: |
239 for value in self.values: | 240 for value in self.values: |
246 self.verboseName() | 247 self.verboseName() |
247 | 248 |
248 for idx, (value, label) in enumerate(self.options): | 249 for idx, (value, label) in enumerate(self.options): |
249 elems = [] | 250 elems = [] |
250 if not self.root.read_only: | 251 if not self.root.read_only: |
251 elems.extend([C.A_SUBHEADER, unicode(idx), A.RESET, u': ']) | 252 elems.extend([C.A_SUBHEADER, unicode(idx), A.RESET, u": "]) |
252 elems.append(label) | 253 elems.append(label) |
253 self.verboseName(elems, value) | 254 self.verboseName(elems, value) |
254 self.disp(A.color(*elems)) | 255 self.disp(A.color(*elems)) |
255 | 256 |
256 if self.root.read_only: | 257 if self.root.read_only: |
259 if len(self.options) == 1: | 260 if len(self.options) == 1: |
260 # we have only one option, no need to ask | 261 # we have only one option, no need to ask |
261 self.value = self.options[0][0] | 262 self.value = self.options[0][0] |
262 return | 263 return |
263 | 264 |
264 # we ask use to choose an option | 265 # we ask use to choose an option |
265 choice = None | 266 choice = None |
266 limit_max = len(self.options)-1 | 267 limit_max = len(self.options) - 1 |
267 while choice is None or choice<0 or choice>limit_max: | 268 while choice is None or choice < 0 or choice > limit_max: |
268 choice = raw_input(A.color(C.A_HEADER, _(u'your choice (0-{max}): ').format(max=limit_max))) | 269 choice = raw_input( |
270 A.color(C.A_HEADER, _(u"your choice (0-{max}): ").format(max=limit_max)) | |
271 ) | |
269 try: | 272 try: |
270 choice = int(choice) | 273 choice = int(choice) |
271 except ValueError: | 274 except ValueError: |
272 choice = None | 275 choice = None |
273 self.value = self.options[choice][0] | 276 self.value = self.options[choice][0] |
274 self.disp('') | 277 self.disp("") |
275 | 278 |
276 | 279 |
277 class BoolWidget(xmlui_manager.BoolWidget, InputWidget): | 280 class BoolWidget(xmlui_manager.BoolWidget, InputWidget): |
278 type = u'bool' | 281 type = u"bool" |
279 | 282 |
280 def show(self): | 283 def show(self): |
281 disp_true = A.color(A.FG_GREEN, u'TRUE') | 284 disp_true = A.color(A.FG_GREEN, u"TRUE") |
282 disp_false = A.color(A.FG_RED,u'FALSE') | 285 disp_false = A.color(A.FG_RED, u"FALSE") |
283 if self.read_only: | 286 if self.read_only: |
284 self.disp(disp_true if self.value else disp_false) | 287 self.disp(disp_true if self.value else disp_false) |
285 else: | 288 else: |
286 self.disp(A.color(C.A_HEADER, u'0: ', disp_false)) | 289 self.disp(A.color(C.A_HEADER, u"0: ", disp_false)) |
287 self.disp(A.color(C.A_HEADER, u'1: ', disp_true)) | 290 self.disp(A.color(C.A_HEADER, u"1: ", disp_true)) |
288 choice = None | 291 choice = None |
289 while choice not in ('0', '1'): | 292 while choice not in ("0", "1"): |
290 elems = [C.A_HEADER, _(u'your choice (0,1): ')] | 293 elems = [C.A_HEADER, _(u"your choice (0,1): ")] |
291 self.verboseName(elems) | 294 self.verboseName(elems) |
292 choice = raw_input(A.color(*elems)) | 295 choice = raw_input(A.color(*elems)) |
293 self.value = bool(int(choice)) | 296 self.value = bool(int(choice)) |
294 self.disp('') | 297 self.disp("") |
295 | 298 |
296 def _xmluiGetValue(self): | 299 def _xmluiGetValue(self): |
297 return C.boolConst(self.value) | 300 return C.boolConst(self.value) |
298 | 301 |
302 | |
299 ## Containers ## | 303 ## Containers ## |
300 | 304 |
305 | |
301 class Container(Base): | 306 class Container(Base): |
302 category = u'container' | 307 category = u"container" |
303 | 308 |
304 def __init__(self, xmlui_parent): | 309 def __init__(self, xmlui_parent): |
305 super(Container, self).__init__(xmlui_parent) | 310 super(Container, self).__init__(xmlui_parent) |
306 self.children = [] | 311 self.children = [] |
307 | 312 |
318 for child in self.children: | 323 for child in self.children: |
319 child.show() | 324 child.show() |
320 | 325 |
321 | 326 |
322 class VerticalContainer(xmlui_manager.VerticalContainer, Container): | 327 class VerticalContainer(xmlui_manager.VerticalContainer, Container): |
323 type = u'vertical' | 328 type = u"vertical" |
324 | 329 |
325 | 330 |
326 class PairsContainer(xmlui_manager.PairsContainer, Container): | 331 class PairsContainer(xmlui_manager.PairsContainer, Container): |
327 type = u'pairs' | 332 type = u"pairs" |
328 | 333 |
329 | 334 |
330 class LabelContainer(xmlui_manager.PairsContainer, Container): | 335 class LabelContainer(xmlui_manager.PairsContainer, Container): |
331 type = u'label' | 336 type = u"label" |
332 | 337 |
333 def show(self): | 338 def show(self): |
334 for child in self.children: | 339 for child in self.children: |
335 no_lf = False | 340 no_lf = False |
336 # we check linked widget type | 341 # we check linked widget type |
337 # to see if we want the label on the same line or not | 342 # to see if we want the label on the same line or not |
338 if child.type == u'label': | 343 if child.type == u"label": |
339 for_name = child.for_name | 344 for_name = child.for_name |
340 if for_name is not None: | 345 if for_name is not None: |
341 for_widget = self.root.widgets[for_name] | 346 for_widget = self.root.widgets[for_name] |
342 wid_type = for_widget.type | 347 wid_type = for_widget.type |
343 if self.root.values_only or wid_type in ('text', 'string', 'jid_input'): | 348 if self.root.values_only or wid_type in ( |
349 "text", | |
350 "string", | |
351 "jid_input", | |
352 ): | |
344 no_lf = True | 353 no_lf = True |
345 elif wid_type == 'bool' and for_widget.read_only: | 354 elif wid_type == "bool" and for_widget.read_only: |
346 no_lf = True | 355 no_lf = True |
347 child.show(no_lf=no_lf, ansi=A.FG_CYAN) | 356 child.show(no_lf=no_lf, ansi=A.FG_CYAN) |
348 else: | 357 else: |
349 child.show() | 358 child.show() |
350 | 359 |
360 | |
351 ## Dialogs ## | 361 ## Dialogs ## |
352 | 362 |
353 | 363 |
354 class Dialog(object): | 364 class Dialog(object): |
355 | |
356 def __init__(self, xmlui_parent): | 365 def __init__(self, xmlui_parent): |
357 self.xmlui_parent = xmlui_parent | 366 self.xmlui_parent = xmlui_parent |
358 self.host = self.xmlui_parent.host | 367 self.host = self.xmlui_parent.host |
359 | 368 |
360 def disp(self, *args, **kwargs): | 369 def disp(self, *args, **kwargs): |
367 """ | 376 """ |
368 raise NotImplementedError(self.__class__) | 377 raise NotImplementedError(self.__class__) |
369 | 378 |
370 | 379 |
371 class NoteDialog(xmlui_manager.NoteDialog, Dialog): | 380 class NoteDialog(xmlui_manager.NoteDialog, Dialog): |
372 | |
373 def show(self): | 381 def show(self): |
374 # TODO: handle title and level | 382 # TODO: handle title and level |
375 self.disp(self.message) | 383 self.disp(self.message) |
376 | 384 |
377 def __init__(self, _xmlui_parent, title, message, level): | 385 def __init__(self, _xmlui_parent, title, message, level): |
378 Dialog.__init__(self, _xmlui_parent) | 386 Dialog.__init__(self, _xmlui_parent) |
379 xmlui_manager.NoteDialog.__init__(self, _xmlui_parent) | 387 xmlui_manager.NoteDialog.__init__(self, _xmlui_parent) |
380 self.title, self.message, self.level = title, message, level | 388 self.title, self.message, self.level = title, message, level |
381 | 389 |
390 | |
382 ## Factory ## | 391 ## Factory ## |
383 | 392 |
384 | 393 |
385 class WidgetFactory(object): | 394 class WidgetFactory(object): |
386 | |
387 def __getattr__(self, attr): | 395 def __getattr__(self, attr): |
388 if attr.startswith("create"): | 396 if attr.startswith("create"): |
389 cls = globals()[attr[6:]] | 397 cls = globals()[attr[6:]] |
390 return cls | 398 return cls |
391 | 399 |
396 read_only = False | 404 read_only = False |
397 values_only = False | 405 values_only = False |
398 workflow = None | 406 workflow = None |
399 _submit_cb = None | 407 _submit_cb = None |
400 | 408 |
401 def __init__(self, host, parsed_dom, title=None, flags=None, callback=None, ignore=None, whitelist=None, profile=None): | 409 def __init__( |
402 xmlui_manager.XMLUIPanel.__init__(self, | 410 self, |
403 host, | 411 host, |
404 parsed_dom, | 412 parsed_dom, |
405 title = title, | 413 title=None, |
406 flags = flags, | 414 flags=None, |
407 ignore = ignore, | 415 callback=None, |
408 whitelist = whitelist, | 416 ignore=None, |
409 profile=host.profile) | 417 whitelist=None, |
418 profile=None, | |
419 ): | |
420 xmlui_manager.XMLUIPanel.__init__( | |
421 self, | |
422 host, | |
423 parsed_dom, | |
424 title=title, | |
425 flags=flags, | |
426 ignore=ignore, | |
427 whitelist=whitelist, | |
428 profile=host.profile, | |
429 ) | |
410 self.submitted = False | 430 self.submitted = False |
411 | 431 |
412 @property | 432 @property |
413 def command(self): | 433 def command(self): |
414 return self.host.command | 434 return self.host.command |
453 self.submit_id = None # avoid double submit | 473 self.submit_id = None # avoid double submit |
454 return | 474 return |
455 elif isinstance(cmd, list): | 475 elif isinstance(cmd, list): |
456 name, value = cmd | 476 name, value = cmd |
457 widget = self.widgets[name] | 477 widget = self.widgets[name] |
458 if widget.type == 'bool': | 478 if widget.type == "bool": |
459 value = C.bool(value) | 479 value = C.bool(value) |
460 widget.value = value | 480 widget.value = value |
461 self.show() | 481 self.show() |
462 | 482 |
463 def submitForm(self, callback=None): | 483 def submitForm(self, callback=None): |
464 XMLUIPanel._submit_cb = callback | 484 XMLUIPanel._submit_cb = callback |
465 self.onFormSubmitted() | 485 self.onFormSubmitted() |
466 | 486 |
467 def onFormSubmitted(self, ignore=None): | 487 def onFormSubmitted(self, ignore=None): |
468 # self.submitted is a Q&D workaround to avoid | 488 # self.submitted is a Q&D workaround to avoid |
469 # double submit when a workflow is set | 489 # double submit when a workflow is set |
470 if self.submitted: | 490 if self.submitted: |
471 return | 491 return |
472 self.submitted = True | 492 self.submitted = True |
473 super(XMLUIPanel, self).onFormSubmitted(ignore) | 493 super(XMLUIPanel, self).onFormSubmitted(ignore) |
476 pass | 496 pass |
477 | 497 |
478 def _launchActionCb(self, data): | 498 def _launchActionCb(self, data): |
479 XMLUIPanel._actions -= 1 | 499 XMLUIPanel._actions -= 1 |
480 assert XMLUIPanel._actions >= 0 | 500 assert XMLUIPanel._actions >= 0 |
481 if u'xmlui' in data: | 501 if u"xmlui" in data: |
482 xmlui_raw = data['xmlui'] | 502 xmlui_raw = data["xmlui"] |
483 xmlui = xmlui_manager.create(self.host, xmlui_raw) | 503 xmlui = xmlui_manager.create(self.host, xmlui_raw) |
484 xmlui.show() | 504 xmlui.show() |
485 if xmlui.submit_id: | 505 if xmlui.submit_id: |
486 xmlui.onFormSubmitted() | 506 xmlui.onFormSubmitted() |
487 # TODO: handle data other than XMLUI | 507 # TODO: handle data other than XMLUI |
496 self.host.bridge.launchAction( | 516 self.host.bridge.launchAction( |
497 action_id, | 517 action_id, |
498 data, | 518 data, |
499 self.profile, | 519 self.profile, |
500 callback=self._launchActionCb, | 520 callback=self._launchActionCb, |
501 errback=partial(self.command.errback, | 521 errback=partial( |
502 msg=_(u"can't launch XMLUI action: {}"), | 522 self.command.errback, |
503 exit_code=C.EXIT_BRIDGE_ERRBACK)) | 523 msg=_(u"can't launch XMLUI action: {}"), |
524 exit_code=C.EXIT_BRIDGE_ERRBACK, | |
525 ), | |
526 ) | |
504 | 527 |
505 | 528 |
506 class XMLUIDialog(xmlui_manager.XMLUIDialog): | 529 class XMLUIDialog(xmlui_manager.XMLUIDialog): |
507 type = 'dialog' | 530 type = "dialog" |
508 dialog_factory = WidgetFactory() | 531 dialog_factory = WidgetFactory() |
509 read_only = False | 532 read_only = False |
510 | 533 |
511 def show(self, dummy=None): | 534 def show(self, dummy=None): |
512 self.dlg.show() | 535 self.dlg.show() |