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

1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
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
1099.1.120 by William Grant
Move the login machinery to the new framework.
22
import urllib
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
23
24
import genshi.template
25
1099.1.60 by William Grant
Add support in XHTMLView for plugin styles and scripts.
26
from ivle.webapp.media import media_url
1092.1.24 by William Grant
Convince the main XHTML template to use versioned styles/scripts, and move the
27
from ivle.webapp.core import Plugin as CorePlugin
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
28
from ivle.webapp.base.views import BaseView
1099.1.115 by William Grant
Add tabs to the new framework. Move the app icons into the apps themselves.
29
from ivle.webapp.base.plugins import ViewPlugin, OverlayPlugin
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
30
from ivle.webapp.errors import HTTPError, Unauthorized
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
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
    """
1099.1.60 by William Grant
Add support in XHTMLView for plugin styles and scripts.
40
41
    template = 'template.html'
42
    plugin_scripts = {}
43
    plugin_styles = {}
1099.1.129 by William Grant
Allow XHTML views to specify that they cannot have overlays.
44
    allow_overlays = True
1099.1.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
45
    overlay_blacklist = []
1099.1.60 by William Grant
Add support in XHTMLView for plugin styles and scripts.
46
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
47
    def __init__(self, req, **kwargs):
48
        for key in kwargs:
1099.1.46 by Nick Chadwick
Fixed a slight issue in the indentation of xhtml.py
49
            setattr(self, key, kwargs[key])
1099.1.38 by William Grant
ivle.webapp.base.xhtml.XHTMLView: Split the global and view contexts.
50
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
51
    def render(self, req):
52
        req.content_type = 'text/html' # TODO: Detect application/xhtml+xml
1099.1.38 by William Grant
ivle.webapp.base.xhtml.XHTMLView: Split the global and view contexts.
53
54
        # View template
55
        viewctx = genshi.template.Context()
56
        self.populate(req, viewctx)
57
58
        # The template is found in the directory of the module containing the
59
        # view.
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
60
        app_template = os.path.join(os.path.dirname(
1099.1.35 by William Grant
ivle.webapp.base.xhtml#XHTMLView: Rename app_template to template (the things
61
                        inspect.getmodule(self).__file__), self.template) 
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
62
        loader = genshi.template.TemplateLoader(".", auto_reload=True)
63
        tmpl = loader.load(app_template)
1099.1.38 by William Grant
ivle.webapp.base.xhtml.XHTMLView: Split the global and view contexts.
64
        app = tmpl.generate(viewctx)
65
1099.1.60 by William Grant
Add support in XHTMLView for plugin styles and scripts.
66
        for plugin in self.plugin_scripts:
67
            for path in self.plugin_scripts[plugin]:
68
                req.scripts.append(media_url(req, plugin, path))
69
70
        for plugin in self.plugin_styles:
71
            for path in self.plugin_styles[plugin]:
72
                req.styles.append(media_url(req, plugin, path))
73
1099.1.38 by William Grant
ivle.webapp.base.xhtml.XHTMLView: Split the global and view contexts.
74
        # Global template
75
        ctx = genshi.template.Context()
1099.1.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
76
        # XXX: Leave this here!! (Before req.styles is read)
1099.1.206 by William Grant
Only display tabs and overlays when we are logged in, and JavaScript settings
77
        ctx['overlays'] = self.render_overlays(req) if req.user else []
1092.1.24 by William Grant
Convince the main XHTML template to use versioned styles/scripts, and move the
78
79
        ctx['styles'] = [media_url(req, CorePlugin, 'ivle.css')]
80
        ctx['styles'] += req.styles
81
82
        ctx['scripts'] = [media_url(req, CorePlugin, path) for path in
1099.1.214 by Nick Chadwick
The skeleton for editing an exercise has now been created. The next
83
                           ('util.js', 'json2.js', 'md5.js', 'jquery.js')]
1092.1.24 by William Grant
Convince the main XHTML template to use versioned styles/scripts, and move the
84
        ctx['scripts'] += req.scripts
85
1099.1.38 by William Grant
ivle.webapp.base.xhtml.XHTMLView: Split the global and view contexts.
86
        ctx['scripts_init'] = req.scripts_init
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
87
        ctx['app_template'] = app
1100.1.9 by Matt Giuca
The IVLE logo is now an <img> element, rather than a CSS background.
88
        ctx['title_img'] = media_url(req, CorePlugin,
89
                                     "images/chrome/title.png")
1099.1.38 by William Grant
ivle.webapp.base.xhtml.XHTMLView: Split the global and view contexts.
90
        self.populate_headings(req, ctx)
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
91
        tmpl = loader.load(os.path.join(os.path.dirname(__file__), 
92
                                                        'ivle-headings.html'))
93
        req.write(tmpl.generate(ctx).render('xhtml', doctype='xhtml'))
1099.1.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
94
        
95
    def populate(self, req, ctx):
96
        raise NotImplementedError()
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
97
98
    def populate_headings(self, req, ctx):
99
        ctx['favicon'] = None
100
        ctx['root_dir'] = ivle.conf.root_dir
101
        ctx['public_host'] = ivle.conf.public_host
102
        ctx['write_javascript_settings'] = req.write_javascript_settings
103
        if req.user:
104
            ctx['login'] = req.user.login
105
            ctx['logged_in'] = True
106
            ctx['nick'] = req.user.nick
107
        else:
108
            ctx['login'] = None
1099.1.92 by William Grant
Fix the XHTML base template to not crash when not logged in.
109
            ctx['logged_in'] = False
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
110
        ctx['publicmode'] = req.publicmode
1099.1.100 by Nick Chadwick
Created a new help system.
111
        if hasattr(self, 'help'):
112
            ctx['help_path'] = self.help
1099.1.115 by William Grant
Add tabs to the new framework. Move the app icons into the apps themselves.
113
114
        ctx['apps_in_tabs'] = []
1092.1.59 by William Grant
Move the plugin loading/indexing logic into ivle.config.Config.
115
        for plugin in req.config.plugin_index[ViewPlugin]:
1099.1.115 by William Grant
Add tabs to the new framework. Move the app icons into the apps themselves.
116
            if not hasattr(plugin, 'tabs'):
117
                continue
118
119
            for tab in plugin.tabs:
120
                # tab is a tuple: name, title, desc, icon, path
121
                new_app = {}
1116 by William Grant
Move the old tutorial views into the 'subjects' tab, so they get the right
122
                new_app['this_app'] = hasattr(self, 'tab') \
123
                                      and tab[0] == self.tab
1099.1.115 by William Grant
Add tabs to the new framework. Move the app icons into the apps themselves.
124
125
                # Icon name
126
                if tab[3] is not None:
127
                    new_app['has_icon'] = True
128
                    icon_url = media_url(req, plugin, tab[3])
129
                    new_app['icon_url'] = icon_url
130
                    if new_app['this_app']:
131
                        ctx['favicon'] = icon_url
132
                else:
133
                    new_app['has_icon'] = False
134
                new_app['path'] = ivle.util.make_path(tab[4])
135
                new_app['desc'] = tab[2]
136
                new_app['name'] = tab[1]
137
                new_app['weight'] = tab[5]
138
                ctx['apps_in_tabs'].append(new_app)
139
140
        ctx['apps_in_tabs'].sort(key=lambda tab: tab['weight'])
141
1099.1.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
142
    def render_overlays(self, req):
143
        """Generate XML streams for the overlays.
144
        
145
        Returns a list of streams. Populates the scripts, styles, and 
146
        scripts_init.
147
        """
148
        overlays = []
1099.1.129 by William Grant
Allow XHTML views to specify that they cannot have overlays.
149
        if not self.allow_overlays:
150
            return overlays
151
1092.1.59 by William Grant
Move the plugin loading/indexing logic into ivle.config.Config.
152
        for plugin in req.config.plugin_index[OverlayPlugin]:
1099.1.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
153
            for overclass in plugin.overlays:
154
                if overclass in self.overlay_blacklist:
155
                    continue
156
                overlay = overclass(req)
157
                #TODO: Re-factor this to look nicer
158
                for mplugin in overlay.plugin_scripts:
159
                    for path in overlay.plugin_scripts[mplugin]:
160
                        req.scripts.append(media_url(req, mplugin, path))
161
162
                for mplugin in overlay.plugin_styles:
163
                    for path in overlay.plugin_styles[mplugin]:
164
                        req.styles.append(media_url(req, mplugin, path))
1099.1.91 by William Grant
Add support for custom error views. Plugins can now declare that errors
165
1099.1.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
166
                req.scripts_init += overlay.plugin_scripts_init
1099.1.91 by William Grant
Add support for custom error views. Plugins can now declare that errors
167
1099.1.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
168
                overlays.append(overlay.render(req))
169
        return overlays
1099.1.91 by William Grant
Add support for custom error views. Plugins can now declare that errors
170
1099.1.95 by William Grant
Error views are now retrieved from a class method of the view, not the plugin
171
    @classmethod
172
    def get_error_view(cls, e):
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
173
        view_map = {HTTPError:    XHTMLErrorView,
174
                    Unauthorized: XHTMLUnauthorizedView}
1099.1.95 by William Grant
Error views are now retrieved from a class method of the view, not the plugin
175
        for exccls in inspect.getmro(type(e)):
176
            if exccls in view_map:
177
                return view_map[exccls]
178
1099.1.91 by William Grant
Add support for custom error views. Plugins can now declare that errors
179
class XHTMLErrorView(XHTMLView):
180
    template = 'xhtmlerror.html'
181
182
    def __init__(self, req, exception):
183
        self.context = exception
184
185
    def populate(self, req, ctx):
186
        ctx['exception'] = self.context
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
187
188
class XHTMLUnauthorizedView(XHTMLErrorView):
189
    template = 'xhtmlunauthorized.html'
190
191
    def __init__(self, req, exception):
192
        super(XHTMLUnauthorizedView, self).__init__(req, exception)
1099.1.120 by William Grant
Move the login machinery to the new framework.
193
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
194
        if req.user is None:
195
            # Not logged in. Redirect to login page.
1099.1.209 by William Grant
Don't escape / in paths when they are in +login/+tos URLs.
196
            if req.uri == '/':
197
                query_string = ''
198
            else:
199
                query_string = '?url=' + urllib.quote(req.uri, safe="/~")
200
            req.throw_redirect('/+login' + query_string)
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
201
202
        req.status = 403