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.

161 lines
5.3 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2016 Therp BV <http://therp.nl>
  3. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
  4. from lxml import etree
  5. from openerp import api, models, tools
  6. class UnquoteObject(str):
  7. def __getattr__(self, name):
  8. return UnquoteObject('%s.%s' % (self, name))
  9. def __repr__(self):
  10. return self
  11. def __call__(self, *args, **kwargs):
  12. return UnquoteObject(
  13. '%s(%s)' % (
  14. self,
  15. ','.join(
  16. [
  17. UnquoteObject(
  18. a if not isinstance(a, basestring)
  19. else "'%s'" % a
  20. )
  21. for a in args
  22. ] +
  23. [
  24. '%s=%s' % (UnquoteObject(k), v)
  25. for (k, v) in kwargs.iteritems()
  26. ]
  27. )
  28. )
  29. )
  30. class UnquoteEvalObjectContext(tools.misc.UnquoteEvalContext):
  31. def __missing__(self, key):
  32. return UnquoteObject(key)
  33. class IrUiView(models.Model):
  34. _inherit = 'ir.ui.view'
  35. @api.model
  36. def apply_inheritance_specs(self, source, specs_tree, inherit_id):
  37. for specs, handled_by in self._iter_inheritance_specs(specs_tree):
  38. source = handled_by(source, specs, inherit_id)
  39. return source
  40. @api.model
  41. def _iter_inheritance_specs(self, spec):
  42. if spec.tag == 'data':
  43. for child in spec:
  44. for node, handler in self._iter_inheritance_specs(child):
  45. yield node, handler
  46. return
  47. if spec.get('position') == 'attributes':
  48. for child in spec:
  49. node = etree.Element(spec.tag, **spec.attrib)
  50. node.insert(0, child)
  51. yield node, self._get_inheritance_handler_attributes(
  52. child
  53. )
  54. return
  55. yield spec, self._get_inheritance_handler(spec)
  56. @api.model
  57. def _get_inheritance_handler(self, node):
  58. handler = super(IrUiView, self).apply_inheritance_specs
  59. if hasattr(
  60. self, 'inheritance_handler_%s' % node.tag
  61. ):
  62. handler = getattr(
  63. self,
  64. 'inheritance_handler_%s' % node.tag
  65. )
  66. return handler
  67. @api.model
  68. def _get_inheritance_handler_attributes(self, node):
  69. handler = super(IrUiView, self).apply_inheritance_specs
  70. if hasattr(
  71. self, 'inheritance_handler_attributes_%s' % node.get('operation')
  72. ):
  73. handler = getattr(
  74. self,
  75. 'inheritance_handler_attributes_%s' % node.get('operation')
  76. )
  77. return handler
  78. @api.model
  79. def inheritance_handler_attributes_python_dict(
  80. self, source, specs, inherit_id
  81. ):
  82. """Implement
  83. <$node position="attributes">
  84. <attribute name="$attribute" operation="python_dict" key="$key">
  85. $keyvalue
  86. </attribute>
  87. </$node>"""
  88. node = self.locate_node(source, specs)
  89. for attribute_node in specs:
  90. python_dict = tools.safe_eval(
  91. node.get(attribute_node.get('name')) or '{}',
  92. UnquoteEvalObjectContext()
  93. )
  94. python_dict[attribute_node.get('key')] = UnquoteObject(
  95. attribute_node.text
  96. )
  97. node.attrib[attribute_node.get('name')] = str(python_dict)
  98. return source
  99. @api.model
  100. def inheritance_handler_xpath(self, source, specs, inherit_id):
  101. if not specs.get('position') == 'move':
  102. return super(IrUiView, self).apply_inheritance_specs(
  103. source, specs, inherit_id
  104. )
  105. node = self.locate_node(source, specs)
  106. target_node = self.locate_node(
  107. source, etree.Element(specs.tag, expr=specs.get('target'))
  108. )
  109. target_node.append(node)
  110. return source
  111. @api.model
  112. def inheritance_handler_attributes_list_add(
  113. self, source, specs, inherit_id
  114. ):
  115. """Implement
  116. <$node position="attributes">
  117. <attribute name="$attribute" operation="list_add">
  118. $new_value
  119. </attribute>
  120. </$node>"""
  121. node = self.locate_node(source, specs)
  122. for attribute_node in specs:
  123. attribute_name = attribute_node.get('name')
  124. old_value = node.get(attribute_name) or ''
  125. new_value = old_value + ',' + attribute_node.text
  126. node.attrib[attribute_name] = new_value
  127. return source
  128. @api.model
  129. def inheritance_handler_attributes_list_remove(
  130. self, source, specs, inherit_id
  131. ):
  132. """Implement
  133. <$node position="attributes">
  134. <attribute name="$attribute" operation="list_remove">
  135. $value_to_remove
  136. </attribute>
  137. </$node>"""
  138. node = self.locate_node(source, specs)
  139. for attribute_node in specs:
  140. attribute_name = attribute_node.get('name')
  141. old_values = (node.get(attribute_name) or '').split(',')
  142. remove_values = attribute_node.text.split(',')
  143. new_values = [x for x in old_values if x not in remove_values]
  144. node.attrib[attribute_name] = ','.join(filter(None, new_values))
  145. return source