') % (
_('Geolocation'),
@@ -766,217 +710,6 @@ class SettingsDirectory(QommonSettingsDirectory):
get_publisher().write_cfg()
return redirect('.')
- def themes(self):
- request = get_request()
-
- if 'theme' not in request.form:
- current_theme = get_cfg('branding', {}).get('theme', 'default')
-
- get_response().breadcrumb.append(('themes', _('Themes')))
- html_top('settings', title=_('Themes'))
- r = TemplateIO(html=True)
- r += htmltext("
%s
") % _('Themes')
-
- r += get_session().display_message()
-
- r += htmltext('%s') % _('Install New Theme')
-
- r += htmltext('')
- return r.getvalue()
- else:
- themes = template.get_themes()
- if str(request.form['theme']) in themes:
- branding_cfg = get_cfg('branding', {})
- branding_cfg['theme'] = str(request.form['theme'])
- get_publisher().cfg['branding'] = branding_cfg
- get_publisher().write_cfg()
- return redirect('.')
-
- def download_theme(self):
- theme_id = get_request().form.get('theme')
- if not theme_id:
- return redirect('themes')
-
- theme_directory = template.get_theme_directory(theme_id)
- if not theme_directory:
- return redirect('themes')
-
- parent_theme_directory = os.path.dirname(theme_directory)
- c = io.BytesIO()
- with zipfile.ZipFile(c, 'w') as z:
- for base, dummy, filenames in os.walk(theme_directory):
- basetheme = base[len(parent_theme_directory) + 1 :]
- for filename in filenames:
- z.write(os.path.join(base, filename), os.path.join(basetheme, filename))
-
- response = get_response()
- response.set_content_type('application/zip')
- response.set_header('content-disposition', 'attachment; filename=%s.zip' % theme_id)
- return c.getvalue()
-
- def install_theme(self):
- form = Form(enctype='multipart/form-data')
- form.add(FileWidget, 'file', title=_('Theme File'), required=False)
- form.add(UrlWidget, 'url', title=_('Theme Address'), required=False, size=50)
- form.add_submit('submit', _('Install'))
- form.add_submit('cancel', _('Cancel'))
-
- if form.get_submit() == 'cancel':
- return redirect('.')
-
- if form.is_submitted() and not form.has_errors():
- try:
- return self.install_theme_submit(form)
- except ValueError:
- form.get_widget('file').set_error(_('Invalid Theme'))
-
- get_response().breadcrumb.append(('install_theme', _('Install Theme')))
- html_top('forms', title=_('Install Theme'))
- r = TemplateIO(html=True)
- r += htmltext('
%s
') % _('Install Theme')
- r += htmltext('
%s
') % _(
- 'You can install a new theme by uploading a file or by pointing to the theme URL.'
- )
- r += form.render()
- return r.getvalue()
-
- def install_theme_submit(self, form):
- if form.get_widget('url').parse():
- return self.install_theme_from_url(form.get_widget('url').parse())
- if form.get_widget('file').parse():
- return self.install_theme_from_file(form.get_widget('file').parse().fp)
- get_session().message = ('error', _('You have to enter a file or a URL.'))
- return redirect('themes')
-
- def install_theme_from_file(self, fp):
- try:
- with zipfile.ZipFile(fp, 'r') as z:
- theme_dir = os.path.join(get_publisher().app_dir, 'themes')
- filename_list = [x for x in z.namelist() if x[0] != '/' and x[-1] != '/']
- if len(filename_list) == 0:
- get_session().message = ('error', _('Empty theme file.'))
- return redirect('themes')
- theme_name = filename_list[0].split('/')[0]
- if ('%s/desc.xml' % theme_name) not in filename_list:
- get_session().message = ('error', _('Theme is missing a desc.xml file.'))
- return redirect('themes')
- desc_xml = z.read('%s/desc.xml' % theme_name)
- theme_dict = template.get_theme_dict(io.StringIO(force_text(desc_xml)))
- if theme_dict.get('name') != theme_name:
- get_session().message = ('error', _('desc.xml is missing a name attribute.'))
- return redirect('themes')
- if os.path.exists(os.path.join(theme_dir, theme_name)):
- shutil.rmtree(os.path.join(theme_dir, theme_name))
- for f in z.namelist():
- if f[-1] == '/':
- continue
- path = os.path.join(theme_dir, f)
- data = z.read(f)
- if not os.path.exists(os.path.dirname(path)):
- os.makedirs(os.path.dirname(path))
- with open(path, 'wb') as _f:
- _f.write(data)
- return redirect('themes')
- except Exception as e:
- get_session().message = ('error', _('Failed to read theme file. (%s)') % str(e))
- return redirect('themes')
-
- def install_theme_from_url(self, url):
- try:
- fp = misc.urlopen(url)
- except misc.ConnectionError as e:
- get_session().message = ('error', _('Error loading theme (%s).') % str(e))
- return redirect('themes')
-
- return self.install_theme_from_file(io.StringIO(fp.read()))
-
- def template(self):
- from wcs.qommon.template import get_default_ezt_template
-
- default_template_ezt = get_default_ezt_template()
- branding_cfg = get_cfg('branding', {})
- template = branding_cfg.get('template', default_template_ezt)
- form = Form(enctype="multipart/form-data")
- form.add(TextWidget, 'template', title=_('Site Template'), value=template, cols=80, rows=25)
- form.add_submit('submit', _('Submit'))
- form.add_submit('restore-default', _('Restore default template'))
- form.add_submit('cancel', _('Cancel'))
- if form.get_widget('cancel').parse():
- return redirect('.')
-
- if form.get_submit() == 'cancel':
- return redirect('.')
-
- if form.get_submit() == 'restore-default':
- self.template_submit()
- return redirect('.')
-
- if form.is_submitted() and not form.has_errors():
- self.template_submit(form)
- return redirect('.')
-
- get_response().breadcrumb.append(('template', _('Template')))
- html_top('settings', title=_('Template'))
- r = TemplateIO(html=True)
- r += htmltext('
%s
') % _('Template')
- r += form.render()
- return r.getvalue()
-
- def template_submit(self, form=None):
- from wcs.qommon.template import DEFAULT_TEMPLATE_EZT, get_default_ezt_template
-
- theme_default_template_ezt = get_default_ezt_template()
-
- get_publisher().reload_cfg()
- branding_cfg = get_cfg('branding', {})
- if not form:
- template = None
- else:
- template = form.get_widget('template').parse()
- if template in (DEFAULT_TEMPLATE_EZT, theme_default_template_ezt) or not template:
- if 'template' in branding_cfg:
- del branding_cfg['template']
- else:
- branding_cfg['template'] = template
- get_publisher().cfg['branding'] = branding_cfg
- get_publisher().write_cfg()
-
def export(self):
if get_request().form.get('download'):
return self.export_download()
diff --git a/wcs/compat.py b/wcs/compat.py
index 2ced96fea..3dd646764 100644
--- a/wcs/compat.py
+++ b/wcs/compat.py
@@ -14,7 +14,6 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
-import os
from contextlib import contextmanager
from threading import Lock
@@ -31,7 +30,7 @@ from quixote.http_request import Upload
from .publisher import WcsPublisher
from .qommon import force_str, template
from .qommon.http_request import HTTPRequest
-from .qommon.publisher import get_cfg, set_publisher_class
+from .qommon.publisher import set_publisher_class
class TemplateWithFallbackView(TemplateView):
@@ -65,8 +64,8 @@ class TemplateWithFallbackView(TemplateView):
elif request.headers.get('X-Popup') == 'true':
response = HttpResponse('
%s
' % context['body'])
elif 'raw' in (getattr(self.quixote_response, 'filter') or {}):
- # used for theme preview (generated in /backoffice/ but cannot
- # obviously receive the admin template.
+ # used for raw HTML snippets (for example in the test tool
+ # results in inspect page).
response = HttpResponse(context['body'])
else:
response = self.render_to_response(context)
@@ -145,19 +144,6 @@ class CompatWcsPublisher(WcsPublisher):
return output
if request.headers.get('X-Popup') == 'true':
return '
%s
' % output
- if response.filter and response.filter.get('admin_ezt'):
- return self.render_response(output)
-
- current_theme = get_cfg('branding', {}).get('theme', 'default')
- theme_directory = template.get_theme_directory(current_theme)
- if not theme_directory:
- return self.render_response(output)
-
- if not os.path.exists(os.path.join(theme_directory, 'templates')):
- return self.render_response(output)
-
- if not os.path.exists(os.path.join(theme_directory, 'templates/wcs/base.html')):
- return self.render_response(output)
if isinstance(output, template.QommonTemplateResponse):
template_response = output
diff --git a/wcs/qommon/publisher.py b/wcs/qommon/publisher.py
index ed7be5e22..149fca327 100644
--- a/wcs/qommon/publisher.py
+++ b/wcs/qommon/publisher.py
@@ -116,7 +116,7 @@ class QommonPublisher(Publisher):
after_login_url = ''
qommon_static_dir = 'static/'
qommon_admin_css = 'css/dc2/admin.css'
- default_theme = 'default'
+ default_theme = 'django'
site_options = None
site_charset = 'utf-8'
@@ -346,11 +346,6 @@ class QommonPublisher(Publisher):
return error_page
- def render_response(self, content):
- if isinstance(content, template.QommonTemplateResponse):
- content = template.render(content.templates, content.context)
- return template.decorate(content, self.get_request().response)
-
def install_lang(self, request=None):
if request:
lang = request.language
diff --git a/wcs/qommon/template.py b/wcs/qommon/template.py
index 8e4f33a6b..5604fbfee 100644
--- a/wcs/qommon/template.py
+++ b/wcs/qommon/template.py
@@ -14,11 +14,9 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
-import glob
import io
import os
import re
-import xml.etree.ElementTree as ET
import django.template
from django.template import TemplateSyntaxError as DjangoTemplateSyntaxError
@@ -27,9 +25,7 @@ from django.template import engines
from django.template.loader import render_to_string
from django.utils.encoding import force_text, smart_text
from quixote import get_publisher, get_request, get_response, get_session
-from quixote.directory import Directory
from quixote.html import TemplateIO, htmlescape, htmltext
-from quixote.util import StaticDirectory, StaticFile
from . import ezt, force_str
@@ -53,123 +49,6 @@ def get_theme_directory(theme_id):
return location
-class ThemesDirectory(Directory):
- def _q_lookup(self, component):
- from . import errors
-
- if component in ('.', '..'):
- raise errors.TraversalError()
-
- location = get_theme_directory(component)
- if location is None:
- raise errors.TraversalError()
-
- if os.path.isdir(location):
- return StaticDirectory(location)
- else:
- return StaticFile(location)
-
-
-def get_themes_dict():
- system_location = os.path.join(get_publisher().data_dir, 'themes')
- local_location = os.path.join(get_publisher().app_dir, 'themes')
-
- themes = {}
- for theme_xml in glob.glob(os.path.join(system_location, '*/desc.xml')) + glob.glob(
- os.path.join(local_location, '*/desc.xml')
- ):
- theme_dict = get_theme_dict(theme_xml)
- if not theme_dict:
- continue
- themes[theme_dict.get('name')] = theme_dict
- return themes
-
-
-def get_theme_dict(theme_xml):
- try:
- tree = ET.parse(theme_xml).getroot()
- except Exception: # parse error
- return None
- name = force_str(tree.attrib['name'])
- version = force_str(tree.attrib.get('version') or '')
- label = force_str(tree.findtext('label') or '')
- desc = force_str(tree.findtext('desc') or '')
- author = force_str(tree.findtext('author') or '')
- icon = None
- if isinstance(theme_xml, str):
- icon = os.path.join(os.path.dirname(theme_xml), 'icon.png')
- if not os.path.exists(icon):
- icon = None
- theme = {'name': name, 'label': label, 'desc': desc, 'author': author, 'icon': icon, 'version': version}
- theme['keywords'] = []
- for keyword in tree.findall('keywords/keyword'):
- theme['keywords'].append(keyword.text)
- return theme
-
-
-def get_themes():
- # backward compatibility function, it returns a tuple with theme info,
- # newer code should use get_themes_dict()
- themes = {}
- for k, v in get_themes_dict().items():
- themes[k] = (v['label'], v['desc'], v['author'], v['icon'])
- return themes
-
-
-def get_current_theme():
- from .publisher import get_cfg
-
- current_theme = get_cfg('branding', {}).get('theme', 'default')
- system_location = os.path.join(get_publisher().data_dir, 'themes', current_theme)
- local_location = os.path.join(get_publisher().app_dir, 'themes', current_theme)
- for location in (local_location, system_location):
- if os.path.exists(location):
- return get_theme_dict(os.path.join(location, 'desc.xml'))
- default_theme_location = os.path.join(get_publisher().data_dir, 'themes', 'default')
- return get_theme_dict(os.path.join(default_theme_location, 'desc.xml'))
-
-
-DEFAULT_TEMPLATE_EZT = """
-
-
- [page_title]
-
- [script]
-
-
-