Browse Source

Merge pull request #29 from hbrunn/7.0-advanced_filters

[ADD] advanced_filters
pull/70/head
Pedro M. Baeza 10 years ago
parent
commit
6741af5986
  1. 22
      web_advanced_filters/__init__.py
  2. 79
      web_advanced_filters/__openerp__.py
  3. 6
      web_advanced_filters/data/migration.xml
  4. 195
      web_advanced_filters/i18n/advanced_filter.pot
  5. 194
      web_advanced_filters/i18n/nl.po
  6. 21
      web_advanced_filters/model/__init__.py
  7. 175
      web_advanced_filters/model/ir_filters.py
  8. 14
      web_advanced_filters/static/src/css/web_advanced_filters.css
  9. BIN
      web_advanced_filters/static/src/img/icon.png
  10. 270
      web_advanced_filters/static/src/js/web_advanced_filters.js
  11. 44
      web_advanced_filters/view/ir_filters.xml
  12. 21
      web_advanced_filters/wizard/__init__.py
  13. 87
      web_advanced_filters/wizard/ir_filters_combine_with_existing.py
  14. 21
      web_advanced_filters/wizard/ir_filters_combine_with_existing.xml

22
web_advanced_filters/__init__.py

@ -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

79
web_advanced_filters/__openerp__.py

@ -0,0 +1,79 @@
# -*- 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": [
"data/migration.xml",
"wizard/ir_filters_combine_with_existing.xml",
"view/ir_filters.xml",
],
"js": [
'static/src/js/web_advanced_filters.js',
],
"css": [
'static/src/css/web_advanced_filters.css',
],
"qweb": [
],
"test": [
],
"auto_install": False,
"installable": True,
"application": False,
"external_dependencies": {
'python': [],
},
}

6
web_advanced_filters/data/migration.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data noupdate="1">
<function name="_migrate_name_change" model="ir.filters" />
</data>
</openerp>

195
web_advanced_filters/i18n/advanced_filter.pot

@ -0,0 +1,195 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * web_advanced_filters
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-07-29 10:55+0000\n"
"PO-Revision-Date: 2014-07-29 10:55+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Save filter"
msgstr ""
#. module: web_advanced_filters
#: selection:ir.filters.combine.with.existing,action:0
msgid "Union"
msgstr ""
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Add the result of following filters"
msgstr ""
#. module: web_advanced_filters
#: view:ir.filters:0
#: view:ir.filters.combine.with.existing:0
msgid "Save"
msgstr ""
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Freeze filter"
msgstr ""
#. module: web_advanced_filters
#. openerp-web
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:94
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:114
#, python-format
msgid "Remove from existing selection"
msgstr ""
#. module: web_advanced_filters
#: code:addons/web_advanced_filters/model/ir_filters.py:131
#, python-format
msgid "Testing %s"
msgstr ""
#. module: web_advanced_filters
#: view:ir.filters:0
#: view:ir.filters.combine.with.existing:0
msgid "or"
msgstr ""
#. module: web_advanced_filters
#: field:ir.filters,complement_filter_ids:0
msgid "Remove result of filters"
msgstr ""
#. module: web_advanced_filters
#. openerp-web
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:86
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:106
#, python-format
msgid "To existing selection"
msgstr ""
#. module: web_advanced_filters
#: view:ir.filters.combine.with.existing:0
msgid "Combine with existing filter"
msgstr ""
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Have this filter contain extly the records it currently contains, with no changes in the future. Be careful, you can't undo this operation!"
msgstr ""
#. module: web_advanced_filters
#. openerp-web
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:32
#, python-format
msgid "Advanced filters"
msgstr ""
#. module: web_advanced_filters
#: field:ir.filters,active:0
msgid "Active"
msgstr ""
#. module: web_advanced_filters
#. openerp-web
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:74
#, python-format
msgid "Marked records"
msgstr ""
#. module: web_advanced_filters
#: field:ir.filters,is_frozen:0
msgid "Frozen"
msgstr ""
#. module: web_advanced_filters
#: field:ir.filters.combine.with.existing,filter_id:0
msgid "Filter"
msgstr ""
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Test filter"
msgstr ""
#. module: web_advanced_filters
#. openerp-web
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:78
#, python-format
msgid "To new selection"
msgstr ""
#. module: web_advanced_filters
#: field:ir.filters,domain_this:0
msgid "This filter's own domain"
msgstr ""
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Remove the result of following filters"
msgstr ""
#. module: web_advanced_filters
#: field:ir.filters.combine.with.existing,context:0
msgid "Context"
msgstr ""
#. module: web_advanced_filters
#: field:ir.filters.combine.with.existing,action:0
msgid "Action"
msgstr ""
#. module: web_advanced_filters
#: field:ir.filters.combine.with.existing,model:0
msgid "Model"
msgstr ""
#. module: web_advanced_filters
#: field:ir.filters.combine.with.existing,domain:0
msgid "Domain"
msgstr ""
#. module: web_advanced_filters
#: field:ir.filters,union_filter_ids:0
msgid "Add result of filters"
msgstr ""
#. module: web_advanced_filters
#: model:ir.model,name:web_advanced_filters.model_ir_filters_combine_with_existing
msgid "Combine a selection with an existing filter"
msgstr ""
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Are you sure? You can't undo this operation!"
msgstr ""
#. module: web_advanced_filters
#: model:ir.model,name:web_advanced_filters.model_ir_filters
msgid "Filters"
msgstr ""
#. module: web_advanced_filters
#: view:ir.filters:0
#: view:ir.filters.combine.with.existing:0
msgid "Cancel"
msgstr ""
#. module: web_advanced_filters
#. openerp-web
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:102
#, python-format
msgid "Whole selection"
msgstr ""
#. module: web_advanced_filters
#: selection:ir.filters.combine.with.existing,action:0
msgid "Complement"
msgstr ""

194
web_advanced_filters/i18n/nl.po

@ -0,0 +1,194 @@
# This file contains the translation of the following modules:
# * web_advanced_filters
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-07-29 09:54+0000\n"
"PO-Revision-Date: 2014-07-29 09:54+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Save filter"
msgstr "Opslaan filter"
#. module: web_advanced_filters
#: selection:ir.filters.combine.with.existing,action:0
msgid "Union"
msgstr "Union"
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Add the result of following filters"
msgstr "Voeg resultaat van onderstaande filteringen toe aan filter"
#. module: web_advanced_filters
#: view:ir.filters:0
#: view:ir.filters.combine.with.existing:0
msgid "Save"
msgstr "Opslaan"
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Freeze filter"
msgstr "Bevries filter"
#. module: web_advanced_filters
#. openerp-web
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:94
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:114
#, python-format
msgid "Remove from existing filter"
msgstr "Verwijder uit bestaand filter"
#. module: web_advanced_filters
#: code:addons/web_advanced_filters/model/ir_filters.py:131
#, python-format
msgid "Testing %s"
msgstr "Testen %s"
#. module: web_advanced_filters
#: view:ir.filters:0
#: view:ir.filters.combine.with.existing:0
msgid "or"
msgstr "or"
#. module: web_advanced_filters
#: field:ir.filters,complement_filter_ids:0
msgid "Remove result of filters"
msgstr "Verwijder resultaat van filters"
#. module: web_advanced_filters
#. openerp-web
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:86
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:106
#, python-format
msgid "To existing filter"
msgstr "Voeg toe aan bestaand filter"
#. module: web_advanced_filters
#: view:ir.filters.combine.with.existing:0
msgid "Combine with existing filter"
msgstr "Combineer met bestaande filter"
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Have this filter contain exactly the records it currently contains, with no changes in the future. Be careful, you can't undo this operation!"
msgstr "Laat deze filter precies deze records bevatten, zonder veranderingen in de toekomst. Wees voorzichtig, je kan dit niet meer veranderen!"
#. module: web_advanced_filters
#. openerp-web
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:32
#, python-format
msgid "Advanced filters"
msgstr "Geavanceerde filters"
#. module: web_advanced_filters
#: field:ir.filters,active:0
msgid "Active"
msgstr "Actief"
#. module: web_advanced_filters
#. openerp-web
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:74
#, python-format
msgid "Marked records"
msgstr "Aangevinkte records (verzameling)"
#. module: web_advanced_filters
#: field:ir.filters,is_frozen:0
msgid "Frozen"
msgstr "Bevroren"
#. module: web_advanced_filters
#: field:ir.filters.combine.with.existing,filter_id:0
msgid "Filter"
msgstr "Filter"
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Test filter"
msgstr "Test filter"
#. module: web_advanced_filters
#. openerp-web
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:78
#, python-format
msgid "To new filter"
msgstr "Opslaan als nieuw filter"
#. module: web_advanced_filters
#: field:ir.filters,domain_this:0
msgid "This filter's own domain"
msgstr "Deze filters eigen domein"
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Remove the result of following filters"
msgstr "Verwijder resultaat van onderstaande filteringen uit filter"
#. module: web_advanced_filters
#: field:ir.filters.combine.with.existing,context:0
msgid "Context"
msgstr "Context"
#. module: web_advanced_filters
#: field:ir.filters.combine.with.existing,action:0
msgid "Action"
msgstr "Actie"
#. module: web_advanced_filters
#: field:ir.filters.combine.with.existing,model:0
msgid "Model"
msgstr "Model"
#. module: web_advanced_filters
#. openerp-web
#: code:addons/web_advanced_filters/static/src/js/web_advanced_filters.js:102
#, python-format
msgid "Whole selection (criteria)"
msgstr "Alle records (als criteria)"
#. module: web_advanced_filters
#: field:ir.filters.combine.with.existing,domain:0
msgid "Domain"
msgstr "Domein"
#. module: web_advanced_filters
#: field:ir.filters,union_filter_ids:0
msgid "Add result of filters"
msgstr "Voeg resultaat toe aan filters"
#. module: web_advanced_filters
#: model:ir.model,name:web_advanced_filters.model_ir_filters_combine_with_existing
msgid "Combine a selection with an existing filter"
msgstr "Combineer een selectie met een bestaande filter"
#. module: web_advanced_filters
#: view:ir.filters:0
msgid "Are you sure? You can't undo this operation!"
msgstr "Weet u het zeker? U kan deze operatie niet meer ongedaan maken"
#. module: web_advanced_filters
#: model:ir.model,name:web_advanced_filters.model_ir_filters
msgid "Filters"
msgstr "Filters"
#. module: web_advanced_filters
#: view:ir.filters:0
#: view:ir.filters.combine.with.existing:0
msgid "Cancel"
msgstr "Annuleren"
#. module: web_advanced_filters
#: selection:ir.filters.combine.with.existing,action:0
msgid "Complement"
msgstr "Aanvullen"

21
web_advanced_filters/model/__init__.py

@ -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

175
web_advanced_filters/model/ir_filters.py

@ -0,0 +1,175 @@
# -*- 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 safe_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):
try:
domain = safe_eval(this.domain)
except:
domain = [expression.FALSE_LEAF]
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'''
try:
domain = safe_eval(domain)
except:
domain = [expression.FALSE_LEAF]
return expression.normalize_domain(
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, safe_eval(this.domain), context=safe_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 [('id', '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=context):
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)
def _migrate_name_change(self, cr, uid, context=None):
cr.execute(
"select id from ir_module_module where name='advanced_filters' "
"and author='Therp BV'")
old_name_installed = cr.fetchall()
if not old_name_installed:
return
cr.execute(
"delete from ir_model_data where module='web_advanced_filters'")
cr.execute(
"update ir_model_data set module='web_advanced_filters' "
"where module='advanced_filters'")
cr.execute(
"update ir_module_module set state='to remove' where "
"name='advanced_filters' and state not in "
"('uninstalled', 'to remove')")

14
web_advanced_filters/static/src/css/web_advanced_filters.css

@ -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;
}

BIN
web_advanced_filters/static/src/img/icon.png

After

Width: 128  |  Height: 128  |  Size: 16 KiB

270
web_advanced_filters/static/src/js/web_advanced_filters.js

@ -0,0 +1,270 @@
//-*- 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.web_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);
this.advanced_filters_show(ids);
return result;
},
load_list: function(data)
{
var result = this._super.apply(this, arguments),
self = this;
if(!this.sidebar || this.sidebar.items.advanced_filters.length)
{
this.advanced_filters_show([]);
return result;
}
this.sidebar.add_items(
'advanced_filters',
[
{
label: _t('Whole selection (criteria)'),
classname: 'oe_advanced_filters_header',
},
{
label: _t('To new filter'),
callback: function ()
{
self.advanced_filters_save_criteria.apply(
self, arguments);
},
},
{
label: _t('To existing filter'),
callback: function (item)
{
self.advanced_filters_combine_with_existing.apply(
self, ['union', 'domain', item]);
},
},
{
label: _t('Remove from existing filter'),
callback: function (item)
{
self.advanced_filters_combine_with_existing.apply(
self, ['complement', 'domain', item]);
},
},
{
label: _t('Marked records'),
classname: 'oe_advanced_filters_header',
},
{
label: _t('To new filter'),
callback: function ()
{
self.advanced_filters_save_selection.apply(
self, arguments);
},
},
{
label: _t('To existing filter'),
callback: function (item)
{
self.advanced_filters_combine_with_existing.apply(
self, ['union', 'ids', item]);
},
},
{
label: _t('Remove from existing filter'),
callback: function (item)
{
self.advanced_filters_combine_with_existing.apply(
self, ['complement', 'ids', item]);
},
},
]
);
this.do_select([], []);
return result;
},
advanced_filters_show: function(ids)
{
var self = this;
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)
{
var search = self.ViewManager.searchview
.build_search_data();
$e.find('a[data-index="0"],a[data-index="1"],' +
'a[data-index="2"],a[data-index="3"]')
.parent().toggle(
search.contexts.length > 0 ||
search.domains.length > 0);
$e.find('a[data-index="4"],a[data-index="5"],' +
'a[data-index="6"],a[data-index="7"]')
.parent().toggle(ids.length > 0);
$e.toggle(
search.contexts.length > 0 ||
search.domains.length > 0 ||
ids.length > 0);
}
else
{
$e.toggle(ids.length > 0);
}
});
}
},
advanced_filters_save_criteria: function(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 ctx = search.context;
_(_.keys(instance.session.user_context)).each(
function (key) {delete ctx[key]});
self.do_action({
name: item.label,
type: 'ir.actions.act_window',
res_model: 'ir.filters',
views: [[false, 'form']],
target: 'new',
context: {
default_model_id: self.dataset._model.name,
default_domain: JSON.stringify(search.domain),
default_context: JSON.stringify(ctx),
form_view_ref: 'web_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_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: 'web_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);
},
});
});
},
});
}

44
web_advanced_filters/view/ir_filters.xml

@ -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&apos;t undo this operation!" confirm="Are you sure? You can&apos;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>

21
web_advanced_filters/wizard/__init__.py

@ -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

87
web_advanced_filters/wizard/ir_filters_combine_with_existing.py

@ -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 safe_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 = safe_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(safe_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(safe_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'}

21
web_advanced_filters/wizard/ir_filters_combine_with_existing.xml

@ -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>
Loading…
Cancel
Save