Mercurial > libervia-backend
comparison libervia/backend/tools/common/template_xmlui.py @ 4071:4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 02 Jun 2023 11:49:51 +0200 |
parents | sat/tools/common/template_xmlui.py@524856bd7b19 |
children | 26b7ed2817da |
comparison
equal
deleted
inserted
replaced
4070:d10748475025 | 4071:4b842c1fb686 |
---|---|
1 #!/usr/bin/env python3 | |
2 | |
3 | |
4 # SAT: a jabber client | |
5 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) | |
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 """ template XMLUI parsing | |
21 | |
22 XMLUI classes from this modules can then be iterated to create the template | |
23 """ | |
24 | |
25 from functools import partial | |
26 from libervia.backend.core.log import getLogger | |
27 from sat_frontends.tools import xmlui | |
28 from sat_frontends.tools import jid | |
29 try: | |
30 from jinja2 import Markup as safe | |
31 except ImportError: | |
32 # Safe marks XHTML values as usable as it. | |
33 # If jinja2 is not there, we can use a simple lamba | |
34 safe = lambda x: x | |
35 | |
36 | |
37 log = getLogger(__name__) | |
38 | |
39 | |
40 ## Widgets ## | |
41 | |
42 | |
43 class Widget(object): | |
44 category = "widget" | |
45 type = None | |
46 enabled = True | |
47 read_only = True | |
48 | |
49 def __init__(self, xmlui_parent): | |
50 self.xmlui_parent = xmlui_parent | |
51 | |
52 @property | |
53 def name(self): | |
54 return self._xmlui_name | |
55 | |
56 | |
57 class ValueWidget(Widget): | |
58 def __init__(self, xmlui_parent, value): | |
59 super(ValueWidget, self).__init__(xmlui_parent) | |
60 self.value = value | |
61 | |
62 @property | |
63 def values(self): | |
64 return [self.value] | |
65 | |
66 @property | |
67 def labels(self): | |
68 # helper property, there is not label for ValueWidget | |
69 # but using labels make rendering more easy (one single method to call) | |
70 # values are actually returned | |
71 return [self.value] | |
72 | |
73 | |
74 class InputWidget(ValueWidget): | |
75 def __init__(self, xmlui_parent, value, read_only=False): | |
76 super(InputWidget, self).__init__(xmlui_parent, value) | |
77 self.read_only = read_only | |
78 | |
79 | |
80 class OptionsWidget(Widget): | |
81 def __init__(self, xmlui_parent, options, selected, style): | |
82 super(OptionsWidget, self).__init__(xmlui_parent) | |
83 self.options = options | |
84 self.selected = selected | |
85 self.style = style | |
86 | |
87 @property | |
88 def values(self): | |
89 for value, label in self.items: | |
90 yield value | |
91 | |
92 @property | |
93 def value(self): | |
94 if self.multi or self.no_select or len(self.selected) != 1: | |
95 raise ValueError( | |
96 "Can't get value for list with multiple selections or nothing selected" | |
97 ) | |
98 return self.selected[0] | |
99 | |
100 @property | |
101 def labels(self): | |
102 """return only labels from self.items""" | |
103 for value, label in self.items: | |
104 yield label | |
105 | |
106 @property | |
107 def items(self): | |
108 """return suitable items, according to style""" | |
109 no_select = self.no_select | |
110 for value, label in self.options: | |
111 if no_select or value in self.selected: | |
112 yield value, label | |
113 | |
114 @property | |
115 def inline(self): | |
116 return "inline" in self.style | |
117 | |
118 @property | |
119 def no_select(self): | |
120 return "noselect" in self.style | |
121 | |
122 @property | |
123 def multi(self): | |
124 return "multi" in self.style | |
125 | |
126 | |
127 class EmptyWidget(xmlui.EmptyWidget, Widget): | |
128 def __init__(self, _xmlui_parent): | |
129 Widget.__init__(self) | |
130 | |
131 | |
132 class TextWidget(xmlui.TextWidget, ValueWidget): | |
133 type = "text" | |
134 | |
135 | |
136 class JidWidget(xmlui.JidWidget, ValueWidget): | |
137 type = "jid" | |
138 | |
139 def __init__(self, xmlui_parent, value): | |
140 self.value = jid.JID(value) | |
141 | |
142 | |
143 class LabelWidget(xmlui.LabelWidget, ValueWidget): | |
144 type = "label" | |
145 | |
146 @property | |
147 def for_name(self): | |
148 try: | |
149 return self._xmlui_for_name | |
150 except AttributeError: | |
151 return None | |
152 | |
153 | |
154 class StringWidget(xmlui.StringWidget, InputWidget): | |
155 type = "string" | |
156 | |
157 | |
158 class JidInputWidget(xmlui.JidInputWidget, StringWidget): | |
159 type = "jid" | |
160 | |
161 class TextBoxWidget(xmlui.TextWidget, InputWidget): | |
162 type = "textbox" | |
163 | |
164 | |
165 class XHTMLBoxWidget(xmlui.XHTMLBoxWidget, InputWidget): | |
166 type = "xhtmlbox" | |
167 | |
168 def __init__(self, xmlui_parent, value, read_only=False): | |
169 # XXX: XHTMLBoxWidget value must be cleaned (harmful XHTML must be removed) | |
170 # This is normally done in the backend, the frontends should not need to | |
171 # worry about it. | |
172 super(XHTMLBoxWidget, self).__init__( | |
173 xmlui_parent=xmlui_parent, value=safe(value), read_only=read_only) | |
174 | |
175 | |
176 class ListWidget(xmlui.ListWidget, OptionsWidget): | |
177 type = "list" | |
178 | |
179 | |
180 ## Containers ## | |
181 | |
182 | |
183 class Container(object): | |
184 category = "container" | |
185 type = None | |
186 | |
187 def __init__(self, xmlui_parent): | |
188 self.xmlui_parent = xmlui_parent | |
189 self.children = [] | |
190 | |
191 def __iter__(self): | |
192 return iter(self.children) | |
193 | |
194 def _xmlui_append(self, widget): | |
195 self.children.append(widget) | |
196 | |
197 def _xmlui_remove(self, widget): | |
198 self.children.remove(widget) | |
199 | |
200 | |
201 class VerticalContainer(xmlui.VerticalContainer, Container): | |
202 type = "vertical" | |
203 | |
204 | |
205 class PairsContainer(xmlui.PairsContainer, Container): | |
206 type = "pairs" | |
207 | |
208 | |
209 class LabelContainer(xmlui.PairsContainer, Container): | |
210 type = "label" | |
211 | |
212 | |
213 ## Factory ## | |
214 | |
215 | |
216 class WidgetFactory(object): | |
217 | |
218 def __getattr__(self, attr): | |
219 if attr.startswith("create"): | |
220 cls = globals()[attr[6:]] | |
221 return cls | |
222 | |
223 | |
224 ## Core ## | |
225 | |
226 | |
227 class XMLUIPanel(xmlui.XMLUIPanel): | |
228 widget_factory = WidgetFactory() | |
229 | |
230 def show(self, *args, **kwargs): | |
231 raise NotImplementedError | |
232 | |
233 | |
234 class XMLUIDialog(xmlui.XMLUIDialog): | |
235 dialog_factory = WidgetFactory() | |
236 | |
237 def __init__(*args, **kwargs): | |
238 raise NotImplementedError | |
239 | |
240 | |
241 create = partial(xmlui.create, class_map={ | |
242 xmlui.CLASS_PANEL: XMLUIPanel, | |
243 xmlui.CLASS_DIALOG: XMLUIDialog}) |