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

« back to all changes in this revision

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

  • Committer: mattgiuca
  • Date: 2008-01-10 00:10:11 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:149
fileservice:
    * Both subversion and OS mode listings now output "." as one of the files.
        This is deliberate in order for the client to see (by the presence or
        absence of the "svnstatus" attribute) whether this directory is
        under version control.
    * Directories no longer display a "type" attribute (since this was always
        just the default type, it's meaningless).
    * Fixed bug where unversioned directories inside a versioned directory
        output an empty listing.

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
 
 
32
 
class XHTMLView(BaseView):
33
 
    """
34
 
    A view which provides a base class for views which need to return XHTML
35
 
    It is expected that apps which use this view will be written using Genshi
36
 
    templates.
37
 
    """
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
 
    def __init__(self, req, **kwargs):
49
 
        for key in kwargs:
50
 
            setattr(self, key, kwargs[key])
51
 
 
52
 
    def filter(self, stream, ctx):
53
 
        return stream
54
 
 
55
 
    def render(self, req):
56
 
        req.content_type = 'text/html' # TODO: Detect application/xhtml+xml
57
 
 
58
 
        # View template
59
 
        viewctx = genshi.template.Context()
60
 
        self.populate(req, viewctx)
61
 
 
62
 
        # The template is found in the directory of the module containing the
63
 
        # view.
64
 
        app_template = os.path.join(os.path.dirname(
65
 
                        inspect.getmodule(self).__file__), self.template) 
66
 
        loader = genshi.template.TemplateLoader(".", auto_reload=True)
67
 
        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))
79
 
 
80
 
        # Global template
81
 
        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]
97
 
        ctx['app_template'] = app
98
 
        ctx['title_img'] = media_url(req, CorePlugin,
99
 
                                     "images/chrome/title.png")
100
 
        self.populate_headings(req, ctx)
101
 
        tmpl = loader.load(os.path.join(os.path.dirname(__file__), 
102
 
                                                        'ivle-headings.html'))
103
 
        req.write(tmpl.generate(ctx).render('xhtml', doctype='xhtml'))
104
 
        
105
 
    def populate(self, req, ctx):
106
 
        raise NotImplementedError()
107
 
 
108
 
    def populate_headings(self, req, ctx):
109
 
        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']
113
 
        ctx['write_javascript_settings'] = req.write_javascript_settings
114
 
        if req.user:
115
 
            ctx['login'] = req.user.login
116
 
            ctx['logged_in'] = True
117
 
            ctx['nick'] = req.user.nick
118
 
        else:
119
 
            ctx['login'] = None
120
 
            ctx['logged_in'] = False
121
 
        ctx['publicmode'] = req.publicmode
122
 
        if hasattr(self, 'help'):
123
 
            ctx['help_path'] = self.help
124
 
 
125
 
        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 = ''
212
 
            else:
213
 
                query_string = '?url=' + urllib.quote(req.uri, safe="/~")
214
 
            req.throw_redirect('/+login' + query_string)
215
 
 
216
 
        req.status = 403