~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.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
44
    overlay_blacklist = []
1099.1.60 by William Grant
Add support in XHTMLView for plugin styles and scripts.
45
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
46
    def __init__(self, req, **kwargs):
47
        for key in kwargs:
1099.1.46 by Nick Chadwick
Fixed a slight issue in the indentation of xhtml.py
48
            setattr(self, key, kwargs[key])
1099.1.38 by William Grant
ivle.webapp.base.xhtml.XHTMLView: Split the global and view contexts.
49
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
50
    def render(self, req):
51
        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.
52
53
        # View template
54
        viewctx = genshi.template.Context()
55
        self.populate(req, viewctx)
56
57
        # The template is found in the directory of the module containing the
58
        # view.
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
59
        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
60
                        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
61
        req.write_html_head_foot = False
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)
77
        ctx['overlays'] = self.render_overlays(req)
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'] = []
113
        for plugin in req.plugin_index[ViewPlugin]:
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 = []
147
        for plugin in req.plugin_index[OverlayPlugin]:
148
            for overclass in plugin.overlays:
149
                if overclass in self.overlay_blacklist:
150
                    continue
151
                overlay = overclass(req)
152
                #TODO: Re-factor this to look nicer
153
                for mplugin in overlay.plugin_scripts:
154
                    for path in overlay.plugin_scripts[mplugin]:
155
                        req.scripts.append(media_url(req, mplugin, path))
156
157
                for mplugin in overlay.plugin_styles:
158
                    for path in overlay.plugin_styles[mplugin]:
159
                        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
160
1099.1.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
161
                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
162
1099.1.74 by Nick Chadwick
Added overlay system and console overlay. Note that the console overlay
163
                overlays.append(overlay.render(req))
164
        return overlays
1099.1.91 by William Grant
Add support for custom error views. Plugins can now declare that errors
165
1099.1.95 by William Grant
Error views are now retrieved from a class method of the view, not the plugin
166
    @classmethod
167
    def get_error_view(cls, e):
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
168
        view_map = {HTTPError:    XHTMLErrorView,
169
                    Unauthorized: XHTMLUnauthorizedView}
1099.1.95 by William Grant
Error views are now retrieved from a class method of the view, not the plugin
170
        for exccls in inspect.getmro(type(e)):
171
            if exccls in view_map:
172
                return view_map[exccls]
173
1099.1.91 by William Grant
Add support for custom error views. Plugins can now declare that errors
174
class XHTMLErrorView(XHTMLView):
175
    template = 'xhtmlerror.html'
176
177
    def __init__(self, req, exception):
178
        self.context = exception
179
180
    def populate(self, req, ctx):
181
        ctx['exception'] = self.context
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
182
183
class XHTMLUnauthorizedView(XHTMLErrorView):
184
    template = 'xhtmlunauthorized.html'
185
186
    def __init__(self, req, exception):
187
        super(XHTMLUnauthorizedView, self).__init__(req, exception)
1099.1.120 by William Grant
Move the login machinery to the new framework.
188
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
189
        if req.user is None:
190
            # Not logged in. Redirect to login page.
1099.1.120 by William Grant
Move the login machinery to the new framework.
191
            req.throw_redirect('/+login?' + 
192
                               urllib.urlencode([('url', req.uri)]))
1099.1.96 by William Grant
Add an XHTMLUnauthorizedView which redirects unauthenticated users to the
193
194
        req.status = 403