Mercurial > libervia-backend
annotate sat_frontends/jp/xmlui_manager.py @ 2787:298408833ec2
memory (sqlite): optimizations
indexes were missing on foreign keys for "message", "subject" and "thread" tables, seriously impacting performances.
In addition to those indexes, two indexes have been added to speed ordering by timestamp on "history", and one on "files" table.
history.rowid is not used anymore as there is an index on (profile_id, received_timestamp) which will speed up the query.
Primary keys order has been changed to use automatic index in most common cases (filtering by profile_id then namespace).
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 19 Jan 2019 22:49:32 +0100 |
parents | 442ab697f831 |
children | 18a98a541f7a |
rev | line source |
---|---|
2408 | 1 #!/usr/bin/env python2 |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # JP: a SàT frontend | |
2771 | 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) |
2408 | 6 |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
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/>. | |
19 | |
20 from sat.core.log import getLogger | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
21 |
2408 | 22 log = getLogger(__name__) |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
23 from sat_frontends.tools import xmlui as xmlui_base |
2408 | 24 from sat_frontends.jp.constants import Const as C |
25 from sat.tools.common.ansi import ANSI as A | |
26 from sat.core.i18n import _ | |
27 from functools import partial | |
28 | |
29 # workflow constants | |
30 | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
31 SUBMIT = "SUBMIT" # submit form |
2408 | 32 |
33 | |
34 ## Widgets ## | |
35 | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
36 |
2408 | 37 class Base(object): |
38 """Base for Widget and Container""" | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
39 |
2408 | 40 type = None |
41 _root = None | |
42 | |
43 def __init__(self, xmlui_parent): | |
44 self.xmlui_parent = xmlui_parent | |
45 self.host = self.xmlui_parent.host | |
46 | |
47 @property | |
48 def root(self): | |
49 """retrieve main XMLUI parent class""" | |
50 if self._root is not None: | |
51 return self._root | |
52 root = self | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
53 while not isinstance(root, xmlui_base.XMLUIBase): |
2408 | 54 root = root.xmlui_parent |
55 self._root = root | |
56 return root | |
57 | |
58 def disp(self, *args, **kwargs): | |
59 self.host.disp(*args, **kwargs) | |
60 | |
61 | |
62 class Widget(Base): | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
63 category = u"widget" |
2408 | 64 enabled = True |
65 | |
66 @property | |
67 def name(self): | |
68 return self._xmlui_name | |
69 | |
70 def show(self): | |
71 """display current widget | |
72 | |
73 must be overriden by subclasses | |
74 """ | |
75 raise NotImplementedError(self.__class__) | |
76 | |
77 def verboseName(self, elems=None, value=None): | |
78 """add name in color to the elements | |
79 | |
80 helper method to display name which can then be used to automate commands | |
81 elems is only modified if verbosity is > 0 | |
82 @param elems(list[unicode], None): elements to display | |
83 None to display name directly | |
84 @param value(unicode, None): value to show | |
85 use self.name if None | |
86 """ | |
87 if value is None: | |
88 value = self.name | |
89 if self.host.verbosity: | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
90 to_disp = [ |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
91 A.FG_MAGENTA, |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
92 u" " if elems else u"", |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
93 u"({})".format(value), |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
94 A.RESET, |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
95 ] |
2408 | 96 if elems is None: |
97 self.host.disp(A.color(*to_disp)) | |
98 else: | |
99 elems.extend(to_disp) | |
100 | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
101 |
2408 | 102 class ValueWidget(Widget): |
103 def __init__(self, xmlui_parent, value): | |
104 super(ValueWidget, self).__init__(xmlui_parent) | |
105 self.value = value | |
106 | |
107 @property | |
108 def values(self): | |
109 return [self.value] | |
110 | |
111 | |
112 class InputWidget(ValueWidget): | |
113 def __init__(self, xmlui_parent, value, read_only=False): | |
114 super(InputWidget, self).__init__(xmlui_parent, value) | |
115 self.read_only = read_only | |
116 | |
117 def _xmluiGetValue(self): | |
118 return self.value | |
119 | |
120 | |
121 class OptionsWidget(Widget): | |
122 def __init__(self, xmlui_parent, options, selected, style): | |
123 super(OptionsWidget, self).__init__(xmlui_parent) | |
124 self.options = options | |
125 self.selected = selected | |
126 self.style = style | |
127 | |
128 @property | |
129 def values(self): | |
130 return self.selected | |
131 | |
132 @values.setter | |
133 def values(self, values): | |
134 self.selected = values | |
135 | |
136 @property | |
137 def value(self): | |
138 return self.selected[0] | |
139 | |
140 @value.setter | |
141 def value(self, value): | |
142 self.selected = [value] | |
143 | |
144 def _xmluiSelectValue(self, value): | |
145 self.value = value | |
146 | |
147 def _xmluiSelectValues(self, values): | |
148 self.values = values | |
149 | |
150 def _xmluiGetSelectedValues(self): | |
151 return self.values | |
152 | |
153 @property | |
154 def labels(self): | |
155 """return only labels from self.items""" | |
156 for value, label in self.items: | |
157 yield label | |
158 | |
159 @property | |
160 def items(self): | |
161 """return suitable items, according to style""" | |
162 no_select = self.no_select | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
163 for value, label in self.options: |
2408 | 164 if no_select or value in self.selected: |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
165 yield value, label |
2408 | 166 |
167 @property | |
168 def inline(self): | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
169 return u"inline" in self.style |
2408 | 170 |
171 @property | |
172 def no_select(self): | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
173 return u"noselect" in self.style |
2408 | 174 |
175 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
176 class EmptyWidget(xmlui_base.EmptyWidget, Widget): |
2739
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
177 |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
178 def __init__(self, xmlui_parent): |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
179 Widget.__init__(self, xmlui_parent) |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
180 |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
181 def show(self): |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
182 self.host.disp(u'') |
2408 | 183 |
184 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
185 class TextWidget(xmlui_base.TextWidget, ValueWidget): |
2408 | 186 type = u"text" |
187 | |
188 def show(self): | |
189 self.host.disp(self.value) | |
190 | |
191 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
192 class LabelWidget(xmlui_base.LabelWidget, ValueWidget): |
2408 | 193 type = u"label" |
194 | |
195 @property | |
196 def for_name(self): | |
197 try: | |
198 return self._xmlui_for_name | |
199 except AttributeError: | |
200 return None | |
201 | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
202 def show(self, no_lf=False, ansi=u""): |
2408 | 203 """show label |
204 | |
205 @param no_lf(bool): same as for [JP.disp] | |
206 @param ansi(unicode): ansi escape code to print before label | |
207 """ | |
208 self.disp(A.color(ansi, self.value), no_lf=no_lf) | |
209 | |
210 | |
2739
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
211 class JidWidget(xmlui_base.JidWidget, TextWidget): |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
212 type = u"jid" |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
213 |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
214 class StringWidget(xmlui_base.StringWidget, InputWidget): |
2408 | 215 type = u"string" |
216 | |
217 def show(self): | |
218 if self.read_only: | |
219 self.disp(self.value) | |
220 else: | |
221 elems = [] | |
222 self.verboseName(elems) | |
223 if self.value: | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
224 elems.append(_(u"(enter: {default})").format(default=self.value)) |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
225 elems.extend([C.A_HEADER, u"> "]) |
2408 | 226 value = raw_input(A.color(*elems)) |
227 if value: | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
228 # TODO: empty value should be possible |
2408 | 229 # an escape key should be used for default instead of enter with empty value |
230 self.value = value | |
231 | |
232 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
233 class JidInputWidget(xmlui_base.JidInputWidget, StringWidget): |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
234 type = u"jid_input" |
2408 | 235 |
236 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
237 class TextBoxWidget(xmlui_base.TextWidget, StringWidget): |
2408 | 238 type = u"textbox" |
239 | |
240 | |
2783
442ab697f831
frontends, jp, templates: added XHTMLBox widget:
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
241 class XHTMLBoxWidget(xmlui_base.XHTMLBoxWidget, StringWidget): |
442ab697f831
frontends, jp, templates: added XHTMLBox widget:
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
242 type = u"xhtmlbox" |
442ab697f831
frontends, jp, templates: added XHTMLBox widget:
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
243 |
442ab697f831
frontends, jp, templates: added XHTMLBox widget:
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
244 def show(self): |
442ab697f831
frontends, jp, templates: added XHTMLBox widget:
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
245 # FIXME: we use bridge in a blocking way as permitted by python-dbus |
442ab697f831
frontends, jp, templates: added XHTMLBox widget:
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
246 # this only for now to make it simpler, it must be refactored |
442ab697f831
frontends, jp, templates: added XHTMLBox widget:
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
247 # to use async when jp will be fully async (expected for 0.8) |
442ab697f831
frontends, jp, templates: added XHTMLBox widget:
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
248 self.value = self.host.bridge.syntaxConvert( |
442ab697f831
frontends, jp, templates: added XHTMLBox widget:
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
249 self.value, C.SYNTAX_XHTML, "markdown", False, self.host.profile) |
442ab697f831
frontends, jp, templates: added XHTMLBox widget:
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
250 super(XHTMLBoxWidget, self).show() |
442ab697f831
frontends, jp, templates: added XHTMLBox widget:
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
251 |
442ab697f831
frontends, jp, templates: added XHTMLBox widget:
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
252 |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
253 class ListWidget(xmlui_base.ListWidget, OptionsWidget): |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
254 type = u"list" |
2408 | 255 # TODO: handle flags, notably multi |
256 | |
257 def show(self): | |
2541
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
258 if self.root.values_only: |
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
259 for value in self.values: |
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
260 self.disp(self.value) |
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
261 return |
2408 | 262 if not self.options: |
263 return | |
264 | |
265 # list display | |
266 self.verboseName() | |
267 | |
268 for idx, (value, label) in enumerate(self.options): | |
269 elems = [] | |
2541
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
270 if not self.root.read_only: |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
271 elems.extend([C.A_SUBHEADER, unicode(idx), A.RESET, u": "]) |
2408 | 272 elems.append(label) |
273 self.verboseName(elems, value) | |
274 self.disp(A.color(*elems)) | |
275 | |
2541
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
276 if self.root.read_only: |
2408 | 277 return |
278 | |
279 if len(self.options) == 1: | |
280 # we have only one option, no need to ask | |
281 self.value = self.options[0][0] | |
282 return | |
283 | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
284 # we ask use to choose an option |
2408 | 285 choice = None |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
286 limit_max = len(self.options) - 1 |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
287 while choice is None or choice < 0 or choice > limit_max: |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
288 choice = raw_input( |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
289 A.color(C.A_HEADER, _(u"your choice (0-{max}): ").format(max=limit_max)) |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
290 ) |
2408 | 291 try: |
292 choice = int(choice) | |
293 except ValueError: | |
294 choice = None | |
295 self.value = self.options[choice][0] | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
296 self.disp("") |
2408 | 297 |
298 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
299 class BoolWidget(xmlui_base.BoolWidget, InputWidget): |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
300 type = u"bool" |
2408 | 301 |
302 def show(self): | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
303 disp_true = A.color(A.FG_GREEN, u"TRUE") |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
304 disp_false = A.color(A.FG_RED, u"FALSE") |
2408 | 305 if self.read_only: |
306 self.disp(disp_true if self.value else disp_false) | |
307 else: | |
2739
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
308 self.disp(A.color(C.A_HEADER, u"0: ", |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
309 disp_false, A.RESET, |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
310 u" *" if not self.value else u"")) |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
311 self.disp(A.color(C.A_HEADER, u"1: ", |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
312 disp_true, A.RESET, |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
313 u" *" if self.value else u"")) |
2408 | 314 choice = None |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
315 while choice not in ("0", "1"): |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
316 elems = [C.A_HEADER, _(u"your choice (0,1): ")] |
2408 | 317 self.verboseName(elems) |
318 choice = raw_input(A.color(*elems)) | |
319 self.value = bool(int(choice)) | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
320 self.disp("") |
2408 | 321 |
322 def _xmluiGetValue(self): | |
323 return C.boolConst(self.value) | |
324 | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
325 |
2408 | 326 ## Containers ## |
327 | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
328 |
2408 | 329 class Container(Base): |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
330 category = u"container" |
2408 | 331 |
332 def __init__(self, xmlui_parent): | |
333 super(Container, self).__init__(xmlui_parent) | |
334 self.children = [] | |
335 | |
336 def __iter__(self): | |
337 return iter(self.children) | |
338 | |
339 def _xmluiAppend(self, widget): | |
340 self.children.append(widget) | |
341 | |
2541
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
342 def _xmluiRemove(self, widget): |
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
343 self.children.remove(widget) |
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
344 |
2408 | 345 def show(self): |
346 for child in self.children: | |
347 child.show() | |
348 | |
349 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
350 class VerticalContainer(xmlui_base.VerticalContainer, Container): |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
351 type = u"vertical" |
2408 | 352 |
353 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
354 class PairsContainer(xmlui_base.PairsContainer, Container): |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
355 type = u"pairs" |
2408 | 356 |
357 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
358 class LabelContainer(xmlui_base.PairsContainer, Container): |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
359 type = u"label" |
2408 | 360 |
361 def show(self): | |
362 for child in self.children: | |
363 no_lf = False | |
364 # we check linked widget type | |
365 # to see if we want the label on the same line or not | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
366 if child.type == u"label": |
2408 | 367 for_name = child.for_name |
2739
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
368 if for_name: |
2408 | 369 for_widget = self.root.widgets[for_name] |
370 wid_type = for_widget.type | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
371 if self.root.values_only or wid_type in ( |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
372 "text", |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
373 "string", |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
374 "jid_input", |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
375 ): |
2408 | 376 no_lf = True |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
377 elif wid_type == "bool" and for_widget.read_only: |
2408 | 378 no_lf = True |
379 child.show(no_lf=no_lf, ansi=A.FG_CYAN) | |
380 else: | |
381 child.show() | |
382 | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
383 |
2408 | 384 ## Dialogs ## |
385 | |
386 | |
387 class Dialog(object): | |
388 def __init__(self, xmlui_parent): | |
389 self.xmlui_parent = xmlui_parent | |
390 self.host = self.xmlui_parent.host | |
391 | |
392 def disp(self, *args, **kwargs): | |
393 self.host.disp(*args, **kwargs) | |
394 | |
395 def show(self): | |
396 """display current dialog | |
397 | |
398 must be overriden by subclasses | |
399 """ | |
400 raise NotImplementedError(self.__class__) | |
401 | |
402 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
403 class NoteDialog(xmlui_base.NoteDialog, Dialog): |
2408 | 404 def show(self): |
405 # TODO: handle title and level | |
406 self.disp(self.message) | |
407 | |
2739
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
408 def __init__(self, xmlui_parent, title, message, level): |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
409 Dialog.__init__(self, xmlui_parent) |
e8dc00f612fb
jp (xmlui): JidWidget + small improvments:
Goffi <goffi@goffi.org>
parents:
2669
diff
changeset
|
410 xmlui_base.NoteDialog.__init__(self, xmlui_parent) |
2408 | 411 self.title, self.message, self.level = title, message, level |
412 | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
413 |
2408 | 414 ## Factory ## |
415 | |
416 | |
417 class WidgetFactory(object): | |
418 def __getattr__(self, attr): | |
419 if attr.startswith("create"): | |
420 cls = globals()[attr[6:]] | |
421 return cls | |
422 | |
423 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
424 class XMLUIPanel(xmlui_base.XMLUIPanel): |
2408 | 425 widget_factory = WidgetFactory() |
426 _actions = 0 # use to keep track of bridge's launchAction calls | |
2541
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
427 read_only = False |
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
428 values_only = False |
2408 | 429 workflow = None |
430 _submit_cb = None | |
431 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
432 def __init__(self, host, parsed_dom, title=None, flags=None, callback=None, |
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
433 ignore=None, whitelist=None, profile=None): |
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
434 xmlui_base.XMLUIPanel.__init__( |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
435 self, |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
436 host, |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
437 parsed_dom, |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
438 title=title, |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
439 flags=flags, |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
440 ignore=ignore, |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
441 whitelist=whitelist, |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
442 profile=host.profile, |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
443 ) |
2408 | 444 self.submitted = False |
445 | |
446 @property | |
447 def command(self): | |
448 return self.host.command | |
449 | |
2541
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
450 def show(self, workflow=None, read_only=False, values_only=False): |
2408 | 451 """display the panel |
452 | |
453 @param workflow(list, None): command to execute if not None | |
454 put here for convenience, the main workflow is the class attribute | |
455 (because workflow can continue in subclasses) | |
456 command are a list of consts or lists: | |
457 - SUBMIT is the only constant so far, it submits the XMLUI | |
458 - list must contain widget name/widget value to fill | |
2541
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
459 @param read_only(bool): if True, don't request values |
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
460 @param values_only(bool): if True, only show select values (imply read_only) |
2408 | 461 """ |
2541
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
462 self.read_only = read_only |
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
463 self.values_only = values_only |
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
464 if self.values_only: |
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
465 self.read_only = True |
2408 | 466 if workflow: |
467 XMLUIPanel.workflow = workflow | |
468 if XMLUIPanel.workflow: | |
469 self.runWorkflow() | |
470 else: | |
471 self.main_cont.show() | |
472 | |
473 def runWorkflow(self): | |
474 """loop into workflow commands and execute commands | |
475 | |
476 SUBMIT will interrupt workflow (which will be continue on callback) | |
477 @param workflow(list): same as [show] | |
478 """ | |
479 workflow = XMLUIPanel.workflow | |
480 while True: | |
481 try: | |
482 cmd = workflow.pop(0) | |
483 except IndexError: | |
484 break | |
485 if cmd == SUBMIT: | |
486 self.onFormSubmitted() | |
487 self.submit_id = None # avoid double submit | |
488 return | |
489 elif isinstance(cmd, list): | |
490 name, value = cmd | |
2412
7641bef56dcd
jp (xmlui): fixed workflow when value is for a BoolWidget
Goffi <goffi@goffi.org>
parents:
2410
diff
changeset
|
491 widget = self.widgets[name] |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
492 if widget.type == "bool": |
2412
7641bef56dcd
jp (xmlui): fixed workflow when value is for a BoolWidget
Goffi <goffi@goffi.org>
parents:
2410
diff
changeset
|
493 value = C.bool(value) |
7641bef56dcd
jp (xmlui): fixed workflow when value is for a BoolWidget
Goffi <goffi@goffi.org>
parents:
2410
diff
changeset
|
494 widget.value = value |
2408 | 495 self.show() |
496 | |
497 def submitForm(self, callback=None): | |
498 XMLUIPanel._submit_cb = callback | |
499 self.onFormSubmitted() | |
500 | |
501 def onFormSubmitted(self, ignore=None): | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
502 # self.submitted is a Q&D workaround to avoid |
2408 | 503 # double submit when a workflow is set |
504 if self.submitted: | |
505 return | |
506 self.submitted = True | |
507 super(XMLUIPanel, self).onFormSubmitted(ignore) | |
508 | |
509 def _xmluiClose(self): | |
510 pass | |
511 | |
512 def _launchActionCb(self, data): | |
513 XMLUIPanel._actions -= 1 | |
514 assert XMLUIPanel._actions >= 0 | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
515 if u"xmlui" in data: |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
516 xmlui_raw = data["xmlui"] |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
517 xmlui = create(self.host, xmlui_raw) |
2408 | 518 xmlui.show() |
519 if xmlui.submit_id: | |
520 xmlui.onFormSubmitted() | |
521 # TODO: handle data other than XMLUI | |
522 if not XMLUIPanel._actions: | |
523 if self._submit_cb is None: | |
524 self.host.quit() | |
525 else: | |
526 self._submit_cb() | |
527 | |
528 def _xmluiLaunchAction(self, action_id, data): | |
529 XMLUIPanel._actions += 1 | |
530 self.host.bridge.launchAction( | |
531 action_id, | |
532 data, | |
533 self.profile, | |
534 callback=self._launchActionCb, | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
535 errback=partial( |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
536 self.command.errback, |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
537 msg=_(u"can't launch XMLUI action: {}"), |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
538 exit_code=C.EXIT_BRIDGE_ERRBACK, |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
539 ), |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
540 ) |
2408 | 541 |
542 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
543 class XMLUIDialog(xmlui_base.XMLUIDialog): |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
544 type = "dialog" |
2408 | 545 dialog_factory = WidgetFactory() |
2541
65695b9343d3
jp (xmlui): added whitelist, read_only and values_only options:
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
546 read_only = False |
2408 | 547 |
2765
378188abe941
misc: replaced all "dummy" by the more conventional and readable "__" ("_" being used for gettext)
Goffi <goffi@goffi.org>
parents:
2739
diff
changeset
|
548 def show(self, __=None): |
2408 | 549 self.dlg.show() |
550 | |
551 def _xmluiClose(self): | |
552 pass | |
553 | |
554 | |
2669
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
555 create = partial(xmlui_base.create, class_map={ |
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
556 xmlui_base.CLASS_PANEL: XMLUIPanel, |
bdb8276fd2da
frontends (xmlui): class_map is now an arg of create function:
Goffi <goffi@goffi.org>
parents:
2624
diff
changeset
|
557 xmlui_base.CLASS_DIALOG: XMLUIDialog}) |