Holger Brunn
11 years ago
11 changed files with 666 additions and 0 deletions
-
22advanced_filters/__init__.py
-
78advanced_filters/__openerp__.py
-
21advanced_filters/model/__init__.py
-
149advanced_filters/model/ir_filters.py
-
14advanced_filters/static/src/css/advanced_filters.css
-
BINadvanced_filters/static/src/img/icon.png
-
209advanced_filters/static/src/js/advanced_filters.js
-
44advanced_filters/view/ir_filters.xml
-
21advanced_filters/wizard/__init__.py
-
87advanced_filters/wizard/ir_filters_combine_with_existing.py
-
21advanced_filters/wizard/ir_filters_combine_with_existing.xml
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2014 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from . import model |
|||
from . import wizard |
@ -0,0 +1,78 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2014 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
{ |
|||
"name": "Advanced filters", |
|||
"version": "1.0", |
|||
"author": "Therp BV", |
|||
"license": "AGPL-3", |
|||
"complexity": "normal", |
|||
"description": """ |
|||
Introduction |
|||
------------ |
|||
|
|||
This addon allows users to apply set operations on filters: Remove or add |
|||
certain ids from/to a selection, but also to remove or add another filter's |
|||
outcome from/to a filter. This can be stacked, so the filter domain can be |
|||
arbitrarily complicated. |
|||
|
|||
The math is hidden from the user as far as possible, in the hope it's still |
|||
user friendly. |
|||
|
|||
Usage |
|||
----- |
|||
|
|||
After this addon is installed, every list view shows a new menu 'Advanced |
|||
filters'. Here the set operations can be applied as necessary. |
|||
|
|||
Caution |
|||
------- |
|||
|
|||
Deinstalling this module will leave you with filters with empty domains. Use |
|||
this query before uninstalling to avoid that: |
|||
|
|||
``alter table ir_filters rename domain_this to domain`` |
|||
""", |
|||
"category": "Tools", |
|||
"depends": [ |
|||
'base', |
|||
'web', |
|||
], |
|||
"data": [ |
|||
"wizard/ir_filters_combine_with_existing.xml", |
|||
"view/ir_filters.xml", |
|||
], |
|||
"js": [ |
|||
'static/src/js/advanced_filters.js', |
|||
], |
|||
"css": [ |
|||
'static/src/css/advanced_filters.css', |
|||
], |
|||
"qweb": [ |
|||
], |
|||
"test": [ |
|||
], |
|||
"auto_install": False, |
|||
"installable": True, |
|||
"application": False, |
|||
"external_dependencies": { |
|||
'python': [], |
|||
}, |
|||
} |
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2014 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from . import ir_filters |
@ -0,0 +1,149 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2014 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import itertools |
|||
from openerp.osv.orm import Model |
|||
from openerp.osv import fields, expression |
|||
from openerp.tools.safe_eval import const_eval |
|||
from openerp.tools.translate import _ |
|||
|
|||
|
|||
class IrFilters(Model): |
|||
_inherit = 'ir.filters' |
|||
|
|||
def _is_frozen_get(self, cr, uid, ids, field_name, args, context=None): |
|||
'''determine if this is fixed list of ids''' |
|||
result = {} |
|||
for this in self.browse(cr, uid, ids, context=context): |
|||
domain = const_eval(this.domain) |
|||
result[this.id] = (len(domain) == 1 and |
|||
expression.is_leaf(domain[0]) and |
|||
domain[0][0] == 'id') |
|||
return result |
|||
|
|||
def _domain_get(self, cr, uid, ids, field_name, args, context=None): |
|||
'''combine our domain with all domains to union/complement, |
|||
this works recursively''' |
|||
def eval_n(domain): |
|||
'''parse a domain and normalize it''' |
|||
return expression.normalize_domain( |
|||
const_eval(domain) or [expression.FALSE_LEAF]) |
|||
result = {} |
|||
for this in self.read( |
|||
cr, uid, ids, |
|||
['domain_this', 'union_filter_ids', 'complement_filter_ids'], |
|||
context=context): |
|||
domain = eval_n(this['domain_this']) |
|||
domain = expression.OR( |
|||
[domain] + |
|||
[eval_n(u['domain']) for u in self.read( |
|||
cr, uid, this['union_filter_ids'], ['domain'], |
|||
context=context)]) |
|||
for c in self.read(cr, uid, this['complement_filter_ids'], |
|||
['domain'], context=context): |
|||
domain = expression.AND([ |
|||
domain, |
|||
['!'] + eval_n(c['domain'])]) |
|||
result[this['id']] = str(domain) |
|||
return result |
|||
|
|||
def _domain_set(self, cr, uid, ids, field_name, field_value, args, |
|||
context=None): |
|||
self.write(cr, uid, ids, {'domain_this': field_value}) |
|||
|
|||
_columns = { |
|||
'is_frozen': fields.function( |
|||
_is_frozen_get, type='boolean', string='Frozen'), |
|||
'union_filter_ids': fields.many2many( |
|||
'ir.filters', 'ir_filters_union_rel', 'left_filter_id', |
|||
'right_filter_id', 'Add result of filters', |
|||
domain=['|', ('active', '=', False), ('active', '=', True)]), |
|||
'complement_filter_ids': fields.many2many( |
|||
'ir.filters', 'ir_filters_complement_rel', 'left_filter_id', |
|||
'right_filter_id', 'Remove result of filters', |
|||
domain=['|', ('active', '=', False), ('active', '=', True)]), |
|||
'active': fields.boolean('Active'), |
|||
'domain': fields.function( |
|||
_domain_get, type='text', string='Domain', |
|||
fnct_inv=_domain_set), |
|||
'domain_this': fields.text( |
|||
'This filter\'s own domain', oldname='domain'), |
|||
} |
|||
|
|||
_defaults = { |
|||
'active': True, |
|||
} |
|||
|
|||
def _evaluate(self, cr, uid, ids, context=None): |
|||
assert len(ids) == 1 |
|||
this = self.browse(cr, uid, ids[0], context=context) |
|||
return self.pool[this.model_id].search( |
|||
cr, uid, const_eval(this.domain), context=const_eval(this.context)) |
|||
|
|||
def button_save(self, cr, uid, ids, context=None): |
|||
return {'type': 'ir.actions.act_window.close'} |
|||
|
|||
def button_freeze(self, cr, uid, ids, context=None): |
|||
'''evaluate the filter and write a fixed [('ids', 'in', [])] domain''' |
|||
for this in self.browse(cr, uid, ids, context=context): |
|||
ids = this._evaluate() |
|||
removed_filter_ids = [f.id for f in itertools.chain( |
|||
this.union_filter_ids, this.complement_filter_ids)] |
|||
this.write({ |
|||
'domain': str([('id', 'in', ids)]), |
|||
'union_filter_ids': [(6, 0, [])], |
|||
'complement_filter_ids': [(6, 0, [])], |
|||
}) |
|||
#if we removed inactive filters which are orphaned now, delete them |
|||
cr.execute('''delete from ir_filters |
|||
where |
|||
not active and id in %s |
|||
and not exists (select right_filter_id |
|||
from ir_filters_union_rel where left_filter_id=id) |
|||
and not exists (select right_filter_id |
|||
from ir_filters_complement_rel where |
|||
left_filter_id=id) |
|||
''', |
|||
(tuple(removed_filter_ids),)) |
|||
|
|||
def button_test(self, cr, uid, ids, context=None): |
|||
for this in self.browse(cr, uid, ids, context=None): |
|||
return { |
|||
'type': 'ir.actions.act_window', |
|||
'name': _('Testing %s') % this.name, |
|||
'res_model': this.model_id, |
|||
'domain': this.domain, |
|||
'view_type': 'form', |
|||
'view_mode': 'tree', |
|||
'context': { |
|||
'default_filter_id': this.id, |
|||
}, |
|||
} |
|||
|
|||
def _auto_init(self, cr, context=None): |
|||
cr.execute( |
|||
'SELECT count(attname) FROM pg_attribute ' |
|||
'WHERE attrelid = ' |
|||
'( SELECT oid FROM pg_class WHERE relname = %s) ' |
|||
'AND attname = %s', (self._table, 'domain_this')) |
|||
if not cr.fetchone()[0]: |
|||
cr.execute( |
|||
'ALTER table %s RENAME domain TO domain_this' % self._table) |
|||
return super(IrFilters, self)._auto_init(cr, context=context) |
@ -0,0 +1,14 @@ |
|||
li.oe_advanced_filters_header |
|||
{ |
|||
font-weight: bold; |
|||
} |
|||
.openerp .oe_dropdown_menu > li.oe_advanced_filters_header:hover |
|||
{ |
|||
background-color: inherit; |
|||
background-image: inherit; |
|||
box-shadow: none; |
|||
} |
|||
.openerp .oe_dropdown_menu > li.oe_advanced_filters_header a:hover |
|||
{ |
|||
cursor: default !important; |
|||
} |
After Width: 128 | Height: 128 | Size: 16 KiB |
@ -0,0 +1,209 @@ |
|||
//-*- coding: utf-8 -*-
|
|||
//############################################################################
|
|||
//
|
|||
// OpenERP, Open Source Management Solution
|
|||
// This module copyright (C) 2014 Therp BV (<http://therp.nl>).
|
|||
//
|
|||
// This program is free software: you can redistribute it and/or modify
|
|||
// it under the terms of the GNU Affero General Public License as
|
|||
// published by the Free Software Foundation, either version 3 of the
|
|||
// License, or (at your option) any later version.
|
|||
//
|
|||
// This program is distributed in the hope that it will be useful,
|
|||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||
// GNU Affero General Public License for more details.
|
|||
//
|
|||
// You should have received a copy of the GNU Affero General Public License
|
|||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
//
|
|||
//############################################################################
|
|||
|
|||
openerp.advanced_filters = function(instance) |
|||
{ |
|||
var _t = instance.web._t; |
|||
|
|||
instance.web.Sidebar.include({ |
|||
init: function() |
|||
{ |
|||
var result = this._super.apply(this, arguments); |
|||
this.sections.push({ |
|||
'name': 'advanced_filters', |
|||
'label': _t('Advanced filters'), |
|||
}); |
|||
this.items.advanced_filters = []; |
|||
return result; |
|||
}, |
|||
}); |
|||
instance.web.ListView.include({ |
|||
do_select: function (ids, records) |
|||
{ |
|||
var result = this._super(this, arguments); |
|||
if(this.sidebar) |
|||
{ |
|||
this.sidebar.$el.show(); |
|||
this.sidebar.$el.children().children().each(function(i, e) |
|||
{ |
|||
$e = jQuery(e) |
|||
if($e.find('li.oe_advanced_filters_header').length) |
|||
{ |
|||
$e.find('a[data-index="0"],a[data-index="1"],' + |
|||
'a[data-index="2"],a[data-index="3"]') |
|||
.parent().toggle(ids.length); |
|||
} |
|||
else |
|||
{ |
|||
$e.toggle(ids.length); |
|||
} |
|||
}); |
|||
} |
|||
return result; |
|||
}, |
|||
load_list: function(data) |
|||
{ |
|||
var result = this._super.apply(this, arguments), |
|||
self = this; |
|||
if(!this.sidebar || this.sidebar.items.advanced_filters.length) |
|||
{ |
|||
return result; |
|||
} |
|||
this.sidebar.add_items( |
|||
'advanced_filters', |
|||
[ |
|||
{ |
|||
label: _t('Marked records'), |
|||
classname: 'oe_advanced_filters_header', |
|||
}, |
|||
{ |
|||
label: _t('To new selection'), |
|||
callback: function () |
|||
{ |
|||
self.advanced_filters_save_selection.apply( |
|||
self, arguments); |
|||
}, |
|||
}, |
|||
{ |
|||
label: _t('To existing selection'), |
|||
callback: function (item) |
|||
{ |
|||
self.advanced_filters_combine_with_existing.apply( |
|||
self, ['union', 'ids', item]); |
|||
}, |
|||
}, |
|||
{ |
|||
label: _t('Remove from existing selection'), |
|||
callback: function (item) |
|||
{ |
|||
self.advanced_filters_combine_with_existing.apply( |
|||
self, ['complement', 'ids', item]); |
|||
}, |
|||
}, |
|||
{ |
|||
label: _t('Whole result set'), |
|||
classname: 'oe_advanced_filters_header', |
|||
}, |
|||
{ |
|||
label: _t('To existing selection'), |
|||
callback: function (item) |
|||
{ |
|||
self.advanced_filters_combine_with_existing.apply( |
|||
self, ['union', 'domain', item]); |
|||
}, |
|||
}, |
|||
{ |
|||
label: _t('Remove from existing selection'), |
|||
callback: function (item) |
|||
{ |
|||
self.advanced_filters_combine_with_existing.apply( |
|||
self, ['complement', 'domain', item]); |
|||
}, |
|||
}, |
|||
] |
|||
); |
|||
this.do_select([], []); |
|||
return result; |
|||
}, |
|||
advanced_filters_save_selection: function(item) |
|||
{ |
|||
var self = this; |
|||
this.do_action({ |
|||
name: item.label, |
|||
type: 'ir.actions.act_window', |
|||
res_model: 'ir.filters', |
|||
views: [[false, 'form']], |
|||
target: 'new', |
|||
context: { |
|||
default_model_id: this.dataset._model.name, |
|||
default_domain: JSON.stringify( |
|||
[ |
|||
['id', 'in', this.groups.get_selection().ids], |
|||
] |
|||
), |
|||
default_context: JSON.stringify({}), |
|||
form_view_ref: 'advanced_filters.form_ir_filters_save_new', |
|||
}, |
|||
}, |
|||
{ |
|||
on_close: function() |
|||
{ |
|||
self.ViewManager.setup_search_view( |
|||
self.ViewManager.searchview.view_id, |
|||
self.ViewManager.searchview.defaults); |
|||
}, |
|||
}); |
|||
}, |
|||
advanced_filters_combine_with_existing: function(action, type, item) |
|||
{ |
|||
var search = this.ViewManager.searchview.build_search_data(), |
|||
self = this; |
|||
instance.web.pyeval.eval_domains_and_contexts({ |
|||
domains: search.domains, |
|||
contexts: search.contexts, |
|||
group_by_seq: search.groupbys || [] |
|||
}).done(function(search) |
|||
{ |
|||
var domain = [], ctx = {}; |
|||
switch(type) |
|||
{ |
|||
case 'domain': |
|||
domain = search.domain; |
|||
ctx = search.context; |
|||
_(_.keys(instance.session.user_context)).each( |
|||
function (key) {delete ctx[key]}); |
|||
break; |
|||
case 'ids': |
|||
domain = [ |
|||
['id', 'in', self.groups.get_selection().ids], |
|||
] |
|||
ctx = {}; |
|||
break; |
|||
} |
|||
self.do_action({ |
|||
name: item.label, |
|||
type: 'ir.actions.act_window', |
|||
res_model: 'ir.filters.combine.with.existing', |
|||
views: [[false, 'form']], |
|||
target: 'new', |
|||
context: _.extend({ |
|||
default_model: self.dataset._model.name, |
|||
default_domain: JSON.stringify(domain), |
|||
default_action: action, |
|||
default_context: JSON.stringify(ctx), |
|||
}, |
|||
self.dataset.context.default_filter_id ? { |
|||
default_filter_id: |
|||
self.dataset.context.default_filter_id, |
|||
} : {}), |
|||
}, |
|||
{ |
|||
on_close: function() |
|||
{ |
|||
self.ViewManager.setup_search_view( |
|||
self.ViewManager.searchview.view_id, |
|||
self.ViewManager.searchview.defaults); |
|||
}, |
|||
}); |
|||
}); |
|||
}, |
|||
}); |
|||
} |
@ -0,0 +1,44 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record id="ir_filters_view_form" model="ir.ui.view"> |
|||
<field name="model">ir.filters</field> |
|||
<field name="inherit_id" ref="base.ir_filters_view_form" /> |
|||
<field name="arch" type="xml"> |
|||
<sheet position="before"> |
|||
<header> |
|||
<button type="object" string="Test filter" name="button_test" class="oe_highlight" /> |
|||
<button type="object" string="Freeze filter" name="button_freeze" attrs="{'invisible': [('is_frozen', '=', True)]}" help="Have this filter contain extly the records it currently contains, with no changes in the future. Be careful, you can't undo this operation!" confirm="Are you sure? You can't undo this operation!" /> |
|||
</header> |
|||
</sheet> |
|||
<group position="after"> |
|||
<field name="is_frozen" invisible="True" /> |
|||
<field name="id" invisible="True" /> |
|||
<group string="Add the result of following filters"> |
|||
<field name="union_filter_ids" nolabel="1" domain="[('user_id', 'in', [False, uid]), ('id', '!=', id), ('model_id', '=', model_id)]" /> |
|||
</group> |
|||
<group string="Remove the result of following filters"> |
|||
<field name="complement_filter_ids" nolabel="1" domain="[('user_id', 'in', [False, uid]),('id', '!=', id), ('model_id', '=', model_id)]" /> |
|||
</group> |
|||
</group> |
|||
</field> |
|||
</record> |
|||
<record id="form_ir_filters_save_new" model="ir.ui.view"> |
|||
<field name="model">ir.filters</field> |
|||
<field name="priority">999</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Save filter" version="7.0"> |
|||
<group> |
|||
<field name="name" /> |
|||
<field name="is_default"/> |
|||
</group> |
|||
<footer> |
|||
<button class="oe_highlight" type="object" name="button_save" string="Save" /> |
|||
or |
|||
<button class="oe_link" special="cancel" string="Cancel" /> |
|||
</footer> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2014 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from . import ir_filters_combine_with_existing |
@ -0,0 +1,87 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2014 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import time |
|||
from openerp.osv.orm import TransientModel |
|||
from openerp.osv import fields, expression |
|||
from openerp.tools.safe_eval import const_eval |
|||
|
|||
|
|||
class IrFiltersCombineWithExisting(TransientModel): |
|||
_name = 'ir.filters.combine.with.existing' |
|||
_description = 'Combine a selection with an existing filter' |
|||
|
|||
_columns = { |
|||
'action': fields.selection( |
|||
[('union', 'Union'), ('complement', 'Complement')], |
|||
'Action', required=True), |
|||
'domain': fields.char('Domain', required=True), |
|||
'context': fields.char('Context', required=True), |
|||
'model': fields.char('Model', required=True), |
|||
'filter_id': fields.many2one('ir.filters', 'Filter', required=True), |
|||
} |
|||
|
|||
def button_save(self, cr, uid, ids, context=None): |
|||
assert len(ids) == 1 |
|||
this = self.browse(cr, uid, ids[0], context=context) |
|||
domain = const_eval(this.domain) |
|||
is_frozen = (len(domain) == 1 and |
|||
expression.is_leaf(domain[0]) and |
|||
domain[0][0] == 'id') |
|||
|
|||
if this.action == 'union': |
|||
if is_frozen and this.filter_id.is_frozen: |
|||
domain[0][2] = list(set(domain[0][2]).union( |
|||
set(const_eval(this.filter_id.domain)[0][2]))) |
|||
this.filter_id.write({'domain': str(domain)}) |
|||
else: |
|||
this.filter_id.write( |
|||
{ |
|||
'union_filter_ids': [(0, 0, { |
|||
'name': '%s_%s_%d' % ( |
|||
this.filter_id.name, 'add', time.time()), |
|||
'active': False, |
|||
'domain': str(domain), |
|||
'context': this.context, |
|||
'model_id': this.model, |
|||
'user_id': uid, |
|||
})], |
|||
}) |
|||
elif this.action == 'complement': |
|||
if is_frozen and this.filter_id.is_frozen: |
|||
complement_set = set(const_eval(this.filter_id.domain)[0][2]) |
|||
domain[0][2] = list( |
|||
complement_set.difference(set(domain[0][2]))) |
|||
this.filter_id.write({'domain': str(domain)}) |
|||
else: |
|||
this.filter_id.write( |
|||
{ |
|||
'complement_filter_ids': [(0, 0, { |
|||
'name': '%s_%s_%d' % ( |
|||
this.filter_id.name, 'remove', time.time()), |
|||
'active': False, |
|||
'domain': str(domain), |
|||
'context': this.context, |
|||
'model_id': this.model, |
|||
'user_id': uid, |
|||
})], |
|||
}) |
|||
|
|||
return {'type': 'ir.actions.act_window.close'} |
@ -0,0 +1,21 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record id="form_ir_filters_combine_with_existing" model="ir.ui.view"> |
|||
<field name="model">ir.filters.combine.with.existing</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Combine with existing filter" version="7.0"> |
|||
<group> |
|||
<field name="model" invisible="1" /> |
|||
<field name="filter_id" domain="[('model_id', '=', model)]" /> |
|||
</group> |
|||
<footer> |
|||
<button class="oe_highlight" type="object" name="button_save" string="Save" /> |
|||
or |
|||
<button class="oe_link" special="cancel" string="Cancel" /> |
|||
</footer> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue