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

« back to all changes in this revision

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

  • Committer: William Grant
  • Date: 2010-02-11 05:09:56 UTC
  • Revision ID: grantw@unimelb.edu.au-20100211050956-t5i2z6b8iulxteza
Unbreak existing tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
import genshi.template
25
25
 
26
26
from ivle.webapp.media import media_url
 
27
from ivle.webapp.core import Plugin as CorePlugin
27
28
from ivle.webapp.base.views import BaseView
28
29
from ivle.webapp.base.plugins import ViewPlugin, OverlayPlugin
29
30
from ivle.webapp.errors import HTTPError, Unauthorized
30
 
import ivle.conf
31
 
import ivle.util
 
31
from ivle.webapp.publisher import NoPath
 
32
from ivle.webapp.breadcrumbs import Breadcrumber
32
33
 
33
34
class XHTMLView(BaseView):
34
35
    """
38
39
    """
39
40
 
40
41
    template = 'template.html'
41
 
    plugin_scripts = {}
42
 
    plugin_styles = {}
43
42
    allow_overlays = True
44
 
    overlay_blacklist = []
45
 
 
46
 
    def __init__(self, req, **kwargs):
47
 
        for key in kwargs:
48
 
            setattr(self, key, kwargs[key])
 
43
    breadcrumb_text = None
 
44
 
 
45
    def __init__(self, *args, **kwargs):
 
46
        super(XHTMLView, self).__init__(*args, **kwargs)
 
47
 
 
48
        self.overlay_blacklist = []
 
49
 
 
50
        self.plugin_scripts = {}
 
51
        self.plugin_styles = {}
 
52
        self.scripts_init = []
 
53
 
 
54
        self.extra_breadcrumbs = []
 
55
        self.overlay_blacklist = []
 
56
 
 
57
    def get_context_ancestry(self, req):
 
58
        return req.publisher.get_ancestors(self.context)
 
59
 
 
60
    def filter(self, stream, ctx):
 
61
        return stream
49
62
 
50
63
    def render(self, req):
51
64
        req.content_type = 'text/html' # TODO: Detect application/xhtml+xml
58
71
        # view.
59
72
        app_template = os.path.join(os.path.dirname(
60
73
                        inspect.getmodule(self).__file__), self.template) 
61
 
        req.write_html_head_foot = False
62
74
        loader = genshi.template.TemplateLoader(".", auto_reload=True)
63
75
        tmpl = loader.load(app_template)
64
 
        app = tmpl.generate(viewctx)
 
76
        app = self.filter(tmpl.generate(viewctx), viewctx)
65
77
 
 
78
        view_scripts = []
66
79
        for plugin in self.plugin_scripts:
67
80
            for path in self.plugin_scripts[plugin]:
68
 
                req.scripts.append(media_url(req, plugin, path))
 
81
                view_scripts.append(media_url(req, plugin, path))
69
82
 
 
83
        view_styles = []
70
84
        for plugin in self.plugin_styles:
71
85
            for path in self.plugin_styles[plugin]:
72
 
                req.styles.append(media_url(req, plugin, path))
 
86
                view_styles.append(media_url(req, plugin, path))
73
87
 
74
88
        # Global template
75
89
        ctx = genshi.template.Context()
76
 
        # XXX: Leave this here!! (Before req.styles is read)
77
 
        ctx['overlays'] = self.render_overlays(req)
78
 
        ctx['app_styles'] = req.styles
79
 
        ctx['scripts'] = req.scripts
80
 
        ctx['scripts_init'] = req.scripts_init
 
90
 
 
91
        overlay_bits = self.render_overlays(req) if req.user else [[]]*4
 
92
        ctx['overlays'] = overlay_bits[0]
 
93
 
 
94
        ctx['styles'] = [media_url(req, CorePlugin, 'ivle.css')]
 
95
        ctx['styles'] += view_styles
 
96
        ctx['styles'] += overlay_bits[1]
 
97
 
 
98
        ctx['scripts'] = [media_url(req, CorePlugin, path) for path in
 
99
                           ('util.js', 'json2.js', 'md5.js')]
 
100
        ctx['scripts'].append(media_url(req, '+external/jquery', 'jquery.js'))
 
101
        ctx['scripts'] += view_scripts
 
102
        ctx['scripts'] += overlay_bits[2]
 
103
 
 
104
        ctx['scripts_init'] = self.scripts_init + overlay_bits[3]
81
105
        ctx['app_template'] = app
 
106
        ctx['title_img'] = media_url(req, CorePlugin,
 
107
                                     "images/chrome/root-breadcrumb.png")
 
108
        try:
 
109
            ancestry = self.get_context_ancestry(req)
 
110
        except NoPath:
 
111
            ancestry = []
 
112
 
 
113
        crumber = Breadcrumber(req)
 
114
 
 
115
        ctx['breadcrumbs'] = []
 
116
        for ancestor in ancestry:
 
117
            crumb = crumber.crumb(ancestor)
 
118
            if crumb is None:
 
119
                continue
 
120
 
 
121
            if hasattr(crumb, 'extra_breadcrumbs_before'):
 
122
                ctx['breadcrumbs'].extend(crumb.extra_breadcrumbs_before)
 
123
            ctx['breadcrumbs'].append(crumb)
 
124
            if hasattr(crumb, 'extra_breadcrumbs_after'):
 
125
                ctx['breadcrumbs'].extend(crumb.extra_breadcrumbs_after)
 
126
 
 
127
        # If the view has specified text for a breadcrumb, add one.
 
128
        if self.breadcrumb_text:
 
129
            ctx['breadcrumbs'].append(ViewBreadcrumb(req, self))
 
130
 
 
131
        # Allow the view to add its own fake breadcrumbs.
 
132
        ctx['breadcrumbs'].extend(self.extra_breadcrumbs)
 
133
 
82
134
        self.populate_headings(req, ctx)
83
135
        tmpl = loader.load(os.path.join(os.path.dirname(__file__), 
84
136
                                                        'ivle-headings.html'))
89
141
 
90
142
    def populate_headings(self, req, ctx):
91
143
        ctx['favicon'] = None
92
 
        ctx['root_dir'] = ivle.conf.root_dir
93
 
        ctx['public_host'] = ivle.conf.public_host
 
144
        ctx['root_dir'] = req.config['urls']['root']
 
145
        ctx['public_host'] = req.config['urls']['public_host']
 
146
        ctx['svn_base'] = req.config['urls']['svn_addr']
94
147
        ctx['write_javascript_settings'] = req.write_javascript_settings
95
148
        if req.user:
96
149
            ctx['login'] = req.user.login
104
157
            ctx['help_path'] = self.help
105
158
 
106
159
        ctx['apps_in_tabs'] = []
107
 
        for plugin in req.plugin_index[ViewPlugin]:
 
160
        for plugin in req.config.plugin_index[ViewPlugin]:
108
161
            if not hasattr(plugin, 'tabs'):
109
162
                continue
110
163
 
111
164
            for tab in plugin.tabs:
112
 
                # tab is a tuple: name, title, desc, icon, path
 
165
                # tab is a tuple: name, title, desc, icon, path, weight, admin
 
166
                # (Admin is optional, defaults to false)
113
167
                new_app = {}
114
 
                new_app['this_app'] = hasattr(self, 'appname') \
115
 
                                      and tab[0] == self.appname
 
168
                new_app['this_app'] = hasattr(self, 'tab') \
 
169
                                      and tab[0] == self.tab
116
170
 
117
171
                # Icon name
118
172
                if tab[3] is not None:
123
177
                        ctx['favicon'] = icon_url
124
178
                else:
125
179
                    new_app['has_icon'] = False
126
 
                new_app['path'] = ivle.util.make_path(tab[4])
 
180
                # The following check is here, so it is AFTER setting the
 
181
                # icon, but BEFORE actually installing the tab in the menu
 
182
                if len(tab) > 6 and tab[6]:
 
183
                    # Admin-only tab
 
184
                    if not (req.user and req.user.admin):
 
185
                        break
 
186
                new_app['path'] = req.make_path(tab[4])
127
187
                new_app['desc'] = tab[2]
128
188
                new_app['name'] = tab[1]
129
189
                new_app['weight'] = tab[5]
138
198
        scripts_init.
139
199
        """
140
200
        overlays = []
 
201
        styles = []
 
202
        scripts = []
 
203
        scripts_init = []
141
204
        if not self.allow_overlays:
142
 
            return overlays
 
205
            return (overlays, styles, scripts, scripts_init)
143
206
 
144
 
        for plugin in req.plugin_index[OverlayPlugin]:
 
207
        for plugin in req.config.plugin_index[OverlayPlugin]:
145
208
            for overclass in plugin.overlays:
146
209
                if overclass in self.overlay_blacklist:
147
210
                    continue
149
212
                #TODO: Re-factor this to look nicer
150
213
                for mplugin in overlay.plugin_scripts:
151
214
                    for path in overlay.plugin_scripts[mplugin]:
152
 
                        req.scripts.append(media_url(req, mplugin, path))
 
215
                        scripts.append(media_url(req, mplugin, path))
153
216
 
154
217
                for mplugin in overlay.plugin_styles:
155
218
                    for path in overlay.plugin_styles[mplugin]:
156
 
                        req.styles.append(media_url(req, mplugin, path))
 
219
                        styles.append(media_url(req, mplugin, path))
157
220
 
158
 
                req.scripts_init += overlay.plugin_scripts_init
 
221
                scripts_init += overlay.plugin_scripts_init
159
222
 
160
223
                overlays.append(overlay.render(req))
161
 
        return overlays
 
224
        return (overlays, styles, scripts, scripts_init)
162
225
 
163
226
    @classmethod
164
227
    def get_error_view(cls, e):
171
234
class XHTMLErrorView(XHTMLView):
172
235
    template = 'xhtmlerror.html'
173
236
 
174
 
    def __init__(self, req, exception):
175
 
        self.context = exception
 
237
    def __init__(self, req, context, lastobj):
 
238
        super(XHTMLErrorView, self).__init__(req, context)
 
239
        self.lastobj = lastobj
 
240
 
 
241
    def get_context_ancestry(self, req):
 
242
        return req.publisher.get_ancestors(self.lastobj)
176
243
 
177
244
    def populate(self, req, ctx):
 
245
        ctx['req'] = req
178
246
        ctx['exception'] = self.context
179
247
 
180
248
class XHTMLUnauthorizedView(XHTMLErrorView):
181
249
    template = 'xhtmlunauthorized.html'
182
250
 
183
 
    def __init__(self, req, exception):
184
 
        super(XHTMLUnauthorizedView, self).__init__(req, exception)
 
251
    def __init__(self, req, exception, lastobj):
 
252
        super(XHTMLUnauthorizedView, self).__init__(req, exception, lastobj)
185
253
 
186
 
        if req.user is None:
 
254
        if not req.publicmode and req.user is None:
187
255
            # Not logged in. Redirect to login page.
188
 
            req.throw_redirect('/+login?' + 
189
 
                               urllib.urlencode([('url', req.uri)]))
 
256
            if req.uri == '/':
 
257
                query_string = ''
 
258
            else:
 
259
                query_string = '?url=' + urllib.quote(req.uri, safe="/~")
 
260
            req.throw_redirect('/+login' + query_string)
190
261
 
191
262
        req.status = 403
 
263
 
 
264
class ViewBreadcrumb(object):
 
265
    def __init__(self, req, context):
 
266
        self.req = req
 
267
        self.context = context
 
268
 
 
269
    @property
 
270
    def text(self):
 
271
        return self.context.breadcrumb_text