1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import math
18 import pkg_resources
19 import re
20
21 from trac.core import *
22 from trac.prefs.api import IPreferencePanelProvider
23 from trac.util import as_float, lazy
24 from trac.util.datefmt import all_timezones, get_timezone, localtz
25 from trac.util.html import tag
26 from trac.util.translation import _, Locale, deactivate,\
27 get_available_locales, make_activable
28 from trac.web.api import HTTPNotFound, IRequestHandler, \
29 is_valid_default_handler
30 from trac.web.chrome import Chrome, INavigationContributor, \
31 ITemplateProvider, add_notice, add_stylesheet, \
32 add_warning
36 """Displays the preference panels and dispatch control to the
37 individual panels"""
38
39 implements(INavigationContributor, IRequestHandler, ITemplateProvider)
40
41 panel_providers = ExtensionPoint(IPreferencePanelProvider)
42
43
44
47
49 panels = self._get_panels(req)[0]
50 if panels:
51 yield 'metanav', 'prefs', tag.a(_("Preferences"),
52 href=req.href.prefs())
53
54
55
57 match = re.match('/prefs(?:/([^/]+))?$', req.path_info)
58 if match:
59 req.args['panel_id'] = match.group(1)
60 return True
61
63 if req.is_xhr and req.method == 'POST' and 'save_prefs' in req.args:
64 self._do_save_xhr(req)
65
66 panels, providers = self._get_panels(req)
67 if not panels:
68 raise HTTPNotFound(_("No preference panels available"))
69
70 panels = []
71 child_panels = {}
72 providers = {}
73 for provider in self.panel_providers:
74 for panel in provider.get_preference_panels(req) or []:
75 if len(panel) == 3:
76 name, label, parent = panel
77 child_panels.setdefault(parent, []).append((name, label))
78 else:
79 name = panel[0]
80 panels.append(panel)
81 providers[name] = provider
82 panels = sorted(panels)
83
84 panel_id = req.args.get('panel_id')
85 if panel_id is None:
86 panel_id = panels[1][0] \
87 if len(panels) > 1 and panels[0][0] == 'advanced' \
88 else panels[0][0]
89 chosen_provider = providers.get(panel_id)
90 if not chosen_provider:
91 raise HTTPNotFound(_("Unknown preference panel '%(panel)s'",
92 panel=panel_id))
93
94 session_data = {'session': req.session}
95
96
97 chrome = Chrome(self.env)
98 children = []
99 if child_panels.get(panel_id):
100 for name, label in child_panels[panel_id]:
101 resp = providers[name].render_preference_panel(req, name)
102 ctemplate, cdata = resp[:2]
103 cdata.update(session_data)
104 if len(resp) == 2:
105 rendered = chrome.render_fragment(req, ctemplate, cdata)
106 else:
107
108
109 rendered = chrome.render_template(req, ctemplate, cdata,
110 None, fragment=True)
111 children.append((name, label, rendered))
112
113 resp = chosen_provider.render_preference_panel(req, panel_id)
114 data = resp[1]
115
116 data.update(session_data)
117 data.update({
118 'active_panel': panel_id,
119 'panels': panels,
120 'children': children,
121 })
122
123 add_stylesheet(req, 'common/css/prefs.css')
124 return resp
125
126
127
130
132 return [pkg_resources.resource_filename('trac.prefs', 'templates')]
133
134
135
147
154
182
199
202
203 implements(IPreferencePanelProvider)
204
205 _form_fields = ('tz', 'lc_time', 'dateinfo', 'language')
206
207
208
210 yield 'localization', _("Localization")
211
213 if req.method == 'POST':
214 if Locale and \
215 req.args.get('language') != req.session.get('language'):
216
217
218 del req.locale
219 deactivate()
220 make_activable(lambda: req.locale, self.env.path)
221 _do_save(req, panel, self._form_fields)
222
223 data = {
224 'timezones': all_timezones,
225 'timezone': get_timezone,
226 'localtz': localtz,
227 'has_babel': False,
228 }
229 if Locale:
230 locale_ids = get_available_locales()
231 locales = [Locale.parse(locale) for locale in locale_ids]
232
233
234
235
236 languages = sorted((id_, locale.display_name)
237 for id_, locale in zip(locale_ids, locales))
238 data['locales'] = locales
239 data['languages'] = languages
240 data['has_babel'] = True
241 return 'prefs_localization.html', data
242
281
282
283 -def _do_save(req, panel, form_fields):
284 for field in form_fields:
285 val = req.args.get(field, '').strip()
286 if val:
287 if field == 'ui.auto_preview_timeout':
288 fval = as_float(val, default=None)
289 if fval is None or math.isinf(fval) or math.isnan(fval) \
290 or fval < 0:
291 add_warning(req, _("Discarded invalid value \"%(val)s\" "
292 "for auto preview timeout.", val=val))
293 continue
294 if field == 'tz' and 'tz' in req.session and \
295 val not in all_timezones:
296 del req.session[field]
297 elif field == 'newsid':
298 req.session.change_sid(val)
299 else:
300 req.session[field] = val
301 elif (field in req.args or field + '_cb' in req.args) and \
302 field in req.session:
303 del req.session[field]
304 add_notice(req, _("Your preferences have been saved."))
305 req.redirect(req.href.prefs(panel))
306