1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import os
18 import re
19
20 import libxyz.parser as parser
21
22 from libxyz.exceptions import ParseError
23 from libxyz.exceptions import SkinError
24 from libxyz.exceptions import XYZValueError
25 from libxyz.exceptions import FSRuleError
26 from libxyz.core import FSRule
27
28 import libxyz.ui as uilib
29
31 """
32 Skin object. Provides simple interface to defined skin rulesets.
33 """
34
36 """
37 @param path: Path to skin file
38 """
39
40 if not os.access(path, os.R_OK):
41 raise SkinError(_(u"Unable to open skin file for reading"))
42 else:
43 self.path = path
44
45 self._data = {}
46
47 self.screen = None
48
49
50 self._default = uilib.colors.Palette(u"default",
51 uilib.colors.Foreground(u"DEFAULT"),
52 uilib.colors.Background(u"DEFAULT"),
53 uilib.colors.Monochrome(u"DEFAULT"))
54
55
56 self._data = self._parse()
57
58
59 self._check()
60
61
62
64 return u"<Skin object: %s>" % str(self.path)
65
66
67
70
71
72
74 return self._data[key]
75
76
77
80
81
82
84 def palette_validator(block, var, val):
85 """
86 Make L{libxyz.ui.colors.Palette} object of palette definition
87 """
88
89 _p = self._default.copy()
90
91 if isinstance(val, basestring):
92 _val = (val,)
93 else:
94 _val = [x.strip() for x in val]
95
96 _p.fg = uilib.colors.Foreground(_val[0])
97
98 if len(_val) > 1:
99 _p.bg = uilib.colors.Background(_val[1])
100 if len(_val) > 2:
101 _p.ma = tuple([uilib.colors.Monochrome(x) for x in _val[2:]])
102
103 _p.name = self._make_name(block, var)
104
105 return _p
106
107
108
109 def trans_cr(rule):
110 """
111 Transform string rules to FSRule objects
112 """
113
114 try:
115 return FSRule(rule)
116 except (ParseError, FSRuleError), e:
117 raise XYZValueError(e)
118
119
120
121
122
123 _fs_rules_opt = {u"count": 1,
124 u"value_validator": palette_validator,
125 u"varre": re.compile(r".+"),
126 u"var_transform": trans_cr,
127 }
128
129 _fs_rules_p = parser.BlockParser(_fs_rules_opt)
130
131 _ui_opt = {u"count": 1,
132 u"value_validator": palette_validator,
133 }
134 _ui_p = parser.BlockParser(_ui_opt)
135
136 _plugin_opt = {u"count": 1,
137 u"value_validator": palette_validator,
138 }
139 _plugin_p = parser.BlockParser(_plugin_opt)
140
141 _flat_opt = {u"count": 1}
142 _flat_p = parser.FlatParser(_flat_opt)
143
144 _parsers = {
145 u"fs.rules": _fs_rules_p,
146 re.compile(r"ui\.(\w)+"): _ui_p,
147 re.compile(r"plugin\.([\w_-])+"): _plugin_p,
148 (u"AUTHOR", u"VERSION", u"DESCRIPTION"): _flat_p,
149 }
150
151 _multi_opt = {u"tokens": (":",)}
152 _multi_p = parser.MultiParser(_parsers, _multi_opt)
153
154 _skinfile = open(self.path, "r")
155
156 try:
157 _data = _multi_p.parse(_skinfile)
158 except ParseError, e:
159 raise SkinError(_(u"Error parsing skin file: %s" % str(e)))
160 finally:
161 _skinfile.close()
162
163 return _data
164
165
166
168 return "%(resource)s@%(block)s" % locals()
169
170
171
173 """
174 Check and variables
175 """
176
177 for _required in (u"AUTHOR", u"DESCRIPTION", u"VERSION"):
178 if _required not in self._data:
179 raise SkinError(_(u"Missing required variable: %s"%_required))
180
181
182
184 """
185 Return list of defined palettes.
186 It is usually passed to register_palette() function
187 """
188
189 _list = [self._default.get_palette()]
190
191 for _name, _pdata in self._data.iteritems():
192 if not isinstance(_pdata, parser.ParsedData):
193 continue
194
195 for _var, _val in _pdata.iteritems():
196 if isinstance(_val, uilib.colors.Palette):
197 _list.append(_val.get_palette())
198
199 return _list
200
201
202
203 - def attr(self, resolution, name, default=True):
204 """
205 Search for first matching attribute <name> according to resolution
206 @param resolution: Sequence of ruleset names
207 @param name: Attribute name
208 @param default: If True, return default palette in case attr
209 is not found, otherwise return None
210 @return: Registered palette name
211 """
212
213 return self.palette(resolution, name, default).name
214
215
216
217 - def palette(self, resolution, name, default=True):
218 """
219 Search for first matching palette <name> according to resolution
220 """
221
222 for _w in resolution:
223
224 if not _w.startswith(u"ui."):
225 _w = u"ui.%s" % _w
226
227 try:
228 return self._data[_w][name]
229 except KeyError:
230 pass
231
232 if default:
233 return self._default
234 else:
235 return None
236
237
238
240 try:
241 return self._data[block][name].name
242 except KeyError:
243 return None
244