Mercurial > libervia-backend
comparison frontends/src/primitivus/xmlui.py @ 1106:e2e1e27a3680
frontends: XMLUI refactoring + dialogs:
- there are now XMLUIPanel and XMLUIDialog both inheriting from XMLUIBase
- following dialogs are managed:
- MessageDialog
- NoteDialog
- ConfirmDialog
- FileDialog
- XMLUI creation is now made using xmlui.create(...) instead of instanciating directly XMLUI
- classes must be registed in frontends
- "parent" attribute renamed to "_xmlui_parent" to avoid name conflicts with frontends toolkits
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 13 Aug 2014 14:48:49 +0200 |
parents | 7a39ae3950f7 |
children | 6184779544c7 |
comparison
equal
deleted
inserted
replaced
1105:018bdd687747 | 1106:e2e1e27a3680 |
---|---|
19 | 19 |
20 from sat.core.i18n import _ | 20 from sat.core.i18n import _ |
21 import urwid | 21 import urwid |
22 import copy | 22 import copy |
23 from urwid_satext import sat_widgets | 23 from urwid_satext import sat_widgets |
24 from urwid_satext import files_management | |
24 from sat.core.log import getLogger | 25 from sat.core.log import getLogger |
25 log = getLogger(__name__) | 26 log = getLogger(__name__) |
27 from sat_frontends.primitivus.constants import Const as C | |
26 from sat_frontends.tools import xmlui | 28 from sat_frontends.tools import xmlui |
27 | 29 |
28 | 30 |
29 class PrimitivusEvents(object): | 31 class PrimitivusEvents(object): |
30 """ Used to manage change event of Primitivus widgets """ | 32 """ Used to manage change event of Primitivus widgets """ |
31 | 33 |
32 def _event_callback(self, ctrl, *args, **ktkwargs): | 34 def _event_callback(self, ctrl, *args, **kwargs): |
33 """" Call xmlui callback and ignore any extra argument """ | 35 """" Call xmlui callback and ignore any extra argument """ |
34 args[-1](ctrl) | 36 args[-1](ctrl) |
35 | 37 |
36 def _xmluiOnChange(self, callback): | 38 def _xmluiOnChange(self, callback): |
37 """ Call callback with widget as only argument """ | 39 """ Call callback with widget as only argument """ |
38 urwid.connect_signal(self, 'change', self._event_callback, callback) | 40 urwid.connect_signal(self, 'change', self._event_callback, callback) |
39 | 41 |
40 | 42 |
41 class PrimitivusEmptyWidget(xmlui.EmptyWidget, urwid.Text): | 43 class PrimitivusEmptyWidget(xmlui.EmptyWidget, urwid.Text): |
42 | 44 |
43 def __init__(self, parent): | 45 def __init__(self, _xmlui_parent): |
44 urwid.Text.__init__(self, '') | 46 urwid.Text.__init__(self, '') |
45 | 47 |
46 | 48 |
47 class PrimitivusTextWidget(xmlui.TextWidget, urwid.Text): | 49 class PrimitivusTextWidget(xmlui.TextWidget, urwid.Text): |
48 | 50 |
49 def __init__(self, parent, value, read_only=False): | 51 def __init__(self, _xmlui_parent, value, read_only=False): |
50 urwid.Text.__init__(self, value) | 52 urwid.Text.__init__(self, value) |
51 | 53 |
52 | 54 |
53 class PrimitivusLabelWidget(xmlui.LabelWidget, PrimitivusTextWidget): | 55 class PrimitivusLabelWidget(xmlui.LabelWidget, PrimitivusTextWidget): |
54 | 56 |
55 def __init__(self, parent, value): | 57 def __init__(self, _xmlui_parent, value): |
56 super(PrimitivusLabelWidget, self).__init__(parent, value+": ") | 58 super(PrimitivusLabelWidget, self).__init__(_xmlui_parent, value+": ") |
57 | 59 |
58 | 60 |
59 class PrimitivusJidWidget(xmlui.JidWidget, PrimitivusTextWidget): | 61 class PrimitivusJidWidget(xmlui.JidWidget, PrimitivusTextWidget): |
60 pass | 62 pass |
61 | 63 |
62 | 64 |
63 class PrimitivusDividerWidget(xmlui.DividerWidget, urwid.Divider): | 65 class PrimitivusDividerWidget(xmlui.DividerWidget, urwid.Divider): |
64 | 66 |
65 def __init__(self, parent, style='line'): | 67 def __init__(self, _xmlui_parent, style='line'): |
66 if style == 'line': | 68 if style == 'line': |
67 div_char = u'─' | 69 div_char = u'─' |
68 elif style == 'dot': | 70 elif style == 'dot': |
69 div_char = u'·' | 71 div_char = u'·' |
70 elif style == 'dash': | 72 elif style == 'dash': |
80 urwid.Divider.__init__(self, div_char) | 82 urwid.Divider.__init__(self, div_char) |
81 | 83 |
82 | 84 |
83 class PrimitivusStringWidget(xmlui.StringWidget, sat_widgets.AdvancedEdit, PrimitivusEvents): | 85 class PrimitivusStringWidget(xmlui.StringWidget, sat_widgets.AdvancedEdit, PrimitivusEvents): |
84 | 86 |
85 def __init__(self, parent, value, read_only=False): | 87 def __init__(self, _xmlui_parent, value, read_only=False): |
86 sat_widgets.AdvancedEdit.__init__(self, edit_text=value) | 88 sat_widgets.AdvancedEdit.__init__(self, edit_text=value) |
87 self.read_only = read_only | 89 self.read_only = read_only |
88 | 90 |
89 def selectable(self): | 91 def selectable(self): |
90 if self.read_only: | 92 if self.read_only: |
98 return self.get_edit_text() | 100 return self.get_edit_text() |
99 | 101 |
100 | 102 |
101 class PrimitivusPasswordWidget(xmlui.PasswordWidget, sat_widgets.Password, PrimitivusEvents): | 103 class PrimitivusPasswordWidget(xmlui.PasswordWidget, sat_widgets.Password, PrimitivusEvents): |
102 | 104 |
103 def __init__(self, parent, value, read_only=False): | 105 def __init__(self, _xmlui_parent, value, read_only=False): |
104 sat_widgets.Password.__init__(self, edit_text=value) | 106 sat_widgets.Password.__init__(self, edit_text=value) |
105 self.read_only = read_only | 107 self.read_only = read_only |
106 | 108 |
107 def selectable(self): | 109 def selectable(self): |
108 if self.read_only: | 110 if self.read_only: |
116 return self.get_edit_text() | 118 return self.get_edit_text() |
117 | 119 |
118 | 120 |
119 class PrimitivusTextBoxWidget(xmlui.TextBoxWidget, sat_widgets.AdvancedEdit, PrimitivusEvents): | 121 class PrimitivusTextBoxWidget(xmlui.TextBoxWidget, sat_widgets.AdvancedEdit, PrimitivusEvents): |
120 | 122 |
121 def __init__(self, parent, value, read_only=False): | 123 def __init__(self, _xmlui_parent, value, read_only=False): |
122 sat_widgets.AdvancedEdit.__init__(self, edit_text=value, multiline=True) | 124 sat_widgets.AdvancedEdit.__init__(self, edit_text=value, multiline=True) |
123 self.read_only = read_only | 125 self.read_only = read_only |
124 | 126 |
125 def selectable(self): | 127 def selectable(self): |
126 if self.read_only: | 128 if self.read_only: |
134 return self.get_edit_text() | 136 return self.get_edit_text() |
135 | 137 |
136 | 138 |
137 class PrimitivusBoolWidget(xmlui.BoolWidget, urwid.CheckBox, PrimitivusEvents): | 139 class PrimitivusBoolWidget(xmlui.BoolWidget, urwid.CheckBox, PrimitivusEvents): |
138 | 140 |
139 def __init__(self, parent, state, read_only=False): | 141 def __init__(self, _xmlui_parent, state, read_only=False): |
140 urwid.CheckBox.__init__(self, '', state=state) | 142 urwid.CheckBox.__init__(self, '', state=state) |
141 self.read_only = read_only | 143 self.read_only = read_only |
142 | 144 |
143 def selectable(self): | 145 def selectable(self): |
144 if self.read_only: | 146 if self.read_only: |
152 return "true" if self.get_state() else "false" | 154 return "true" if self.get_state() else "false" |
153 | 155 |
154 | 156 |
155 class PrimitivusButtonWidget(xmlui.ButtonWidget, sat_widgets.CustomButton, PrimitivusEvents): | 157 class PrimitivusButtonWidget(xmlui.ButtonWidget, sat_widgets.CustomButton, PrimitivusEvents): |
156 | 158 |
157 def __init__(self, parent, value, click_callback): | 159 def __init__(self, _xmlui_parent, value, click_callback): |
158 sat_widgets.CustomButton.__init__(self, value, on_press=click_callback) | 160 sat_widgets.CustomButton.__init__(self, value, on_press=click_callback) |
159 | 161 |
160 def _xmluiOnClick(self, callback): | 162 def _xmluiOnClick(self, callback): |
161 urwid.connect_signal(self, 'click', callback) | 163 urwid.connect_signal(self, 'click', callback) |
162 | 164 |
163 | 165 |
164 class PrimitivusListWidget(xmlui.ListWidget, sat_widgets.List, PrimitivusEvents): | 166 class PrimitivusListWidget(xmlui.ListWidget, sat_widgets.List, PrimitivusEvents): |
165 | 167 |
166 def __init__(self, parent, options, selected, flags): | 168 def __init__(self, _xmlui_parent, options, selected, flags): |
167 sat_widgets.List.__init__(self, options=options, style=flags) | 169 sat_widgets.List.__init__(self, options=options, style=flags) |
168 self._xmluiSelectValues(selected) | 170 self._xmluiSelectValues(selected) |
169 | 171 |
170 def _xmluiSelectValue(self, value): | 172 def _xmluiSelectValue(self, value): |
171 return self.selectValue(value) | 173 return self.selectValue(value) |
192 self._xmluiSelectValues(selected) | 194 self._xmluiSelectValues(selected) |
193 | 195 |
194 | 196 |
195 class PrimitivusAdvancedListContainer(xmlui.AdvancedListContainer, sat_widgets.TableContainer, PrimitivusEvents): | 197 class PrimitivusAdvancedListContainer(xmlui.AdvancedListContainer, sat_widgets.TableContainer, PrimitivusEvents): |
196 | 198 |
197 def __init__(self, parent, columns, selectable='no'): | 199 def __init__(self, _xmlui_parent, columns, selectable='no'): |
198 options = {'ADAPT':()} | 200 options = {'ADAPT':()} |
199 if selectable != 'no': | 201 if selectable != 'no': |
200 options['HIGHLIGHT'] = () | 202 options['HIGHLIGHT'] = () |
201 sat_widgets.TableContainer.__init__(self, columns=columns, options=options, row_selectable = selectable!='no') | 203 sat_widgets.TableContainer.__init__(self, columns=columns, options=options, row_selectable = selectable!='no') |
202 | 204 |
217 urwid.connect_signal(self, 'click', self._event_callback, callback) | 219 urwid.connect_signal(self, 'click', self._event_callback, callback) |
218 | 220 |
219 | 221 |
220 class PrimitivusPairsContainer(xmlui.PairsContainer, sat_widgets.TableContainer): | 222 class PrimitivusPairsContainer(xmlui.PairsContainer, sat_widgets.TableContainer): |
221 | 223 |
222 def __init__(self, parent): | 224 def __init__(self, _xmlui_parent): |
223 options = {'ADAPT':(0,), 'HIGHLIGHT':(0,)} | 225 options = {'ADAPT':(0,), 'HIGHLIGHT':(0,)} |
224 if self._xmlui_main.type == 'param': | 226 if self._xmlui_main.type == 'param': |
225 options['FOCUS_ATTR'] = 'param_selected' | 227 options['FOCUS_ATTR'] = 'param_selected' |
226 sat_widgets.TableContainer.__init__(self, columns=2, options=options) | 228 sat_widgets.TableContainer.__init__(self, columns=2, options=options) |
227 | 229 |
232 self.addWidget(widget) | 234 self.addWidget(widget) |
233 | 235 |
234 | 236 |
235 class PrimitivusTabsContainer(xmlui.TabsContainer, sat_widgets.TabsContainer): | 237 class PrimitivusTabsContainer(xmlui.TabsContainer, sat_widgets.TabsContainer): |
236 | 238 |
237 def __init__(self, parent): | 239 def __init__(self, _xmlui_parent): |
238 sat_widgets.TabsContainer.__init__(self) | 240 sat_widgets.TabsContainer.__init__(self) |
239 | 241 |
240 def _xmluiAppend(self, widget): | 242 def _xmluiAppend(self, widget): |
241 self.body.append(widget) | 243 self.body.append(widget) |
242 | 244 |
247 | 249 |
248 | 250 |
249 class PrimitivusVerticalContainer(xmlui.VerticalContainer, urwid.ListBox): | 251 class PrimitivusVerticalContainer(xmlui.VerticalContainer, urwid.ListBox): |
250 BOX_HEIGHT = 5 | 252 BOX_HEIGHT = 5 |
251 | 253 |
252 def __init__(self, parent): | 254 def __init__(self, _xmlui_parent): |
253 urwid.ListBox.__init__(self, urwid.SimpleListWalker([])) | 255 urwid.ListBox.__init__(self, urwid.SimpleListWalker([])) |
254 self._last_size = None | 256 self._last_size = None |
255 | 257 |
256 def _xmluiAppend(self, widget): | 258 def _xmluiAppend(self, widget): |
257 if 'flow' not in widget.sizing(): | 259 if 'flow' not in widget.sizing(): |
267 widget.height = maxrow | 269 widget.height = maxrow |
268 self._last_size = size | 270 self._last_size = size |
269 return super(PrimitivusVerticalContainer, self).render(size, focus) | 271 return super(PrimitivusVerticalContainer, self).render(size, focus) |
270 | 272 |
271 | 273 |
272 class WidgetFactory(object): | 274 ### Dialogs ### |
275 | |
276 | |
277 class PrimitivusDialog(object): | |
278 | |
279 def __init__(self, _xmlui_parent): | |
280 self.host = _xmlui_parent.host | |
281 | |
282 def _xmluiShow(self): | |
283 self.host.showPopUp(self) | |
284 | |
285 def _xmluiClose(self): | |
286 self.host.removePopUp() | |
287 | |
288 | |
289 class PrimitivusMessageDialog(PrimitivusDialog, xmlui.MessageDialog, sat_widgets.Alert): | |
290 | |
291 def __init__(self, _xmlui_parent, title, message, level): | |
292 PrimitivusDialog.__init__(self, _xmlui_parent) | |
293 xmlui.MessageDialog.__init__(self, _xmlui_parent) | |
294 sat_widgets.Alert.__init__(self, title, message, ok_cb=lambda dummy: self._xmluiValidated()) | |
295 | |
296 | |
297 class PrimitivusNoteDialog(xmlui.NoteDialog, PrimitivusMessageDialog): | |
298 # TODO: separate NoteDialog | |
299 pass | |
300 | |
301 | |
302 class PrimitivusConfirmDialog(PrimitivusDialog, xmlui.ConfirmDialog, sat_widgets.ConfirmDialog): | |
303 | |
304 def __init__(self, _xmlui_parent, title, message, level, buttons_set): | |
305 PrimitivusDialog.__init__(self, _xmlui_parent) | |
306 xmlui.ConfirmDialog.__init__(self, _xmlui_parent) | |
307 sat_widgets.ConfirmDialog.__init__(self, title, message, no_cb=lambda dummy: self._xmluiCancelled(), yes_cb=lambda dummy: self._xmluiValidated()) | |
308 | |
309 | |
310 class PrimitivusFileDialog(PrimitivusDialog, xmlui.FileDialog, files_management.FileDialog): | |
311 | |
312 def __init__(self, _xmlui_parent, title, message, level, filetype): | |
313 # TODO: message is not managed yet | |
314 PrimitivusDialog.__init__(self, _xmlui_parent) | |
315 xmlui.FileDialog.__init__(self, _xmlui_parent) | |
316 style = [] | |
317 if filetype == C.XMLUI_DATA_FILETYPE_DIR: | |
318 style.append('dir') | |
319 files_management.FileDialog.__init__(self, ok_cb=lambda path: self._xmluiValidated({'path': path}), cancel_cb=lambda dummy: self._xmluiCancelled(), title=title) | |
320 | |
321 | |
322 class GenericFactory(object): | |
273 | 323 |
274 def __getattr__(self, attr): | 324 def __getattr__(self, attr): |
275 if attr.startswith("create"): | 325 if attr.startswith("create"): |
276 cls = globals()["Primitivus" + attr[6:]] # XXX: we prefix with "Primitivus" to work around an Urwid bug, WidgetMeta in Urwid don't manage multiple inheritance with same names | 326 cls = globals()["Primitivus" + attr[6:]] # XXX: we prefix with "Primitivus" to work around an Urwid bug, WidgetMeta in Urwid don't manage multiple inheritance with same names |
327 return cls | |
328 | |
329 | |
330 class WidgetFactory(GenericFactory): | |
331 | |
332 def __getattr__(self, attr): | |
333 if attr.startswith("create"): | |
334 cls = GenericFactory.__getattr__(self, attr) | |
277 cls._xmlui_main = self._xmlui_main | 335 cls._xmlui_main = self._xmlui_main |
278 return cls | 336 return cls |
279 | 337 |
280 class XMLUI(xmlui.XMLUI, urwid.WidgetWrap): | 338 |
339 class XMLUIPanel(xmlui.XMLUIPanel, urwid.WidgetWrap): | |
281 widget_factory = WidgetFactory() | 340 widget_factory = WidgetFactory() |
282 | 341 |
283 def __init__(self, host, xml_data, title = None, flags = None): | 342 def __init__(self, host, parsed_xml, title = None, flags = None): |
284 self.widget_factory._xmlui_main = self | 343 self.widget_factory._xmlui_main = self |
285 self._dest = None | 344 self._dest = None |
286 xmlui.XMLUI.__init__(self, host, xml_data, title, flags) | 345 xmlui.XMLUIPanel.__init__(self, host, parsed_xml, title, flags) |
287 urwid.WidgetWrap.__init__(self, self.main_cont) | 346 urwid.WidgetWrap.__init__(self, self.main_cont) |
288 | 347 |
289 def constructUI(self, xml_data): | 348 def constructUI(self, parsed_dom): |
290 def postTreat(): | 349 def postTreat(): |
291 assert self.main_cont.body | 350 assert self.main_cont.body |
292 | 351 |
293 if self.type in ('form', 'popup'): | 352 if self.type in ('form', 'popup'): |
294 buttons = [] | 353 buttons = [] |
309 buttons.append(sat_widgets.CustomButton(_('Cancel'),lambda x:self.host.removeWindow())) | 368 buttons.append(sat_widgets.CustomButton(_('Cancel'),lambda x:self.host.removeWindow())) |
310 max_len = max([button.getSize() for button in buttons]) | 369 max_len = max([button.getSize() for button in buttons]) |
311 grid_wid = urwid.GridFlow(buttons,max_len,1,0,'center') | 370 grid_wid = urwid.GridFlow(buttons,max_len,1,0,'center') |
312 tabs_cont.addFooter(grid_wid) | 371 tabs_cont.addFooter(grid_wid) |
313 | 372 |
314 super(XMLUI, self).constructUI(xml_data, postTreat) | 373 xmlui.XMLUIPanel.constructUI(self, parsed_dom, postTreat) |
315 urwid.WidgetWrap.__init__(self, self.main_cont) | 374 urwid.WidgetWrap.__init__(self, self.main_cont) |
316 | 375 |
317 def show(self, show_type=None, valign='middle'): | 376 def show(self, show_type=None, valign='middle'): |
318 """Show the constructed UI | 377 """Show the constructed UI |
319 @param show_type: how to show the UI: | 378 @param show_type: how to show the UI: |
320 - None (follow XMLUI's recommendation) | 379 - None (follow XMLUI's recommendation) |
321 - 'popup' | 380 - 'popup' |
322 - 'window' | 381 - 'window' |
323 @param valign: vertical alignment when show_type is 'popup'. | 382 @param valign: vertical alignment when show_type is 'popup'. |
324 Ignored when show_type is 'window'. | 383 Ignored when show_type is 'window'. |
325 | 384 |
326 """ | 385 """ |
327 if show_type is None: | 386 if show_type is None: |
328 if self.type in ('window', 'param'): | 387 if self.type in ('window', 'param'): |
329 show_type = 'window' | 388 show_type = 'window' |
341 self.host.addWindow(decorated) | 400 self.host.addWindow(decorated) |
342 else: | 401 else: |
343 assert(False) | 402 assert(False) |
344 self.host.redraw() | 403 self.host.redraw() |
345 | 404 |
346 | |
347 def _xmluiClose(self): | 405 def _xmluiClose(self): |
348 if self._dest == 'window': | 406 if self._dest == 'window': |
349 self.host.removeWindow() | 407 self.host.removeWindow() |
350 else: | 408 else: |
351 self.host.removePopUp() | 409 self.host.removePopUp() |
410 | |
411 | |
412 class XMLUIDialog(xmlui.XMLUIDialog): | |
413 dialog_factory = GenericFactory() | |
414 | |
415 | |
416 xmlui.registerClass(xmlui.CLASS_PANEL, XMLUIPanel) | |
417 xmlui.registerClass(xmlui.CLASS_DIALOG, XMLUIDialog) | |
418 create = xmlui.create |