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.

142 lines
5.7 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2015-2018 Therp BV <https://therp.nl>
  3. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
  4. import operator
  5. from openerp import _, models, api, fields
  6. from openerp.tools.safe_eval import safe_eval
  7. from openerp.exceptions import Warning as UserError
  8. from openerp.osv import expression
  9. class IrUiMenu(models.Model):
  10. _inherit = 'ir.ui.menu'
  11. needaction = fields.Boolean(
  12. help='Set to False to disable needaction for specific menu items',
  13. default=True)
  14. needaction_domain = fields.Text(
  15. help='If your menu item needs a different domain, set it here. It '
  16. 'will override the model\'s needaction domain completely.')
  17. @api.multi
  18. def get_navbar_needaction_data(self):
  19. """Return aggregated needaction data for all children of self"""
  20. result = {}
  21. for this in self:
  22. count_per_model = {}
  23. action_menu = self.env['ir.ui.menu'].browse([])
  24. if not this.needaction:
  25. continue
  26. custom_needaction = this._get_navbar_needaction_data_custom()
  27. if custom_needaction:
  28. result[this.id] = custom_needaction
  29. continue
  30. for menu_id, needaction in self.search(
  31. [('id', 'child_of', this.ids)])._filter_visible_menus()\
  32. .get_needaction_data().iteritems():
  33. if needaction.get('needaction_from_children'):
  34. continue
  35. if needaction['needaction_enabled']:
  36. menu = self.env['ir.ui.menu'].browse(menu_id)
  37. model = menu._get_needaction_model()
  38. count_per_model[model] = max(
  39. count_per_model.get(model),
  40. needaction['needaction_counter']
  41. )
  42. if needaction['needaction_counter'] and not action_menu:
  43. action_menu = menu
  44. result[this.id] = {
  45. 'count': sum(count_per_model.itervalues()),
  46. }
  47. if action_menu:
  48. result[this.id].update({
  49. 'action_id': action_menu.action and
  50. action_menu.action.id or None,
  51. 'action_domain': action_menu._eval_needaction_domain(),
  52. })
  53. return result
  54. @api.multi
  55. def _get_navbar_needaction_data_custom(self):
  56. """Return nonstandard needaction data for a menu item"""
  57. self.ensure_one()
  58. if self == self.env.ref('mail.mail_channel_menu_root_chat'):
  59. return {
  60. 'count': self.env['mail.message']._needaction_count(),
  61. 'action_id':
  62. self.env.ref('mail.mail_channel_action_client_chat').id,
  63. }
  64. @api.multi
  65. def get_needaction_data(self):
  66. result = super(IrUiMenu, self).get_needaction_data()
  67. for this in self.sorted(operator.itemgetter('parent_left'), True):
  68. data = result[this.id]
  69. if data['needaction_enabled'] or this.needaction and\
  70. this.needaction_domain:
  71. if not this.needaction:
  72. data['needaction_enabled'] = False
  73. data['needaction_counter'] = 0
  74. continue
  75. if this.needaction_domain and\
  76. this._get_needaction_model() is not None:
  77. data['needaction_enabled'] = True
  78. data['needaction_counter'] = this._get_needaction_model()\
  79. .search_count(this._eval_needaction_domain())
  80. if not data['needaction_enabled'] and this.needaction and\
  81. this.child_id and this.parent_id and this.parent_id.parent_id:
  82. # if the user didn't turn it off, show counters for submenus
  83. # but only from the 3rd level (the first that is closed by
  84. # default)
  85. for child in this.child_id:
  86. data['needaction_counter'] += result.get(child.id, {}).get(
  87. 'needaction_counter', 0)
  88. data['needaction_enabled'] = bool(data['needaction_counter'])
  89. data['needaction_from_children'] = True
  90. return result
  91. @api.multi
  92. def _eval_needaction_domain(self):
  93. self.ensure_one()
  94. eval_context = {
  95. 'uid': self.env.user.id,
  96. 'user': self.env.user,
  97. }
  98. if self.needaction_domain:
  99. return safe_eval(self.needaction_domain, locals_dict=eval_context)
  100. model = self._get_needaction_model()
  101. if model is None or not hasattr(model, '_needaction_domain_get'):
  102. return []
  103. return expression.AND([
  104. safe_eval(
  105. 'domain' in self.action._fields and self.action.domain or '[]',
  106. locals_dict=eval_context),
  107. model._needaction_domain_get(),
  108. ])
  109. @api.multi
  110. def _get_needaction_model(self):
  111. if not self.action:
  112. return None
  113. model = None
  114. if 'res_model' in self.action._fields:
  115. model = self.action.res_model
  116. elif 'model_id' in self.action._fields:
  117. model = self.action.model_id.model
  118. if model in self.env.registry:
  119. return self.env[model]
  120. return None
  121. @api.constrains('needaction_domain')
  122. @api.multi
  123. def _check_needaction_domain(self):
  124. for this in self:
  125. try:
  126. expression.AND([
  127. this._eval_needaction_domain(),
  128. expression.TRUE_DOMAIN,
  129. ])
  130. except Exception as ex:
  131. raise UserError(
  132. _('Cannot evaluate %s to a search domain:\n%s') %
  133. (self.needaction_domain, ex))