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

« back to all changes in this revision

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

  • Committer: Matt Giuca
  • Date: 2009-04-22 04:13:54 UTC
  • Revision ID: matt.giuca@gmail.com-20090422041354-atmqpak2c7hd37ym
ivle.config: Fixed docstring.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# IVLE - Informatics Virtual Learning Environment
 
2
# Copyright (C) 2007-2009 The University of Melbourne
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 
 
18
# Author: Nick Chadwick
 
19
 
 
20
import inspect
 
21
import os.path
 
22
import urllib
 
23
 
 
24
import genshi.template
 
25
 
 
26
from ivle.webapp.media import media_url
 
27
from ivle.webapp.core import Plugin as CorePlugin
 
28
from ivle.webapp.base.views import BaseView
 
29
from ivle.webapp.base.plugins import ViewPlugin, OverlayPlugin
 
30
from ivle.webapp.errors import HTTPError, Unauthorized
 
31
import ivle.conf
 
32
import ivle.util
 
33
 
 
34
class XHTMLView(BaseView):
 
35
    """
 
36
    A view which provides a base class for views which need to return XHTML
 
37
    It is expected that apps which use this view will be written using Genshi
 
38
    templates.
 
39
    """
 
40
 
 
41
    template = 'template.html'
 
42
    plugin_scripts = {}
 
43
    plugin_styles = {}
 
44
    allow_overlays = True
 
45
    overlay_blacklist = []
 
46
 
 
47
    def __init__(self, req, **kwargs):
 
48
        for key in kwargs:
 
49
            setattr(self, key, kwargs[key])
 
50
 
 
51
    def filter(self, stream, ctx):
 
52
        return stream
 
53
 
 
54
    def render(self, req):
 
55
        req.content_type = 'text/html' # TODO: Detect application/xhtml+xml
 
56
 
 
57
        # View template
 
58
        viewctx = genshi.template.Context()
 
59
        self.populate(req, viewctx)
 
60
 
 
61
        # The template is found in the directory of the module containing the
 
62
        # view.
 
63
        app_template = os.path.join(os.path.dirname(
 
64
                        inspect.getmodule(self).__file__), self.template) 
 
65
        loader = genshi.template.TemplateLoader(".", auto_reload=True)
 
66
        tmpl = loader.load(app_template)
 
67
        app = self.filter(tmpl.generate(viewctx), viewctx)
 
68
 
 
69
        for plugin in self.plugin_scripts:
 
70
            for path in self.plugin_scripts[plugin]:
 
71
                req.scripts.append(media_url(req, plugin, path))
 
72
 
 
73
        for plugin in self.plugin_styles:
 
74
            for path in self.plugin_styles[plugin]:
 
75
                req.styles.append(media_url(req, plugin, path))
 
76
 
 
77
        # Global template
 
78
        ctx = genshi.template.Context()
 
79
        # XXX: Leave this here!! (Before req.styles is read)
 
80
        ctx['overlays'] = self.render_overlays(req) if req.user else []
 
81
 
 
82
        ctx['styles'] = [media_url(req, CorePlugin, 'ivle.css')]
 
83
        ctx['styles'] += req.styles
 
84
 
 
85
        ctx['scripts'] = [media_url(req, CorePlugin, path) for path in
 
86
                           ('util.js', 'json2.js', 'md5.js')]
 
87
        ctx['scripts'].append(media_url(req, '+external/jquery', 'jquery.js'))
 
88
        ctx['scripts'] += req.scripts
 
89
 
 
90
        ctx['scripts_init'] = req.scripts_init
 
91
        ctx['app_template'] = app
 
92
        ctx['title_img'] = media_url(req, CorePlugin,
 
93
                                     "images/chrome/title.png")
 
94
        self.populate_headings(req, ctx)
 
95
        tmpl = loader.load(os.path.join(os.path.dirname(__file__), 
 
96
                                                        'ivle-headings.html'))
 
97
        req.write(tmpl.generate(ctx).render('xhtml', doctype='xhtml'))
 
98
        
 
99
    def populate(self, req, ctx):
 
100
        raise NotImplementedError()
 
101
 
 
102
    def populate_headings(self, req, ctx):
 
103
        ctx['favicon'] = None
 
104
        ctx['root_dir'] = ivle.conf.root_dir
 
105
        ctx['public_host'] = ivle.conf.public_host
 
106
        ctx['svn_base'] = ivle.conf.svn_addr
 
107
        ctx['write_javascript_settings'] = req.write_javascript_settings
 
108
        if req.user:
 
109
            ctx['login'] = req.user.login
 
110
            ctx['logged_in'] = True
 
111
            ctx['nick'] = req.user.nick
 
112
        else:
 
113
            ctx['login'] = None
 
114
            ctx['logged_in'] = False
 
115
        ctx['publicmode'] = req.publicmode
 
116
        if hasattr(self, 'help'):
 
117
            ctx['help_path'] = self.help
 
118
 
 
119
        ctx['apps_in_tabs'] = []
 
120
        for plugin in req.config.plugin_index[ViewPlugin]:
 
121
            if not hasattr(plugin, 'tabs'):
 
122
                continue
 
123
 
 
124
            for tab in plugin.tabs:
 
125
                # tab is a tuple: name, title, desc, icon, path
 
126
                new_app = {}
 
127
                new_app['this_app'] = hasattr(self, 'tab') \
 
128
                                      and tab[0] == self.tab
 
129
 
 
130
                # Icon name
 
131
                if tab[3] is not None:
 
132
                    new_app['has_icon'] = True
 
133
                    icon_url = media_url(req, plugin, tab[3])
 
134
                    new_app['icon_url'] = icon_url
 
135
                    if new_app['this_app']:
 
136
                        ctx['favicon'] = icon_url
 
137
                else:
 
138
                    new_app['has_icon'] = False
 
139
                new_app['path'] = ivle.util.make_path(tab[4])
 
140
                new_app['desc'] = tab[2]
 
141
                new_app['name'] = tab[1]
 
142
                new_app['weight'] = tab[5]
 
143
                ctx['apps_in_tabs'].append(new_app)
 
144
 
 
145
        ctx['apps_in_tabs'].sort(key=lambda tab: tab['weight'])
 
146
 
 
147
    def render_overlays(self, req):
 
148
        """Generate XML streams for the overlays.
 
149
        
 
150
        Returns a list of streams. Populates the scripts, styles, and 
 
151
        scripts_init.
 
152
        """
 
153
        overlays = []
 
154
        if not self.allow_overlays:
 
155
            return overlays
 
156
 
 
157
        for plugin in req.config.plugin_index[OverlayPlugin]:
 
158
            for overclass in plugin.overlays:
 
159
                if overclass in self.overlay_blacklist:
 
160
                    continue
 
161
                overlay = overclass(req)
 
162
                #TODO: Re-factor this to look nicer
 
163
                for mplugin in overlay.plugin_scripts:
 
164
                    for path in overlay.plugin_scripts[mplugin]:
 
165
                        req.scripts.append(media_url(req, mplugin, path))
 
166
 
 
167
                for mplugin in overlay.plugin_styles:
 
168
                    for path in overlay.plugin_styles[mplugin]:
 
169
                        req.styles.append(media_url(req, mplugin, path))
 
170
 
 
171
                req.scripts_init += overlay.plugin_scripts_init
 
172
 
 
173
                overlays.append(overlay.render(req))
 
174
        return overlays
 
175
 
 
176
    @classmethod
 
177
    def get_error_view(cls, e):
 
178
        view_map = {HTTPError:    XHTMLErrorView,
 
179
                    Unauthorized: XHTMLUnauthorizedView}
 
180
        for exccls in inspect.getmro(type(e)):
 
181
            if exccls in view_map:
 
182
                return view_map[exccls]
 
183
 
 
184
class XHTMLErrorView(XHTMLView):
 
185
    template = 'xhtmlerror.html'
 
186
 
 
187
    def __init__(self, req, exception):
 
188
        self.context = exception
 
189
 
 
190
    def populate(self, req, ctx):
 
191
        ctx['exception'] = self.context
 
192
 
 
193
class XHTMLUnauthorizedView(XHTMLErrorView):
 
194
    template = 'xhtmlunauthorized.html'
 
195
 
 
196
    def __init__(self, req, exception):
 
197
        super(XHTMLUnauthorizedView, self).__init__(req, exception)
 
198
 
 
199
        if req.user is None:
 
200
            # Not logged in. Redirect to login page.
 
201
            if req.uri == '/':
 
202
                query_string = ''
 
203
            else:
 
204
                query_string = '?url=' + urllib.quote(req.uri, safe="/~")
 
205
            req.throw_redirect('/+login' + query_string)
 
206
 
 
207
        req.status = 403