diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index ab024e18197..39f3067720f 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -158,22 +158,25 @@ class Website(openerp.addons.web.controllers.main.Home): @http.route('/website/theme_change', type='http', auth="user", website=True) def theme_change(self, theme_id=False, **kwargs): imd = request.registry['ir.model.data'] - view = request.registry['ir.ui.view'] + Views = request.registry['ir.ui.view'] - view_model, view_option_id = imd.get_object_reference( + _, theme_template_id = imd.get_object_reference( request.cr, request.uid, 'website', 'theme') - views = view.search( - request.cr, request.uid, [('inherit_id', '=', view_option_id)], - context=request.context) - view.write(request.cr, request.uid, views, {'inherit_id': False}, - context=request.context) + views = Views.search(request.cr, request.uid, [ + ('inherit_id', '=', theme_template_id), + ('application', '=', 'enabled'), + ], context=request.context) + Views.write(request.cr, request.uid, views, { + 'application': 'disabled', + }, context=request.context) if theme_id: module, xml_id = theme_id.split('.') - view_model, view_id = imd.get_object_reference( + _, view_id = imd.get_object_reference( request.cr, request.uid, module, xml_id) - view.write(request.cr, request.uid, [view_id], - {'inherit_id': view_option_id}, context=request.context) + Views.write(request.cr, request.uid, [view_id], { + 'application': 'enabled' + }, context=request.context) return request.render('website.themes', {'theme_changed': True}) @@ -197,54 +200,45 @@ class Website(openerp.addons.web.controllers.main.Home): module_obj.button_immediate_upgrade(request.cr, request.uid, module_ids, context=request.context) return request.redirect(redirect) - @http.route('/website/customize_template_toggle', type='json', auth='user', website=True) - def customize_template_set(self, view_id): - view_obj = request.registry.get("ir.ui.view") - view = view_obj.browse(request.cr, request.uid, int(view_id), - context=request.context) - if view.inherit_id: - value = False - else: - value = view.inherit_option_id and view.inherit_option_id.id or False - view_obj.write(request.cr, request.uid, [view_id], { - 'inherit_id': value - }, context=request.context) - return True - @http.route('/website/customize_template_get', type='json', auth='user', website=True) - def customize_template_get(self, xml_id, optional=True): + def customize_template_get(self, xml_id, full=False): + """ Lists the templates customizing ``xml_id``. By default, only + returns optional templates (which can be toggled on and off), if + ``full=True`` returns all templates customizing ``xml_id`` + """ imd = request.registry['ir.model.data'] view_model, view_theme_id = imd.get_object_reference( request.cr, request.uid, 'website', 'theme') - user = request.registry['res.users'].browse(request.cr, request.uid, request.uid, request.context) - group_ids = [g.id for g in user.groups_id] + user = request.registry['res.users']\ + .browse(request.cr, request.uid, request.uid, request.context) + user_groups = set(user.groups_id) - view = request.registry.get("ir.ui.view") - views = view._views_get(request.cr, request.uid, xml_id, context=request.context) - done = {} + views = request.registry["ir.ui.view"]\ + ._views_get(request.cr, request.uid, xml_id, context=request.context) + done = set() result = [] for v in views: - if v.groups_id and [g for g in v.groups_id if g.id not in group_ids]: + if not user_groups.issuperset(v.groups_id): continue - if v.inherit_option_id and v.inherit_option_id.id != view_theme_id or not optional: - if v.inherit_option_id.id not in done: + if full or (v.application != 'always' and v.inherit_id.id != view_theme_id): + if v.inherit_id not in done: result.append({ - 'name': v.inherit_option_id.name, + 'name': v.inherit_id.name, 'id': v.id, 'xml_id': v.xml_id, 'inherit_id': v.inherit_id.id, 'header': True, 'active': False }) - done[v.inherit_option_id.id] = True + done.add(v.inherit_id) result.append({ 'name': v.name, 'id': v.id, 'xml_id': v.xml_id, 'inherit_id': v.inherit_id.id, 'header': False, - 'active': (v.inherit_id.id == v.inherit_option_id.id) or (not optional and v.inherit_id.id) + 'active': v.application in ('always', 'enabled'), }) return result diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py index 9d89665c56f..398bbb6a87b 100644 --- a/addons/website/models/ir_ui_view.py +++ b/addons/website/models/ir_ui_view.py @@ -13,8 +13,6 @@ from openerp.osv import osv, fields class view(osv.osv): _inherit = "ir.ui.view" _columns = { - 'inherit_option_id': fields.many2one('ir.ui.view','Optional Inheritancy'), - 'inherited_option_ids': fields.one2many('ir.ui.view','inherit_option_id','Optional Inheritancies'), 'page': fields.boolean("Whether this view is a web page template (complete)"), 'website_meta_title': fields.char("Website meta title", size=70, translate=True), 'website_meta_description': fields.text("Website meta description", size=160, translate=True), @@ -24,25 +22,30 @@ class view(osv.osv): 'page': False, } + + def _view_obj(self, cr, uid, view_id, context=None): + if isinstance(view_id, basestring): + return self.pool['ir.model.data'].xmlid_to_object( + cr, uid, view_id, raise_if_not_found=True, context=context + ) + elif isinstance(view_id, (int, long)): + return self.browse(cr, uid, view_id, context=context) + + # assume it's already a view object (WTF?) + return view_id + # Returns all views (called and inherited) related to a view # Used by translation mechanism, SEO and optional templates - def _views_get(self, cr, uid, view, options=True, context=None, root=True, stack_result=None): - if not context: - context = {} - if not stack_result: - stack_result = [] - - def view_obj(view): - if isinstance(view, basestring): - mod_obj = self.pool.get("ir.model.data") - m, n = view.split('.') - view = mod_obj.get_object(cr, uid, m, n, context=context) - elif isinstance(view, (int, long)): - view = self.pool.get("ir.ui.view").browse(cr, uid, view, context=context) - return view + def _views_get(self, cr, uid, view_id, options=True, context=None, root=True): + """ For a given view ``view_id``, should return: + * the view itself + * all views inheriting from it, enabled or not + - but not the optional children of a non-enabled child + * all views called from it (via t-call) + """ try: - view = view_obj(view) + view = self._view_obj(cr, uid, view_id, context=context) except ValueError: # Shall we log that ? return [] @@ -55,19 +58,25 @@ class view(osv.osv): node = etree.fromstring(view.arch) for child in node.xpath("//t[@t-call]"): try: - call_view = view_obj(child.get('t-call')) + called_view = self._view_obj(cr, uid, child.get('t-call'), context=context) except ValueError: continue - if call_view not in result: - result += self._views_get(cr, uid, call_view, options=options, context=context, stack_result=result) + if called_view not in result: + result += self._views_get(cr, uid, called_view, options=options, context=context) - todo = view.inherit_children_ids - if options: - todo += filter(lambda x: not x.inherit_id, view.inherited_option_ids) - # Keep options in a determinitic order whatever their enabled disabled status - todo.sort(lambda x,y:cmp(x.id,y.id)) - for child_view in todo: - for r in self._views_get(cr, uid, child_view, options=bool(child_view.inherit_id), context=context, root=False, stack_result=result): + extensions = view.inherit_children_ids + if not options: + # only active children + extensions = (v for v in view.inherit_children_ids + if v.application in ('always', 'enabled')) + + # Keep options in a deterministic order regardless of their applicability + for extension in sorted(extensions, key=lambda v: v.id): + for r in self._views_get( + cr, uid, extension, + # only return optional grandchildren if this child is enabled + options=extension.application in ('always', 'enabled'), + context=context, root=False): if r not in result: result.append(r) return result diff --git a/addons/website/static/src/js/website.ace.js b/addons/website/static/src/js/website.ace.js index a8af74bb52d..27e5cd60e62 100644 --- a/addons/website/static/src/js/website.ace.js +++ b/addons/website/static/src/js/website.ace.js @@ -97,7 +97,7 @@ var viewId = $(document.documentElement).data('view-xmlid'); openerp.jsonRpc('/website/customize_template_get', 'call', { 'xml_id': viewId, - 'optional': false, + 'full': true, }).then(function (views) { self.loadViews.call(self, views); self.open.call(self); diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 595df04a088..fcb957cafda 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -470,8 +470,14 @@ }); menu.on('click', 'a[data-action!=ace]', function (event) { var view_id = $(event.currentTarget).data('view-id'); - openerp.jsonRpc('/website/customize_template_toggle', 'call', { - 'view_id': view_id + return openerp.jsonRpc('/web/dataset/call_kw', 'call', { + model: 'ir.ui.view', + method: 'toggle', + args: [], + kwargs: { + ids: [parseInt(view_id, 10)], + context: website.get_context() + } }).then( function() { window.location.reload(); }); diff --git a/addons/website/views/themes.xml b/addons/website/views/themes.xml index 82f5105adcd..a2408133207 100644 --- a/addons/website/views/themes.xml +++ b/addons/website/views/themes.xml @@ -203,82 +203,82 @@ All Default Themes --> -