~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
1092.1.28 by William Grant
Only load tos.js on /+tos.
83
                           ('util.js', 'json2.js', 'md5.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
1099.1.38 by William Grant
ivle.webapp.base.xhtml.XHTMLView: Split the global and view contexts.
88
        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
89
        tmpl = loader.load(os.path.join(os.path.dirname(__file__), 
90
                                                        'ivle-headings.html'))
91
        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
92
        
93
    def populate(self, req, ctx):
94
        raise NotImplementedError()
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
95
96
    def populate_headings(self, req, ctx):
97
        ctx['favicon'] = None
98
        ctx['root_dir'] = ivle.conf.root_dir
99
        ctx['public_host'] = ivle.conf.public_host
100
        ctx['write_javascript_settings'] = req.write_javascript_settings
101
        if req.user:
102
            ctx['login'] = req.user.login
103
            ctx['logged_in'] = True
104
            ctx['nick'] = req.user.nick
105
        else:
106
            ctx['login'] = None
1099.1.92 by William Grant
Fix the XHTML base template to not crash when not logged in.
107
            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
108
        ctx['publicmode'] = req.publicmode
1099.1.100 by Nick Chadwick
Created a new help system.
109
        if hasattr(self, 'help'):
110
            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.
111
112
        ctx['apps_in_tabs'] = []
1092.1.59 by William Grant
Move the plugin loading/indexing logic into ivle.config.Config.
113
        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.
114
            if not hasattr(plugin, 'tabs'):
115
                continue
116
117
            for tab in plugin.tabs:
118
                # tab is a tuple: name, title, desc, icon, path
119
                new_app = {}
120
                new_app['this_app'] = hasattr(self, 'appname') \
121
                                      and tab[0] == self.appname
122
123
                # Icon name
124
                if tab[3] is not None:
125
                    new_app['has_icon'] = True
126
                    icon_url = media_url(req, plugin, tab[3])
127
                    new_app['icon_url'] = icon_url
128
                    if new_app['this_app']:
129
                        ctx['favicon'] = icon_url
130
                else:
131
                    new_app['has_icon'] = False
132
                new_app['path'] = ivle.util.make_path(tab[4])
133
                new_app['desc'] = tab[2]
134
                new_app['name'] = tab[1]
135
                new_app['weight'] = tab[5]
136
                ctx['apps_in_tabs'].append(new_app)
137
138
        ctx['apps_in_tabs'].sort(key=lambda tab: tab['weight'])
139
1099.1.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
140
    def render_overlays(self, req):
141
        """Generate XML streams for the overlays.
142
        
143
        Returns a list of streams. Populates the scripts, styles, and 
144
        scripts_init.
145
        """
146
        overlays = []
1099.1.129 by William Grant
Allow XHTML views to specify that they cannot have overlays.
147
        if not self.allow_overlays:
148
            return overlays
149
1092.1.59 by William Grant
Move the plugin loading/indexing logic into ivle.config.Config.
150
        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
151
            for overclass in plugin.overlays:
152
                if overclass in self.overlay_blacklist:
153
                    continue
154
                overlay = overclass(req)
155
                #TODO: Re-factor this to look nicer
156
                for mplugin in overlay.plugin_scripts:
157
                    for path in overlay.plugin_scripts[mplugin]:
158
                        req.scripts.append(media_url(req, mplugin, path))
159
160
                for mplugin in overlay.plugin_styles:
161
                    for path in overlay.plugin_styles[mplugin]:
162
                        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
163
1099.1.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
164
                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
165
1099.1.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
166
                overlays.append(overlay.render(req))
167
        return overlays
1099.1.91 by William Grant
Add support for custom error views. Plugins can now declare that errors
168
1099.1.95 by William Grant
Error views are now retrieved from a class method of the view, not the plugin
169
    @classmethod
170
    def get_error_view(cls, e):
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
171
        view_map = {HTTPError:    XHTMLErrorView,
172
                    Unauthorized: XHTMLUnauthorizedView}
1099.1.95 by William Grant
Error views are now retrieved from a class method of the view, not the plugin
173
        for exccls in inspect.getmro(type(e)):
174
            if exccls in view_map:
175
                return view_map[exccls]
176
1099.1.91 by William Grant
Add support for custom error views. Plugins can now declare that errors
177
class XHTMLErrorView(XHTMLView):
178
    template = 'xhtmlerror.html'
179
180
    def __init__(self, req, exception):
181
        self.context = exception
182
183
    def populate(self, req, ctx):
184
        ctx['exception'] = self.context
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
185
186
class XHTMLUnauthorizedView(XHTMLErrorView):
187
    template = 'xhtmlunauthorized.html'
188
189
    def __init__(self, req, exception):
190
        super(XHTMLUnauthorizedView, self).__init__(req, exception)
1099.1.120 by William Grant
Move the login machinery to the new framework.
191
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
192
        if req.user is None:
193
            # 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.
194
            if req.uri == '/':
195
                query_string = ''
196
            else:
197
                query_string = '?url=' + urllib.quote(req.uri, safe="/~")
198
            req.throw_redirect('/+login' + query_string)
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
199
200
        req.status = 403