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.

139 lines
5.7 KiB

  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # This module copyright (C) 2015 Therp BV (<http://therp.nl>).
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU Affero General Public License as
  8. # published by the Free Software Foundation, either version 3 of the
  9. # License, or (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU Affero General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU Affero General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. ##############################################################################
  20. import operator
  21. from openerp import _, models, api, fields
  22. from openerp.tools.safe_eval import safe_eval
  23. from openerp.exceptions import Warning as UserError
  24. from openerp.osv import expression
  25. class IrUiMenu(models.Model):
  26. _inherit = 'ir.ui.menu'
  27. needaction = fields.Boolean(
  28. help='Set to False to disable needaction for specific menu items',
  29. default=True)
  30. needaction_domain = fields.Text(
  31. help='If your menu item needs a different domain, set it here. It '
  32. 'will override the model\'s needaction domain completely.')
  33. @api.multi
  34. def get_navbar_needaction_data(self):
  35. result = {}
  36. for this in self:
  37. count_per_model = {}
  38. action_menu = self.env['ir.ui.menu'].browse([])
  39. if not this.needaction:
  40. continue
  41. for menu_id, needaction in self.search(
  42. [('id', 'child_of', this.ids)])._filter_visible_menus()\
  43. .get_needaction_data().iteritems():
  44. if needaction['needaction_enabled']:
  45. menu = self.env['ir.ui.menu'].browse(menu_id)
  46. model = menu._get_needaction_model()
  47. count_per_model[model] = max(
  48. count_per_model.get(model),
  49. needaction['needaction_counter']
  50. )
  51. if needaction['needaction_counter'] and not action_menu:
  52. action_menu = menu
  53. result[this.id] = {
  54. 'count': sum(count_per_model.itervalues()),
  55. }
  56. if action_menu:
  57. result[this.id].update({
  58. 'action_id': action_menu.action and
  59. action_menu.action.id or None,
  60. 'action_domain': action_menu._eval_needaction_domain(),
  61. })
  62. return result
  63. @api.multi
  64. def get_needaction_data(self):
  65. result = super(IrUiMenu, self).get_needaction_data()
  66. for this in self.sorted(operator.itemgetter('parent_left'), True):
  67. data = result[this.id]
  68. if data['needaction_enabled'] or this.needaction and\
  69. this.needaction_domain:
  70. if not this.needaction:
  71. data['needaction_enabled'] = False
  72. data['needaction_counter'] = 0
  73. continue
  74. if this.needaction_domain and\
  75. this._get_needaction_model() is not None:
  76. data['needaction_enabled'] = True
  77. data['needaction_counter'] = this._get_needaction_model()\
  78. .search_count(this._eval_needaction_domain())
  79. if not data['needaction_enabled'] and this.needaction and\
  80. this.child_id and this.parent_id and this.parent_id.parent_id:
  81. # if the user didn't turn it off, show counters for submenus
  82. # but only from the 3rd level (the first that is closed by
  83. # default)
  84. for child in this.child_id:
  85. data['needaction_counter'] += result.get(child.id, {}).get(
  86. 'needaction_counter', 0)
  87. data['needaction_enabled'] = bool(data['needaction_counter'])
  88. return result
  89. @api.multi
  90. def _eval_needaction_domain(self):
  91. self.ensure_one()
  92. eval_context = {
  93. 'uid': self.env.user.id,
  94. 'user': self.env.user,
  95. }
  96. if self.needaction_domain:
  97. return safe_eval(self.needaction_domain, locals_dict=eval_context)
  98. model = self._get_needaction_model()
  99. if model is None or not hasattr(model, '_needaction_domain_get'):
  100. return []
  101. return expression.AND([
  102. safe_eval(
  103. 'domain' in self.action._fields and self.action.domain or '[]',
  104. locals_dict=eval_context),
  105. model._needaction_domain_get(),
  106. ])
  107. @api.multi
  108. def _get_needaction_model(self):
  109. if not self.action:
  110. return None
  111. model = None
  112. if 'res_model' in self.action._fields:
  113. model = self.action.res_model
  114. elif 'model_id' in self.action._fields:
  115. model = self.action.model_id.model
  116. if model in self.env.registry:
  117. return self.env[model]
  118. return None
  119. @api.constrains('needaction_domain')
  120. @api.multi
  121. def _check_needaction_domain(self):
  122. for this in self:
  123. try:
  124. expression.AND([
  125. this._eval_needaction_domain(),
  126. expression.TRUE_DOMAIN,
  127. ])
  128. except Exception as ex:
  129. raise UserError(
  130. _('Cannot evaluate %s to a search domain:\n%s') %
  131. (self.needaction_domain, ex))