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.

150 lines
6.3 KiB

10 years ago
  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # OpenERP, Open Source Management Solution
  5. # This module copyright (C) 2014 Therp BV (<http://therp.nl>).
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU Affero General Public License as
  9. # published by the Free Software Foundation, either version 3 of the
  10. # License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU Affero General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU Affero General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. #
  20. ##############################################################################
  21. import itertools
  22. from openerp.osv.orm import Model
  23. from openerp.osv import fields, expression
  24. from openerp.tools.safe_eval import safe_eval
  25. from openerp.tools.translate import _
  26. class IrFilters(Model):
  27. _inherit = 'ir.filters'
  28. def _is_frozen_get(self, cr, uid, ids, field_name, args, context=None):
  29. '''determine if this is fixed list of ids'''
  30. result = {}
  31. for this in self.browse(cr, uid, ids, context=context):
  32. domain = safe_eval(this.domain)
  33. result[this.id] = (len(domain) == 1 and
  34. expression.is_leaf(domain[0]) and
  35. domain[0][0] == 'id')
  36. return result
  37. def _domain_get(self, cr, uid, ids, field_name, args, context=None):
  38. '''combine our domain with all domains to union/complement,
  39. this works recursively'''
  40. def eval_n(domain):
  41. '''parse a domain and normalize it'''
  42. return expression.normalize_domain(
  43. safe_eval(domain) or [expression.FALSE_LEAF])
  44. result = {}
  45. for this in self.read(
  46. cr, uid, ids,
  47. ['domain_this', 'union_filter_ids', 'complement_filter_ids'],
  48. context=context):
  49. domain = eval_n(this['domain_this'])
  50. domain = expression.OR(
  51. [domain] +
  52. [eval_n(u['domain']) for u in self.read(
  53. cr, uid, this['union_filter_ids'], ['domain'],
  54. context=context)])
  55. for c in self.read(cr, uid, this['complement_filter_ids'],
  56. ['domain'], context=context):
  57. domain = expression.AND([
  58. domain,
  59. ['!'] + eval_n(c['domain'])])
  60. result[this['id']] = str(domain)
  61. return result
  62. def _domain_set(self, cr, uid, ids, field_name, field_value, args,
  63. context=None):
  64. self.write(cr, uid, ids, {'domain_this': field_value})
  65. _columns = {
  66. 'is_frozen': fields.function(
  67. _is_frozen_get, type='boolean', string='Frozen'),
  68. 'union_filter_ids': fields.many2many(
  69. 'ir.filters', 'ir_filters_union_rel', 'left_filter_id',
  70. 'right_filter_id', 'Add result of filters',
  71. domain=['|', ('active', '=', False), ('active', '=', True)]),
  72. 'complement_filter_ids': fields.many2many(
  73. 'ir.filters', 'ir_filters_complement_rel', 'left_filter_id',
  74. 'right_filter_id', 'Remove result of filters',
  75. domain=['|', ('active', '=', False), ('active', '=', True)]),
  76. 'active': fields.boolean('Active'),
  77. 'domain': fields.function(
  78. _domain_get, type='text', string='Domain',
  79. fnct_inv=_domain_set),
  80. 'domain_this': fields.text(
  81. 'This filter\'s own domain', oldname='domain'),
  82. }
  83. _defaults = {
  84. 'active': True,
  85. }
  86. def _evaluate(self, cr, uid, ids, context=None):
  87. assert len(ids) == 1
  88. this = self.browse(cr, uid, ids[0], context=context)
  89. return self.pool[this.model_id].search(
  90. cr, uid, safe_eval(this.domain), context=safe_eval(this.context))
  91. def button_save(self, cr, uid, ids, context=None):
  92. return {'type': 'ir.actions.act_window.close'}
  93. def button_freeze(self, cr, uid, ids, context=None):
  94. '''evaluate the filter and write a fixed [('ids', 'in', [])] domain'''
  95. for this in self.browse(cr, uid, ids, context=context):
  96. ids = this._evaluate()
  97. removed_filter_ids = [f.id for f in itertools.chain(
  98. this.union_filter_ids, this.complement_filter_ids)]
  99. this.write({
  100. 'domain': str([('id', 'in', ids)]),
  101. 'union_filter_ids': [(6, 0, [])],
  102. 'complement_filter_ids': [(6, 0, [])],
  103. })
  104. # if we removed inactive filters which are orphaned now, delete
  105. # them
  106. cr.execute('''delete from ir_filters
  107. where
  108. not active and id in %s
  109. and not exists (select right_filter_id
  110. from ir_filters_union_rel where left_filter_id=id)
  111. and not exists (select right_filter_id
  112. from ir_filters_complement_rel where
  113. left_filter_id=id)
  114. ''',
  115. (tuple(removed_filter_ids),))
  116. def button_test(self, cr, uid, ids, context=None):
  117. for this in self.browse(cr, uid, ids, context=None):
  118. return {
  119. 'type': 'ir.actions.act_window',
  120. 'name': _('Testing %s') % this.name,
  121. 'res_model': this.model_id,
  122. 'domain': this.domain,
  123. 'view_type': 'form',
  124. 'view_mode': 'tree',
  125. 'context': {
  126. 'default_filter_id': this.id,
  127. },
  128. }
  129. def _auto_init(self, cr, context=None):
  130. cr.execute(
  131. 'SELECT count(attname) FROM pg_attribute '
  132. 'WHERE attrelid = '
  133. '( SELECT oid FROM pg_class WHERE relname = %s) '
  134. 'AND attname = %s', (self._table, 'domain_this'))
  135. if not cr.fetchone()[0]:
  136. cr.execute(
  137. 'ALTER table %s RENAME domain TO domain_this' % self._table)
  138. return super(IrFilters, self)._auto_init(cr, context=context)