~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/webapp/base/xhtml.py

ivle.webapp.base.rest#RESTView: Remove broken old render() - it should be
                                implemented by subclasses.
                     #JSONRESTView: Remove an impossible assertion, and fix
                                    some exception message spacing.
ivle.webapp.base.test.test_rest: Add a named operation with both default and
                                 non-default arguments, and check that we die
                                 properly when the non-default is unspecified.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
import inspect
21
21
import os.path
22
 
import urllib
23
22
 
24
23
import genshi.template
25
24
 
26
 
from ivle.webapp.media import media_url
27
 
from ivle.webapp.core import Plugin as CorePlugin
28
25
from ivle.webapp.base.views import BaseView
29
 
from ivle.webapp.base.plugins import ViewPlugin, OverlayPlugin
30
 
from ivle.webapp.errors import HTTPError, Unauthorized
 
26
import ivle.conf
 
27
import ivle.util
31
28
 
32
29
class XHTMLView(BaseView):
33
30
    """
35
32
    It is expected that apps which use this view will be written using Genshi
36
33
    templates.
37
34
    """
38
 
 
39
 
    template = 'template.html'
40
 
 
41
 
    plugin_scripts = {}
42
 
    plugin_styles = {}
43
 
    scripts_init = []
44
 
 
45
 
    allow_overlays = True
46
 
    overlay_blacklist = []
47
 
 
48
35
    def __init__(self, req, **kwargs):
49
36
        for key in kwargs:
50
37
            setattr(self, key, kwargs[key])
51
38
 
52
 
    def filter(self, stream, ctx):
53
 
        return stream
54
 
 
55
39
    def render(self, req):
56
40
        req.content_type = 'text/html' # TODO: Detect application/xhtml+xml
57
41
 
63
47
        # view.
64
48
        app_template = os.path.join(os.path.dirname(
65
49
                        inspect.getmodule(self).__file__), self.template) 
 
50
        req.write_html_head_foot = False
66
51
        loader = genshi.template.TemplateLoader(".", auto_reload=True)
67
52
        tmpl = loader.load(app_template)
68
 
        app = self.filter(tmpl.generate(viewctx), viewctx)
69
 
 
70
 
        view_scripts = []
71
 
        for plugin in self.plugin_scripts:
72
 
            for path in self.plugin_scripts[plugin]:
73
 
                view_scripts.append(media_url(req, plugin, path))
74
 
 
75
 
        view_styles = []
76
 
        for plugin in self.plugin_styles:
77
 
            for path in self.plugin_styles[plugin]:
78
 
                view_styles.append(media_url(req, plugin, path))
 
53
        app = tmpl.generate(viewctx)
79
54
 
80
55
        # Global template
81
56
        ctx = genshi.template.Context()
82
 
 
83
 
        overlay_bits = self.render_overlays(req) if req.user else [[]]*4
84
 
        ctx['overlays'] = overlay_bits[0]
85
 
 
86
 
        ctx['styles'] = [media_url(req, CorePlugin, 'ivle.css')]
87
 
        ctx['styles'] += view_styles
88
 
        ctx['styles'] += overlay_bits[1]
89
 
 
90
 
        ctx['scripts'] = [media_url(req, CorePlugin, path) for path in
91
 
                           ('util.js', 'json2.js', 'md5.js')]
92
 
        ctx['scripts'].append(media_url(req, '+external/jquery', 'jquery.js'))
93
 
        ctx['scripts'] += view_scripts
94
 
        ctx['scripts'] += overlay_bits[2]
95
 
 
96
 
        ctx['scripts_init'] = self.scripts_init + overlay_bits[3]
 
57
        ctx['app_styles'] = req.styles
 
58
        ctx['scripts'] = req.scripts
 
59
        ctx['scripts_init'] = req.scripts_init
97
60
        ctx['app_template'] = app
98
 
        ctx['title_img'] = media_url(req, CorePlugin,
99
 
                                     "images/chrome/title.png")
100
61
        self.populate_headings(req, ctx)
101
62
        tmpl = loader.load(os.path.join(os.path.dirname(__file__), 
102
63
                                                        'ivle-headings.html'))
103
64
        req.write(tmpl.generate(ctx).render('xhtml', doctype='xhtml'))
104
 
        
105
 
    def populate(self, req, ctx):
106
 
        raise NotImplementedError()
107
65
 
108
66
    def populate_headings(self, req, ctx):
109
67
        ctx['favicon'] = None
110
 
        ctx['root_dir'] = req.config['urls']['root']
111
 
        ctx['public_host'] = req.config['urls']['public_host']
112
 
        ctx['svn_base'] = req.config['urls']['svn_addr']
 
68
        ctx['root_dir'] = ivle.conf.root_dir
 
69
        ctx['public_host'] = ivle.conf.public_host
113
70
        ctx['write_javascript_settings'] = req.write_javascript_settings
114
71
        if req.user:
115
72
            ctx['login'] = req.user.login
117
74
            ctx['nick'] = req.user.nick
118
75
        else:
119
76
            ctx['login'] = None
120
 
            ctx['logged_in'] = False
121
77
        ctx['publicmode'] = req.publicmode
122
 
        if hasattr(self, 'help'):
123
 
            ctx['help_path'] = self.help
124
 
 
125
78
        ctx['apps_in_tabs'] = []
126
 
        for plugin in req.config.plugin_index[ViewPlugin]:
127
 
            if not hasattr(plugin, 'tabs'):
128
 
                continue
129
 
 
130
 
            for tab in plugin.tabs:
131
 
                # tab is a tuple: name, title, desc, icon, path
132
 
                new_app = {}
133
 
                new_app['this_app'] = hasattr(self, 'tab') \
134
 
                                      and tab[0] == self.tab
135
 
 
136
 
                # Icon name
137
 
                if tab[3] is not None:
138
 
                    new_app['has_icon'] = True
139
 
                    icon_url = media_url(req, plugin, tab[3])
140
 
                    new_app['icon_url'] = icon_url
141
 
                    if new_app['this_app']:
142
 
                        ctx['favicon'] = icon_url
143
 
                else:
144
 
                    new_app['has_icon'] = False
145
 
                new_app['path'] = req.make_path(tab[4])
146
 
                new_app['desc'] = tab[2]
147
 
                new_app['name'] = tab[1]
148
 
                new_app['weight'] = tab[5]
149
 
                ctx['apps_in_tabs'].append(new_app)
150
 
 
151
 
        ctx['apps_in_tabs'].sort(key=lambda tab: tab['weight'])
152
 
 
153
 
    def render_overlays(self, req):
154
 
        """Generate XML streams for the overlays.
155
 
        
156
 
        Returns a list of streams. Populates the scripts, styles, and 
157
 
        scripts_init.
158
 
        """
159
 
        overlays = []
160
 
        styles = []
161
 
        scripts = []
162
 
        scripts_init = []
163
 
        if not self.allow_overlays:
164
 
            return (overlays, styles, scripts, scripts_init)
165
 
 
166
 
        for plugin in req.config.plugin_index[OverlayPlugin]:
167
 
            for overclass in plugin.overlays:
168
 
                if overclass in self.overlay_blacklist:
169
 
                    continue
170
 
                overlay = overclass(req)
171
 
                #TODO: Re-factor this to look nicer
172
 
                for mplugin in overlay.plugin_scripts:
173
 
                    for path in overlay.plugin_scripts[mplugin]:
174
 
                        scripts.append(media_url(req, mplugin, path))
175
 
 
176
 
                for mplugin in overlay.plugin_styles:
177
 
                    for path in overlay.plugin_styles[mplugin]:
178
 
                        styles.append(media_url(req, mplugin, path))
179
 
 
180
 
                scripts_init += overlay.plugin_scripts_init
181
 
 
182
 
                overlays.append(overlay.render(req))
183
 
        return (overlays, styles, scripts, scripts_init)
184
 
 
185
 
    @classmethod
186
 
    def get_error_view(cls, e):
187
 
        view_map = {HTTPError:    XHTMLErrorView,
188
 
                    Unauthorized: XHTMLUnauthorizedView}
189
 
        for exccls in inspect.getmro(type(e)):
190
 
            if exccls in view_map:
191
 
                return view_map[exccls]
192
 
 
193
 
class XHTMLErrorView(XHTMLView):
194
 
    template = 'xhtmlerror.html'
195
 
 
196
 
    def __init__(self, req, exception):
197
 
        self.context = exception
198
 
 
199
 
    def populate(self, req, ctx):
200
 
        ctx['exception'] = self.context
201
 
 
202
 
class XHTMLUnauthorizedView(XHTMLErrorView):
203
 
    template = 'xhtmlunauthorized.html'
204
 
 
205
 
    def __init__(self, req, exception):
206
 
        super(XHTMLUnauthorizedView, self).__init__(req, exception)
207
 
 
208
 
        if req.user is None:
209
 
            # Not logged in. Redirect to login page.
210
 
            if req.uri == '/':
211
 
                query_string = ''
 
79
        for urlname in ivle.conf.apps.apps_in_tabs:
 
80
            new_app = {}
 
81
            app = ivle.conf.apps.app_url[urlname]
 
82
            new_app['this_app'] = hasattr(self, 'appname') \
 
83
                                  and urlname == self.appname
 
84
            if app.icon:
 
85
                new_app['has_icon'] = True
 
86
                icon_dir = ivle.conf.apps.app_icon_dir
 
87
                icon_url = ivle.util.make_path(os.path.join(icon_dir, app.icon))
 
88
                new_app['icon_url'] = icon_url
 
89
                if new_app['this_app']:
 
90
                    ctx['favicon'] = icon_url
212
91
            else:
213
 
                query_string = '?url=' + urllib.quote(req.uri, safe="/~")
214
 
            req.throw_redirect('/+login' + query_string)
215
 
 
216
 
        req.status = 403
 
92
                new_app['has_icon'] = False
 
93
            new_app['path'] = ivle.util.make_path(urlname)
 
94
            new_app['desc'] = app.desc
 
95
            new_app['name'] = app.name
 
96
            ctx['apps_in_tabs'].append(new_app)