You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
5.5 KiB
143 lines
5.5 KiB
# -*- coding: utf-8 -*-
|
|
# © 2017 Therp BV <http://therp.nl>
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
from lxml import etree
|
|
from openerp import _, api, models, tools
|
|
|
|
|
|
class IrUiView(models.Model):
|
|
_inherit = 'ir.ui.view'
|
|
|
|
@api.multi
|
|
def custom_column(self, diff):
|
|
"""Apply a change for a custom view. Create a new custom view or
|
|
view override as necessary"""
|
|
self.ensure_one()
|
|
tree = etree.fromstring(self.read_combined(self.id)['arch'])
|
|
customized_view = self.env.ref(
|
|
self._custom_column_xmlid(diff), raise_if_not_found=False
|
|
) or self.browse([])
|
|
if diff['operation'] == 'add':
|
|
etree.SubElement(tree, 'field', {'name': diff['name']})
|
|
elif diff['operation'] == 'remove':
|
|
for element in tree:
|
|
if element.attrib['name'] == diff['name'] and\
|
|
element.tag == 'field':
|
|
tree.remove(element)
|
|
elif diff['operation'] == 'left':
|
|
for element in tree:
|
|
if element.attrib['name'] == diff['name'] and\
|
|
element.tag == 'field' and\
|
|
element.getprevious() is not None:
|
|
element.getprevious().addprevious(element)
|
|
break
|
|
elif diff['operation'] == 'right':
|
|
for element in tree:
|
|
if element.attrib['name'] == diff['name'] and\
|
|
element.tag == 'field' and\
|
|
element.getnext() is not None:
|
|
element.getnext().addnext(element)
|
|
break
|
|
elif diff['operation'] == 'reset':
|
|
customized_view.unlink()
|
|
return []
|
|
elif diff['operation'] == 'to_user':
|
|
diff['type'] = 'user'
|
|
customized_view = self.env.ref(
|
|
self._custom_column_xmlid(diff), raise_if_not_found=False
|
|
) or self.browse([])
|
|
elif diff['operation'] == 'to_all':
|
|
customized_view.unlink()
|
|
diff['type'] = 'all'
|
|
customized_view = self.env.ref(
|
|
self._custom_column_xmlid(diff), raise_if_not_found=False
|
|
) or self.browse([])
|
|
else:
|
|
raise NotImplementedError(
|
|
'Unknown operation %s' % diff['operation']
|
|
)
|
|
|
|
replacement = etree.Element('tree', {'position': 'replace'})
|
|
replacement.append(tree)
|
|
arch = etree.tostring(replacement, pretty_print=True)
|
|
if customized_view:
|
|
customized_view.write({'arch': arch})
|
|
else:
|
|
customized_view = self._custom_column_create_view(diff, arch)
|
|
return customized_view.id
|
|
|
|
@api.multi
|
|
def custom_column_desc(self):
|
|
"""Return metadata necessary for UI"""
|
|
self.ensure_one()
|
|
return {
|
|
'fields': self.env[self.model].fields_get(),
|
|
'type': bool(self.env.ref(
|
|
self._custom_column_xmlid({'type': 'user'}),
|
|
raise_if_not_found=False
|
|
)) and 'user' or bool(self.env.ref(
|
|
self._custom_column_xmlid({'type': 'all'}),
|
|
raise_if_not_found=False
|
|
)) and 'all' or 'user',
|
|
}
|
|
|
|
@api.multi
|
|
def _custom_column_xmlid(self, diff, qualify=True):
|
|
"""Return an xmlid for the view of a type of customization"""
|
|
self.ensure_one()
|
|
customization_type = diff['type']
|
|
return '%scustom_view_%d_%s%s' % (
|
|
qualify and 'web_listview_custom_column.' or '',
|
|
self.id,
|
|
customization_type,
|
|
'_%d' % self.env.uid if customization_type == 'user' else '',
|
|
)
|
|
|
|
@api.multi
|
|
def _custom_column_create_view(self, diff, arch):
|
|
"""Actually create a view for customization"""
|
|
self.ensure_one()
|
|
values = self.copy_data(default={
|
|
'name': _('%s customized') % self.name,
|
|
'arch': arch,
|
|
'inherit_id': self.id,
|
|
'mode': 'extension',
|
|
'priority': 10000 + (diff['type'] == 'user' and 1 or 0),
|
|
'user_ids': [(4, self.env.uid)] if diff['type'] == 'user' else [],
|
|
})[0]
|
|
result = self.create(values)
|
|
self.env['ir.model.data'].create({
|
|
'name': self._custom_column_xmlid(diff, qualify=False),
|
|
'module': 'web_listview_custom_column',
|
|
'model': self._name,
|
|
'res_id': result.id,
|
|
'noupdate': True,
|
|
})
|
|
return result
|
|
|
|
@api.multi
|
|
def _check_xml(self):
|
|
"""Don't validate our custom views, this will break in init mode"""
|
|
if self.env.registry._init:
|
|
self = self.filtered(
|
|
lambda x: not x.xml_id or not x.xml_id.startswith(
|
|
'web_listview_custom_column.custom_view_'
|
|
)
|
|
)
|
|
return super(IrUiView, self)._check_xml()
|
|
|
|
_constraints = [(_check_xml, 'Invalid view definition', ['arch'])]
|
|
|
|
@api.model
|
|
def get_inheriting_views_arch(self, view_id, model):
|
|
"""Don't apply our view inheritance in init mode for the same reason"""
|
|
return [
|
|
(arch, view_id_)
|
|
for arch, view_id_ in
|
|
super(IrUiView, self).get_inheriting_views_arch(view_id, model)
|
|
if (not self.env.registry._init or tools.config['test_enable']) or
|
|
not self.sudo().browse(view_id_).xml_id or
|
|
not self.sudo().browse(view_id_).xml_id.startswith(
|
|
'web_listview_custom_column.custom_view_'
|
|
)
|
|
]
|