From 87b23c05d24b5d7891e60672720f6a8e0b60450d Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 14 Sep 2011 18:00:40 +0200 Subject: [PATCH 1/9] [REVERT] Revert revid:fme@openerp.com-20110907074810-17ssgepzpc11u7bd causing problems in search view bzr revid: fme@openerp.com-20110914160040-1bvgewarlh5x3tsq --- addons/web/static/src/css/base.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 02ea33e4ec3..4645c55f692 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -842,8 +842,8 @@ label.error { .openerp label.oe_label_help { cursor: help; } -.openerp label.oe_label, -.openerp label.oe_label_help { + +.openerp .oe_form_field label.oe_label, .openerp .oe_form_field label.oe_label_help { text-align: right; margin: 3px 0 0 10px; } From 17f64b27e32a452eb286551830cb325f4cda7c16 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Wed, 14 Sep 2011 19:57:11 +0200 Subject: [PATCH 2/9] [FIX] remove openerplib.openerplib bzr revid: al@openerp.com-20110914175711-9e5x85f4r9wd4q6w --- .../common/openerplib/openerplib/__init__.py | 35 -- .../web/common/openerplib/openerplib/dates.py | 99 ----- .../web/common/openerplib/openerplib/main.py | 397 ------------------ 3 files changed, 531 deletions(-) delete mode 100644 addons/web/common/openerplib/openerplib/__init__.py delete mode 100644 addons/web/common/openerplib/openerplib/dates.py delete mode 100644 addons/web/common/openerplib/openerplib/main.py diff --git a/addons/web/common/openerplib/openerplib/__init__.py b/addons/web/common/openerplib/openerplib/__init__.py deleted file mode 100644 index 23fc257e4d1..00000000000 --- a/addons/web/common/openerplib/openerplib/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Copyright (C) Stephane Wirtel -# Copyright (C) 2011 Nicolas Vanhoren -# Copyright (C) 2011 OpenERP s.a. (). -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -############################################################################## - - -from main import * - diff --git a/addons/web/common/openerplib/openerplib/dates.py b/addons/web/common/openerplib/openerplib/dates.py deleted file mode 100644 index 6d6c3808c27..00000000000 --- a/addons/web/common/openerplib/openerplib/dates.py +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Copyright (C) Stephane Wirtel -# Copyright (C) 2011 Nicolas Vanhoren -# Copyright (C) 2011 OpenERP s.a. (). -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -############################################################################## - -import datetime - -DEFAULT_SERVER_DATE_FORMAT = "%Y-%m-%d" -DEFAULT_SERVER_TIME_FORMAT = "%H:%M:%S" -DEFAULT_SERVER_DATETIME_FORMAT = "%s %s" % ( - DEFAULT_SERVER_DATE_FORMAT, - DEFAULT_SERVER_TIME_FORMAT) - -def str_to_datetime(str): - """ - Converts a string to a datetime object using OpenERP's - datetime string format (exemple: '2011-12-01 15:12:35'). - - No timezone information is added, the datetime is a naive instance, but - according to OpenERP 6.1 specification the timezone is always UTC. - """ - if not str: - return str - return datetime.datetime.strptime(str, DEFAULT_SERVER_DATETIME_FORMAT) - -def str_to_date(str): - """ - Converts a string to a date object using OpenERP's - date string format (exemple: '2011-12-01'). - """ - if not str: - return str - return datetime.datetime.strptime(str, DEFAULT_SERVER_DATE_FORMAT).date() - -def str_to_time(str): - """ - Converts a string to a time object using OpenERP's - time string format (exemple: '15:12:35'). - """ - if not str: - return str - return datetime.datetime.strptime(str, DEFAULT_SERVER_TIME_FORMAT).time() - -def datetime_to_str(obj): - """ - Converts a datetime object to a string using OpenERP's - datetime string format (exemple: '2011-12-01 15:12:35'). - - The datetime instance should not have an attached timezone and be in UTC. - """ - if not obj: - return False - return obj.strftime(DEFAULT_SERVER_DATETIME_FORMAT) - -def date_to_str(obj): - """ - Converts a date object to a string using OpenERP's - date string format (exemple: '2011-12-01'). - """ - if not obj: - return False - return obj.strftime(DEFAULT_SERVER_DATE_FORMAT) - -def time_to_str(obj): - """ - Converts a time object to a string using OpenERP's - time string format (exemple: '15:12:35'). - """ - if not obj: - return False - return obj.strftime(DEFAULT_SERVER_TIME_FORMAT) - diff --git a/addons/web/common/openerplib/openerplib/main.py b/addons/web/common/openerplib/openerplib/main.py deleted file mode 100644 index 2fee67b7daa..00000000000 --- a/addons/web/common/openerplib/openerplib/main.py +++ /dev/null @@ -1,397 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Copyright (C) Stephane Wirtel -# Copyright (C) 2011 Nicolas Vanhoren -# Copyright (C) 2011 OpenERP s.a. (). -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -############################################################################## - -""" -OpenERP Client Library -""" - -import xmlrpclib -import logging -import socket - -try: - import cPickle as pickle - pickle.__name__ -except: - import pickle - -try: - import cStringIO as StringIO - StringIO.__name__ -except: - import StringIO - -_logger = logging.getLogger(__name__) - -def _getChildLogger(logger, subname): - return logging.getLogger(logger.name + "." + subname) - -class Connector(object): - """ - The base abstract class representing a connection to an OpenERP Server. - """ - - __logger = _getChildLogger(_logger, 'connector') - - def __init__(self, hostname, port): - """ - Initilize by specifying an hostname and a port. - :param hostname: Host name of the server. - :param port: Port for the connection to the server. - """ - self.hostname = hostname - self.port = port - -class XmlRPCConnector(Connector): - """ - A type of connector that uses the XMLRPC protocol. - """ - PROTOCOL = 'xmlrpc' - - __logger = _getChildLogger(_logger, 'connector.xmlrpc') - - def __init__(self, hostname, port=8069): - """ - Initialize by specifying the hostname and the port. - :param hostname: The hostname of the computer holding the instance of OpenERP. - :param port: The port used by the OpenERP instance for XMLRPC (default to 8069). - """ - Connector.__init__(self, hostname, port) - self.url = 'http://%s:%d/xmlrpc' % (self.hostname, self.port) - - def send(self, service_name, method, *args): - url = '%s/%s' % (self.url, service_name) - service = xmlrpclib.ServerProxy(url) - return getattr(service, method)(*args) - -class NetRPC_Exception(Exception): - """ - Exception for NetRPC errors. - """ - def __init__(self, faultCode, faultString): - self.faultCode = faultCode - self.faultString = faultString - self.args = (faultCode, faultString) - -class NetRPC: - """ - Low level class for NetRPC protocol. - """ - def __init__(self, sock=None): - if sock is None: - self.sock = socket.socket( - socket.AF_INET, socket.SOCK_STREAM) - else: - self.sock = sock - self.sock.settimeout(120) - def connect(self, host, port=False): - if not port: - buf = host.split('//')[1] - host, port = buf.split(':') - self.sock.connect((host, int(port))) - - def disconnect(self): - self.sock.shutdown(socket.SHUT_RDWR) - self.sock.close() - - def mysend(self, msg, exception=False, traceback=None): - msg = pickle.dumps([msg,traceback]) - size = len(msg) - self.sock.send('%8d' % size) - self.sock.send(exception and "1" or "0") - totalsent = 0 - while totalsent < size: - sent = self.sock.send(msg[totalsent:]) - if sent == 0: - raise RuntimeError, "socket connection broken" - totalsent = totalsent + sent - - def myreceive(self): - buf='' - while len(buf) < 8: - chunk = self.sock.recv(8 - len(buf)) - if chunk == '': - raise RuntimeError, "socket connection broken" - buf += chunk - size = int(buf) - buf = self.sock.recv(1) - if buf != "0": - exception = buf - else: - exception = False - msg = '' - while len(msg) < size: - chunk = self.sock.recv(size-len(msg)) - if chunk == '': - raise RuntimeError, "socket connection broken" - msg = msg + chunk - msgio = StringIO.StringIO(msg) - unpickler = pickle.Unpickler(msgio) - unpickler.find_global = None - res = unpickler.load() - - if isinstance(res[0],Exception): - if exception: - raise NetRPC_Exception(str(res[0]), str(res[1])) - raise res[0] - else: - return res[0] - -class NetRPCConnector(Connector): - """ - A type of connector that uses the NetRPC protocol. - """ - - PROTOCOL = 'netrpc' - - __logger = _getChildLogger(_logger, 'connector.netrpc') - - def __init__(self, hostname, port=8070): - """ - Initialize by specifying the hostname and the port. - :param hostname: The hostname of the computer holding the instance of OpenERP. - :param port: The port used by the OpenERP instance for NetRPC (default to 8070). - """ - Connector.__init__(self, hostname, port) - - def send(self, service_name, method, *args): - socket = NetRPC() - socket.connect(self.hostname, self.port) - socket.mysend((service_name, method, )+args) - result = socket.myreceive() - socket.disconnect() - return result - -class Service: - """ - A class to execute RPC calls on a specific service of the remote server. - """ - def __init__(self, connector, service_name): - """ - :param connector: A valid Connector instance. - :param service_name: The name of the service on the remote server. - """ - self.connector = connector - self.service_name = service_name - self.__logger = _getChildLogger(_getChildLogger(_logger, 'service'),service_name) - - def __getattr__(self, method): - """ - :param method: The name of the method to execute on the service. - """ - self.__logger.debug('method: %r', method) - def proxy(*args): - """ - :param args: A list of values for the method - """ - self.__logger.debug('args: %r', args) - result = self.connector.send(self.service_name, method, *args) - self.__logger.debug('result: %r' % result) - return result - return proxy - -class Connection(object): - """ - A class to represent a connection with authentification to an OpenERP Server. - It also provides utility methods to interact with the server more easily. - """ - __logger = _getChildLogger(_logger, 'connection') - - def __init__(self, connector, - database=None, - login=None, - password=None, - user_id=None): - """ - Initialize with login information. The login information is facultative to allow specifying - it after the initialization of this object. - - :param connector: A valid Connector instance to send messages to the remote server. - :param database: The name of the database to work on. - :param login: The login of the user. - :param password: The password of the user. - :param user_id: The user id is a number identifying the user. This is only useful if you - already know it, in most cases you don't need to specify it. - """ - self.connector = connector - - self.set_login_info(database, login, password, user_id) - - def set_login_info(self, database, login, password, user_id=None): - """ - Set login information after the initialisation of this object. - - :param connector: A valid Connector instance to send messages to the remote server. - :param database: The name of the database to work on. - :param login: The login of the user. - :param password: The password of the user. - :param user_id: The user id is a number identifying the user. This is only useful if you - already know it, in most cases you don't need to specify it. - """ - self.database, self.login, self.password = database, login, password - - self.user_id = user_id - - def check_login(self, force=True): - """ - Checks that the login information is valid. Throws an AuthentificationError if the - authentification fails. - - :param force: Force to re-check even if this Connection was already validated previously. - Default to True. - """ - if self.user_id and not force: - return - - self.user_id = self.get_service("common").login(self.database, self.login, self.password) - if not self.user_id: - raise AuthentificationError("Authentification failure") - self.__logger.debug("Authentified with user id %s" % self.user_id) - - """ - Returns a Model instance to allow easy remote manipulation of an OpenERP model. - - :param model_name: The name of the model. - """ - def get_model(self, model_name): - return Model(self, model_name) - - """ - Returns a Service instance to allow easy manipulation of one of the services offered by the remote server. - Please note this Connection instance does not need to have valid authenfication information since authentification - is only necessary for the "object" service that handles models. - - :param service_name: The name of the service. - """ - def get_service(self, service_name): - return Service(self.connector, service_name) - -class AuthentificationError(Exception): - """ - An error thrown when an authentification to an OpenERP server failed. - """ - pass - -class Model(object): - """ - Useful class to dialog with one of the models provided by an OpenERP server. - An instance of this class depends on a Connection instance with valid authenfication information. - """ - - def __init__(self, connection, model_name): - """ - :param connection: A valid Connection instance with correct authentification information. - :param model_name: The name of the model. - """ - self.connection = connection - self.model_name = model_name - self.__logger = _getChildLogger(_getChildLogger(_logger, 'object'), model_name) - - def __getattr__(self, method): - """ - Provides proxy methods that will forward calls to the model on the remote OpenERP server. - - :param method: The method for the linked model (search, read, write, unlink, create, ...) - """ - def proxy(*args): - """ - :param args: A list of values for the method - """ - self.connection.check_login(False) - self.__logger.debug(args) - result = self.connection.get_service('object').execute( - self.connection.database, - self.connection.user_id, - self.connection.password, - self.model_name, - method, - *args) - if method == "read": - if isinstance(result, list) and len(result) > 0 and "id" in result[0]: - index = {} - for i in xrange(len(result)): - index[result[i]["id"]] = result[i] - result = [index[x] for x in args[0]] - self.__logger.debug('result: %r' % result) - return result - return proxy - - def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, context=None): - """ - A shortcut method to combine a search() and a read(). - - :param domain: The domain for the search. - :param fields: The fields to extract (can be None or [] to extract all fields). - :param offset: The offset for the rows to read. - :param limit: The maximum number of rows to read. - :param order: The order to class the rows. - :param context: The context. - :return: A list of dictionaries containing all the specified fields. - """ - record_ids = self.search(domain or [], offset, limit or False, order or False, context or {}) - records = self.read(record_ids, fields or [], context or {}) - return records - -def get_connector(hostname, protocol="xmlrpc", port="auto"): - """ - A shortcut method to easily create a connector to a remote server using XMLRPC or NetRPC. - - :param hostname: The hostname to the remote server. - :param protocol: The name of the protocol, must be "xmlrpc" or "netrpc". - :param port: The number of the port. Defaults to auto. - """ - if port == 'auto': - port = 8069 if protocol=="xmlrpc" else 8070 - if protocol == "xmlrpc": - return XmlRPCConnector(hostname, port) - elif protocol == "netrpc": - return NetRPCConnector(hostname, port) - else: - raise ValueError("You must choose xmlrpc or netrpc") - -def get_connection(hostname, protocol="xmlrpc", port='auto', database=None, - login=None, password=None, user_id=None): - """ - A shortcut method to easily create a connection to a remote OpenERP server. - - :param hostname: The hostname to the remote server. - :param protocol: The name of the protocol, must be "xmlrpc" or "netrpc". - :param port: The number of the port. Defaults to auto. - :param connector: A valid Connector instance to send messages to the remote server. - :param database: The name of the database to work on. - :param login: The login of the user. - :param password: The password of the user. - :param user_id: The user id is a number identifying the user. This is only useful if you - already know it, in most cases you don't need to specify it. - """ - return Connection(get_connector(hostname, protocol, port), database, login, password, user_id) - From 3ef575744d0b83fbdaa09334d0f217b2ad5065b9 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Wed, 14 Sep 2011 22:40:57 +0200 Subject: [PATCH 3/9] =?UTF-8?q?[IMP]=20prefix=20view=20(obsessive=E2=80=93?= =?UTF-8?q?compulsive=20rename=20disorder)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bzr revid: al@openerp.com-20110914204057-cg8y5yy3py70ge62 --- addons/web/__openerp__.py | 6 +++--- addons/web/static/src/js/{form.js => view_form.js} | 0 addons/web/static/src/js/{list.js => view_list.js} | 0 .../src/js/{list-editable.js => view_list_editable.js} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename addons/web/static/src/js/{form.js => view_form.js} (100%) rename addons/web/static/src/js/{list.js => view_list.js} (100%) rename addons/web/static/src/js/{list-editable.js => view_list_editable.js} (100%) diff --git a/addons/web/__openerp__.py b/addons/web/__openerp__.py index dd4d2071f00..9a1fd119fb9 100644 --- a/addons/web/__openerp__.py +++ b/addons/web/__openerp__.py @@ -32,10 +32,10 @@ "static/src/js/views.js", "static/src/js/data.js", "static/src/js/data_export.js", - "static/src/js/form.js", - "static/src/js/list.js", - "static/src/js/list-editable.js", "static/src/js/search.js", + "static/src/js/view_form.js", + "static/src/js/view_list.js", + "static/src/js/view_list_editable.js", "static/src/js/view_tree.js", ], 'css' : [ diff --git a/addons/web/static/src/js/form.js b/addons/web/static/src/js/view_form.js similarity index 100% rename from addons/web/static/src/js/form.js rename to addons/web/static/src/js/view_form.js diff --git a/addons/web/static/src/js/list.js b/addons/web/static/src/js/view_list.js similarity index 100% rename from addons/web/static/src/js/list.js rename to addons/web/static/src/js/view_list.js diff --git a/addons/web/static/src/js/list-editable.js b/addons/web/static/src/js/view_list_editable.js similarity index 100% rename from addons/web/static/src/js/list-editable.js rename to addons/web/static/src/js/view_list_editable.js From eadb161a38cb9d1bd6065bf2e01f103b8e96017d Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 14 Sep 2011 23:04:45 +0200 Subject: [PATCH 4/9] [IMP] Improved dirty state in form view bzr revid: fme@openerp.com-20110914210445-ul8aax7g1q5b47c6 --- addons/web/static/src/js/view_form.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index aecc52c5eef..583f8f38b67 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -35,7 +35,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# this.datarecord = {}; this.ready = false; this.show_invalid = true; - this.dirty = false; + this.dirty_for_user = false; this.default_focus_field = null; this.default_focus_button = null; this.registry = openerp.web.form.widgets; @@ -135,7 +135,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# this.$form_header.find('.oe_form_on_update').show(); this.$form_header.find('button.oe_form_button_new').show(); } - this.dirty = false; + this.dirty_for_user = false; this.datarecord = record; for (var f in this.fields) { var field = this.fields[f]; @@ -145,7 +145,6 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# } if (!record.id) { // New record: Second pass in order to trigger the onchanges - this.dirty = true; this.show_invalid = false; for (var f in record) { var field = this.fields[f]; @@ -270,7 +269,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# processed.push(field.name); if (field.get_value() != value) { field.set_value(value); - field.dirty = true; + field.dirty = this.dirty_for_user = true; if (_.indexOf(processed, field.name) < 0) { this.do_onchange(field, processed); } @@ -298,10 +297,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# var self = this; var def = $.Deferred(); $.when(this.has_been_loaded).then(function() { - self.dataset.default_get( - _.keys(self.fields_view.fields)).then(self.on_record_loaded).then(function() { - def.resolve(); - }); + self.dataset.default_get(_.keys(self.fields_view.fields)).then(self.on_record_loaded).then(function() { + def.resolve(); + }); }); return def.promise(); }, @@ -809,7 +807,7 @@ openerp.web.form.WidgetButton = openerp.web.form.Widget.extend({ }, on_click: function(saved) { var self = this; - if (!this.node.attrs.special && this.view.dirty && saved !== true) { + if ((!this.node.attrs.special && this.view.dirty_for_user && saved !== true) || !this.view.recordcount.id) { this.view.do_save(function() { self.on_click(true); }); @@ -957,7 +955,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f } }, on_ui_change: function() { - this.dirty = this.view.dirty = true; + this.dirty = this.view.dirty_for_user = true; this.validate(); if (this.is_valid()) { this.set_value_from_ui(); From 5189b91d8e81642ea65baac3d25403a29967b79b Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 14 Sep 2011 23:09:02 +0200 Subject: [PATCH 5/9] [ADD] Add form dirty confirmation dialog bzr revid: fme@openerp.com-20110914210902-z08taar5woqmxnts --- addons/web/static/src/js/view_form.js | 41 ++++++++++++++++----------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 583f8f38b67..b097fc6abf0 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -173,21 +173,23 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# } }, on_pager_action: function(action) { - switch (action) { - case 'first': - this.dataset.index = 0; - break; - case 'previous': - this.dataset.previous(); - break; - case 'next': - this.dataset.next(); - break; - case 'last': - this.dataset.index = this.dataset.ids.length - 1; - break; + if (this.can_be_discarded()) { + switch (action) { + case 'first': + this.dataset.index = 0; + break; + case 'previous': + this.dataset.previous(); + break; + case 'next': + this.dataset.next(); + break; + case 'last': + this.dataset.index = this.dataset.ids.length - 1; + break; + } + this.reload(); } - this.reload(); }, do_update_pager: function(hide_index) { var $pager = this.$element.find('#' + this.element_id + '_header div.oe_form_pager'); @@ -297,12 +299,17 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# var self = this; var def = $.Deferred(); $.when(this.has_been_loaded).then(function() { - self.dataset.default_get(_.keys(self.fields_view.fields)).then(self.on_record_loaded).then(function() { - def.resolve(); - }); + if (self.can_be_discarded()) { + self.dataset.default_get(_.keys(self.fields_view.fields)).then(self.on_record_loaded).then(function() { + def.resolve(); + }); + } }); return def.promise(); }, + can_be_discarded: function() { + return !this.dirty_for_user || confirm(_t("Warning, the record has been modified, your changes will be discarded.")); + }, /** * Triggers saving the form's record. Chooses between creating a new * record or saving an existing one depending on whether the record From 79440f2b7bbd9ff8aa5610bb29761779fdb7fd87 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Wed, 14 Sep 2011 23:54:03 +0200 Subject: [PATCH 6/9] =?UTF-8?q?[IMP]=20rename=20openerp=20into=20db=20in?= =?UTF-8?q?=20views.js=20(obsessive=E2=80=93compulsive=20rename=20disorder?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bzr revid: al@openerp.com-20110914215403-vu110701a9701nip --- addons/web/static/src/js/views.js | 93 +++++++++++++++---------------- 1 file changed, 44 insertions(+), 49 deletions(-) diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 0c3ef6c65d6..46c3f7e6b30 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -2,17 +2,21 @@ * OpenERP web library *---------------------------------------------------------*/ -openerp.web.views = function(openerp) { +openerp.web.views = function(db) { -var _t = openerp.web._t; -var QWeb = openerp.web.qweb; +var _t = db.web._t; /** * Registry for all the client actions key: tag value: widget */ -openerp.web.client_actions = new openerp.web.Registry(); +db.web.client_actions = new db.web.Registry(); -openerp.web.ActionManager = openerp.web.Widget.extend({ +/** + * Registry for all the main views + */ +db.web.views = new db.web.Registry(); + +db.web.ActionManager = db.web.Widget.extend({ identifier_prefix: "actionmanager", init: function(parent) { this._super(parent); @@ -87,20 +91,20 @@ openerp.web.ActionManager = openerp.web.Widget.extend({ ir_actions_act_window: function (action, on_close) { if (action.target === 'new') { if (this.dialog == null) { - this.dialog = new openerp.web.Dialog(this, { title: action.name, width: '80%' }); + this.dialog = new db.web.Dialog(this, { title: action.name, width: '80%' }); if(on_close) this.dialog.on_close.add(on_close); this.dialog.start(); } else { this.dialog_viewmanager.stop(); } - this.dialog_viewmanager = new openerp.web.ViewManagerAction(this, action); + this.dialog_viewmanager = new db.web.ViewManagerAction(this, action); this.dialog_viewmanager.appendTo(this.dialog.$element); this.dialog.open(); } else { this.dialog_stop(); this.content_stop(); - this.inner_viewmanager = new openerp.web.ViewManagerAction(this, action); + this.inner_viewmanager = new db.web.ViewManagerAction(this, action); this.inner_viewmanager.appendTo(this.$element); this.url_update(action); } @@ -125,7 +129,7 @@ openerp.web.ActionManager = openerp.web.Widget.extend({ }, ir_actions_client: function (action) { this.content_stop(); - var ClientWidget = openerp.web.client_actions.get_object(action.tag); + var ClientWidget = db.web.client_actions.get_object(action.tag); (this.client_widget = new ClientWidget(this, action.params)).appendTo(this); }, ir_actions_report_xml: function(action) { @@ -138,12 +142,12 @@ openerp.web.ActionManager = openerp.web.Widget.extend({ } }); -openerp.web.ViewManager = openerp.web.Widget.extend(/** @lends openerp.web.ViewManager# */{ +db.web.ViewManager = db.web.Widget.extend(/** @lends db.web.ViewManager# */{ identifier_prefix: "viewmanager", template: "ViewManager", /** - * @constructs openerp.web.ViewManager - * @extends openerp.web.Widget + * @constructs db.web.ViewManager + * @extends db.web.Widget * * @param parent * @param dataset @@ -158,10 +162,10 @@ openerp.web.ViewManager = openerp.web.Widget.extend(/** @lends openerp.web.View this.views_src = _.map(views, function(x) {return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;}); this.views = {}; this.flags = this.flags || {}; - this.registry = openerp.web.views; + this.registry = db.web.views; }, render: function() { - return QWeb.render(this.template, { + return db.web.qweb.render(this.template, { self: this, prefix: this.element_id, views: this.views_src}); @@ -280,7 +284,7 @@ openerp.web.ViewManager = openerp.web.Widget.extend(/** @lends openerp.web.View if (this.searchview) { this.searchview.stop(); } - this.searchview = new openerp.web.SearchView( + this.searchview = new db.web.SearchView( this, this.element_id + "_search", this.dataset, view_id, search_defaults); @@ -307,13 +311,13 @@ openerp.web.ViewManager = openerp.web.Widget.extend(/** @lends openerp.web.View on_action_executed: function () {} }); -openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepnerp.web.ViewManagerAction# */{ +db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.ViewManagerAction# */{ template:"ViewManagerAction", /** - * @constructs openerp.web.ViewManagerAction - * @extends openerp.web.ViewManager + * @constructs db.web.ViewManagerAction + * @extends db.web.ViewManager * - * @param {openerp.web.ActionManager} parent parent object/widget + * @param {db.web.ActionManager} parent parent object/widget * @param {Object} action descriptor for the action this viewmanager needs to manage its views. */ init: function(parent, action) { @@ -322,7 +326,7 @@ openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepner // ``_super()``) rpc requests will blow up. this.session = parent.session; this.action = action; - var dataset = new openerp.web.DataSetSearch(this, action.res_model, action.context, action.domain); + var dataset = new db.web.DataSetSearch(this, action.res_model, action.context, action.domain); if (action.res_id) { dataset.ids.push(action.res_id); dataset.index = 0; @@ -376,12 +380,12 @@ openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepner this.$element.find('.oe_get_xml_view').click(function () { // TODO: add search view? - $('
').text(openerp.web.json_node_to_xml(
+            $('
').text(db.web.json_node_to_xml(
                 self.views[self.active_view].controller.fields_view.arch, true))
                     .dialog({ width: '95%'});
         });
         if (this.action.help && !this.flags.low_profile) {
-            var Users = new openerp.web.DataSet(self, 'res.users'),
+            var Users = new db.web.DataSet(self, 'res.users'),
                 header = this.$element.find('.oe-view-manager-header');
             header.delegate('blockquote button', 'click', function() {
                 var $this = $(this);
@@ -421,7 +425,7 @@ openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepner
         var grandparent = this.widget_parent && this.widget_parent.widget_parent;
         // display shortcuts if on the first view for the action
         var $shortcut_toggle = this.$element.find('.oe-shortcut-toggle');
-        if (!(grandparent instanceof openerp.web.WebClient) ||
+        if (!(grandparent instanceof db.web.WebClient) ||
             !(view.view_type === this.views_src[0].view_type
                 && view.view_id === this.views_src[0].view_id)) {
             $shortcut_toggle.hide();
@@ -458,7 +462,7 @@ openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepner
      * Intercept do_action resolution from children views
      */
     on_action_executed: function () {
-        new openerp.web.DataSet(this, 'res.log')
+        new db.web.DataSet(this, 'res.log')
                 .call('get', [], this.do_display_log);
     },
     /**
@@ -485,7 +489,7 @@ openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepner
     }
 });
 
-openerp.web.Sidebar = openerp.web.Widget.extend({
+db.web.Sidebar = db.web.Widget.extend({
     init: function(parent, element_id) {
         this._super(parent, element_id);
         this.items = {};
@@ -494,7 +498,7 @@ openerp.web.Sidebar = openerp.web.Widget.extend({
     start: function() {
         this._super(this);
         var self = this;
-        this.$element.html(QWeb.render('Sidebar'));
+        this.$element.html(db.web.qweb.render('Sidebar'));
         this.$element.find(".toggle-sidebar").click(function(e) {
             self.do_toggle();
         });
@@ -536,7 +540,7 @@ openerp.web.Sidebar = openerp.web.Widget.extend({
                 this.items[items[i].element_id] = items[i];
             }
         }
-        var $section = $(QWeb.render("Sidebar.section", {
+        var $section = $(db.web.qweb.render("Sidebar.section", {
             section_id: section_id,
             name: name,
             classname: 'oe_sidebar_' + code,
@@ -592,7 +596,7 @@ openerp.web.Sidebar = openerp.web.Widget.extend({
     }
 });
 
-openerp.web.TranslateDialog = openerp.web.Dialog.extend({
+db.web.TranslateDialog = db.web.Dialog.extend({
     dialog_title: _t("Translations"),
     init: function(view) {
         // TODO fme: should add the language to fields_view_get because between the fields view get
@@ -612,14 +616,14 @@ openerp.web.TranslateDialog = openerp.web.Dialog.extend({
         this.translatable_fields_keys = _.map(this.view.translatable_fields || [], function(i) { return i.name });
         this.languages = null;
         this.languages_loaded = $.Deferred();
-        (new openerp.web.DataSetSearch(this, 'res.lang', this.view.dataset.get_context(),
+        (new db.web.DataSetSearch(this, 'res.lang', this.view.dataset.get_context(),
             [['translatable', '=', '1']])).read_slice(['code', 'name'], { sort: 'id' }, this.on_languages_loaded);
     },
     start: function() {
         var self = this;
         this._super();
         $.when(this.languages_loaded).then(function() {
-            self.$element.html(QWeb.render('TranslateDialog', { widget: self }));
+            self.$element.html(db.web.qweb.render('TranslateDialog', { widget: self }));
             self.$element.tabs();
             if (!(self.view.translatable_fields && self.view.translatable_fields.length)) {
                 self.hide_tabs('fields');
@@ -724,11 +728,7 @@ openerp.web.TranslateDialog = openerp.web.Dialog.extend({
     }
 });
 
-/**
- * @class
- * @extends openerp.web.Widget
- */
-openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
+db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{
     set_default_options: function(options) {
         this.options = options || {};
         _.defaults(this.options, {
@@ -741,7 +741,7 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
     },
     open_translate_dialog: function(field) {
         if (!this.translate_dialog) {
-            this.translate_dialog = new openerp.web.TranslateDialog(this).start();
+            this.translate_dialog = new db.web.TranslateDialog(this).start();
         }
         this.translate_dialog.open(field);
     },
@@ -753,7 +753,7 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
      * @param {String} [action_data.special=null] special action handlers (currently: only ``'cancel'``)
      * @param {String} [action_data.type='workflow'] the action type, if present, one of ``'object'``, ``'action'`` or ``'workflow'``
      * @param {Object} [action_data.context=null] additional action context, to add to the current context
-     * @param {openerp.web.DataSet} dataset a dataset object used to communicate with the server
+     * @param {db.web.DataSet} dataset a dataset object used to communicate with the server
      * @param {Object} [record_id] the identifier of the object on which the action is to be applied
      * @param {Function} on_closed callback to execute when dialog is closed or when the action does not generate any result (no new action)
      */
@@ -772,14 +772,14 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
                     active_ids: [record_id || false],
                     active_model: dataset.model
                 });
-                action.context = new openerp.web.CompoundContext(dataset.get_context(), action.context);
+                action.context = new db.web.CompoundContext(dataset.get_context(), action.context);
                 self.do_action(action, result_handler);
             } else {
                 result_handler();
             }
         };
 
-        var context = new openerp.web.CompoundContext(dataset.get_context(), action_data.context || {});
+        var context = new db.web.CompoundContext(dataset.get_context(), action_data.context || {});
 
         if (action_data.special) {
             handler({result: {"type":"ir.actions.act_window_close"}});
@@ -794,7 +794,7 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
     /**
      * Directly set a view to use instead of calling fields_view_get. This method must
      * be called before start(). When an embedded view is set, underlying implementations
-     * of openerp.web.View must use the provided view instead of any other one.
+     * of db.web.View must use the provided view instead of any other one.
      *
      * @param embedded_view A view.
      */
@@ -841,7 +841,7 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
     },
     on_sidebar_manage_view: function() {
         if (this.fields_view && this.fields_view.arch) {
-            $('' + openerp.web.json_node_to_xml(this.fields_view.arch, true) + '').dialog({ width: '95%', height: 600});
+            $('' + db.web.json_node_to_xml(this.fields_view.arch, true) + '').dialog({ width: '95%', height: 600});
         } else {
             this.notification.warn("Manage Views", "Could not find current view declaration");
         }
@@ -855,7 +855,7 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
     on_sidebar_import: function() {
     },
     on_sidebar_export: function() {
-        var export_view = new openerp.web.DataExport(this, this.dataset);
+        var export_view = new db.web.DataExport(this, this.dataset);
         export_view.start();
     },
     on_sidebar_translate: function() {
@@ -865,12 +865,7 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
     }
 });
 
-/**
- * Registry for all the main views
- */
-openerp.web.views = new openerp.web.Registry();
-
-openerp.web.json_node_to_xml = function(node, single_quote, indent) {
+db.web.json_node_to_xml = function(node, single_quote, indent) {
     // For debugging purpose, this function will convert a json node back to xml
     // Maybe usefull for xml view editor
 
@@ -899,7 +894,7 @@ openerp.web.json_node_to_xml = function(node, single_quote, indent) {
         r += '>\n';
         var childs = [];
         for (var i = 0, ii = node.children.length; i < ii; i++) {
-            childs.push(openerp.web.json_node_to_xml(node.children[i], single_quote, indent + 1));
+            childs.push(db.web.json_node_to_xml(node.children[i], single_quote, indent + 1));
         }
         r += childs.join('\n');
         r += '\n' + sindent + '';

From b612f2563f04ce8a271522787b83641275afdfcd Mon Sep 17 00:00:00 2001
From: Launchpad Translations on behalf of openerp <>
Date: Thu, 15 Sep 2011 04:48:01 +0000
Subject: [PATCH 7/9] Launchpad automatic translations update.

bzr revid: launchpad_translations_on_behalf_of_openerp-20110915044801-ku4i0ixvpozhyaup
---
 addons/account_analytic_analysis/i18n/mk.po | 296 ++++++++++++++++++++
 addons/account_coda/i18n/sl.po              | 259 +++++++++++++++++
 addons/base_crypt/i18n/sl.po                |  84 ++++++
 addons/google_map/i18n/mk.po                |  53 ++++
 addons/html_view/i18n/mk.po                 |  63 +++++
 5 files changed, 755 insertions(+)
 create mode 100644 addons/account_analytic_analysis/i18n/mk.po
 create mode 100644 addons/account_coda/i18n/sl.po
 create mode 100644 addons/base_crypt/i18n/sl.po
 create mode 100644 addons/google_map/i18n/mk.po
 create mode 100644 addons/html_view/i18n/mk.po

diff --git a/addons/account_analytic_analysis/i18n/mk.po b/addons/account_analytic_analysis/i18n/mk.po
new file mode 100644
index 00000000000..81d5d115207
--- /dev/null
+++ b/addons/account_analytic_analysis/i18n/mk.po
@@ -0,0 +1,296 @@
+# Macedonian translation for openobject-addons
+# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2011-01-11 11:14+0000\n"
+"PO-Revision-Date: 2011-09-14 08:10+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: Macedonian \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2011-09-15 04:47+0000\n"
+"X-Generator: Launchpad (build 13921)\n"
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,hours_qtt_invoiced:0
+msgid ""
+"Number of hours that can be invoiced plus those that already have been "
+"invoiced."
+msgstr ""
+"Број на часови кои можат да бидат фактурирани, плус часови кои веќе се "
+"фактурирани."
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,remaining_ca:0
+msgid "Computed using the formula: Max Invoice Price - Invoiced Amount."
+msgstr ""
+"Пресметано според формулата: Максимална фактурирана цена - Фактурирана цена."
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,remaining_hours:0
+msgid "Computed using the formula: Maximum Quantity - Hours Tot."
+msgstr "Пресметано според формулата: Максимална количина - Вкупно часови"
+
+#. module: account_analytic_analysis
+#: code:addons/account_analytic_analysis/account_analytic_analysis.py:532
+#: code:addons/account_analytic_analysis/account_analytic_analysis.py:703
+#, python-format
+msgid "AccessError"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,last_invoice_date:0
+msgid "Date of the last invoice created for this analytic account."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: model:ir.module.module,description:account_analytic_analysis.module_meta_information
+msgid ""
+"\n"
+"This module is for modifying account analytic view to show\n"
+"important data to project manager of services companies.\n"
+"Adds menu to show relevant information to each manager..\n"
+"\n"
+"You can also view the report of account analytic summary\n"
+"user-wise as well as month wise.\n"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,last_invoice_date:0
+msgid "Last Invoice Date"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,theorical_margin:0
+msgid "Computed using the formula: Theorial Revenue - Total Costs"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,real_margin_rate:0
+msgid "Real Margin Rate (%)"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,ca_theorical:0
+msgid "Theoretical Revenue"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,last_worked_invoiced_date:0
+msgid ""
+"If invoice from the costs, this is the date of the latest work or cost that "
+"have been invoiced."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: model:ir.ui.menu,name:account_analytic_analysis.menu_invoicing
+msgid "Billing"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,last_worked_date:0
+msgid "Date of Last Cost/Work"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,total_cost:0
+msgid "Total Costs"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,hours_quantity:0
+msgid ""
+"Number of hours you spent on the analytic account (from timesheet). It "
+"computes on all journal of type 'general'."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,remaining_hours:0
+msgid "Remaining Hours"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,theorical_margin:0
+msgid "Theoretical Margin"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,ca_theorical:0
+msgid ""
+"Based on the costs you had on the project, what would have been the revenue "
+"if all these costs have been invoiced at the normal sale price provided by "
+"the pricelist."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,user_ids:0
+#: field:account_analytic_analysis.summary.user,user:0
+msgid "User"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,ca_to_invoice:0
+msgid "Uninvoiced Amount"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,real_margin:0
+msgid "Computed using the formula: Invoiced Amount - Total Costs."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,hours_qtt_non_invoiced:0
+msgid "Uninvoiced Hours"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,last_worked_date:0
+msgid "Date of the latest work done on this account."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: model:ir.module.module,shortdesc:account_analytic_analysis.module_meta_information
+msgid "report_account_analytic"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: model:ir.model,name:account_analytic_analysis.model_account_analytic_analysis_summary_user
+msgid "Hours Summary by User"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,ca_invoiced:0
+msgid "Invoiced Amount"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: code:addons/account_analytic_analysis/account_analytic_analysis.py:533
+#: code:addons/account_analytic_analysis/account_analytic_analysis.py:704
+#, python-format
+msgid "You try to bypass an access rule (Document type: %s)."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,last_worked_invoiced_date:0
+msgid "Date of Last Invoiced Cost"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,hours_qtt_invoiced:0
+msgid "Invoiced Hours"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,real_margin:0
+msgid "Real Margin"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: constraint:account.analytic.account:0
+msgid ""
+"Error! The currency has to be the same as the currency of the selected "
+"company"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,ca_invoiced:0
+msgid "Total customer invoiced amount for this account."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: model:ir.model,name:account_analytic_analysis.model_account_analytic_analysis_summary_month
+msgid "Hours summary by month"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,real_margin_rate:0
+msgid "Computes using the formula: (Real Margin / Total Costs) * 100."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,hours_qtt_non_invoiced:0
+msgid ""
+"Number of hours (from journal of type 'general') that can be invoiced if you "
+"invoice based on analytic account."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: view:account.analytic.account:0
+msgid "Analytic accounts"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,remaining_ca:0
+msgid "Remaining Revenue"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,ca_to_invoice:0
+msgid ""
+"If invoice from analytic account, the remaining amount you can invoice to "
+"the customer based on the total costs."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,revenue_per_hour:0
+msgid "Computed using the formula: Invoiced Amount / Hours Tot."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,revenue_per_hour:0
+msgid "Revenue per Hours (real)"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account_analytic_analysis.summary.month,unit_amount:0
+#: field:account_analytic_analysis.summary.user,unit_amount:0
+msgid "Total Time"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,month_ids:0
+#: field:account_analytic_analysis.summary.month,month:0
+msgid "Month"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account_analytic_analysis.summary.month,account_id:0
+#: field:account_analytic_analysis.summary.user,account_id:0
+#: model:ir.model,name:account_analytic_analysis.model_account_analytic_account
+msgid "Analytic Account"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_managed_overpassed
+#: model:ir.ui.menu,name:account_analytic_analysis.menu_action_account_analytic_managed_overpassed
+msgid "Overpassed Accounts"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: model:ir.actions.act_window,name:account_analytic_analysis.action_hr_tree_invoiced_all
+#: model:ir.ui.menu,name:account_analytic_analysis.menu_action_hr_tree_invoiced_all
+msgid "All Uninvoiced Entries"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: field:account.analytic.account,hours_quantity:0
+msgid "Hours Tot"
+msgstr ""
+
+#. module: account_analytic_analysis
+#: constraint:account.analytic.account:0
+msgid "Error! You can not create recursive analytic accounts."
+msgstr ""
+
+#. module: account_analytic_analysis
+#: help:account.analytic.account,total_cost:0
+msgid ""
+"Total of costs for this account. It includes real costs (from invoices) and "
+"indirect costs, like time spent on timesheets."
+msgstr ""
diff --git a/addons/account_coda/i18n/sl.po b/addons/account_coda/i18n/sl.po
new file mode 100644
index 00000000000..b2c7e144795
--- /dev/null
+++ b/addons/account_coda/i18n/sl.po
@@ -0,0 +1,259 @@
+# Slovenian translation for openobject-addons
+# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2011-01-11 11:14+0000\n"
+"PO-Revision-Date: 2011-09-14 11:29+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: Slovenian \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2011-09-15 04:47+0000\n"
+"X-Generator: Launchpad (build 13921)\n"
+
+#. module: account_coda
+#: help:account.coda,journal_id:0
+#: field:account.coda.import,journal_id:0
+msgid "Bank Journal"
+msgstr "Bančni dnevnik"
+
+#. module: account_coda
+#: view:account.coda:0
+#: field:account.coda.import,note:0
+msgid "Log"
+msgstr "Dnevnik"
+
+#. module: account_coda
+#: model:ir.model,name:account_coda.model_account_coda_import
+msgid "Account Coda Import"
+msgstr ""
+
+#. module: account_coda
+#: field:account.coda,name:0
+msgid "Coda file"
+msgstr ""
+
+#. module: account_coda
+#: view:account.coda:0
+msgid "Group By..."
+msgstr "Združi po ..."
+
+#. module: account_coda
+#: field:account.coda.import,awaiting_account:0
+msgid "Default Account for Unrecognized Movement"
+msgstr ""
+
+#. module: account_coda
+#: help:account.coda,date:0
+msgid "Import Date"
+msgstr "Datum uvoza"
+
+#. module: account_coda
+#: field:account.coda,note:0
+msgid "Import log"
+msgstr "Dnevnik uvoza"
+
+#. module: account_coda
+#: view:account.coda.import:0
+msgid "Import"
+msgstr "Uvozi"
+
+#. module: account_coda
+#: view:account.coda:0
+msgid "Coda import"
+msgstr ""
+
+#. module: account_coda
+#: code:addons/account_coda/account_coda.py:51
+#, python-format
+msgid "Coda file not found for bank statement !!"
+msgstr ""
+
+#. module: account_coda
+#: help:account.coda.import,awaiting_account:0
+msgid ""
+"Set here the default account that will be used, if the partner is found but "
+"does not have the bank account, or if he is domiciled"
+msgstr ""
+
+#. module: account_coda
+#: view:account.coda:0
+#: field:account.coda,company_id:0
+msgid "Company"
+msgstr "Podjetje"
+
+#. module: account_coda
+#: help:account.coda.import,def_payable:0
+msgid ""
+"Set here the payable account that will be used, by default, if the partner "
+"is not found"
+msgstr ""
+
+#. module: account_coda
+#: view:account.coda:0
+msgid "Search Coda"
+msgstr ""
+
+#. module: account_coda
+#: view:account.coda:0
+#: field:account.coda,user_id:0
+msgid "User"
+msgstr "Uporabnik"
+
+#. module: account_coda
+#: view:account.coda:0
+#: field:account.coda,date:0
+msgid "Date"
+msgstr "Datum"
+
+#. module: account_coda
+#: model:ir.ui.menu,name:account_coda.menu_account_coda_statement
+msgid "Coda Import Logs"
+msgstr ""
+
+#. module: account_coda
+#: model:ir.model,name:account_coda.model_account_coda
+msgid "coda for an Account"
+msgstr ""
+
+#. module: account_coda
+#: field:account.coda.import,def_payable:0
+msgid "Default Payable Account"
+msgstr ""
+
+#. module: account_coda
+#: help:account.coda,name:0
+msgid "Store the detail of bank statements"
+msgstr ""
+
+#. module: account_coda
+#: view:account.coda.import:0
+msgid "Cancel"
+msgstr "Prekliči"
+
+#. module: account_coda
+#: view:account.coda.import:0
+msgid "Open Statements"
+msgstr ""
+
+#. module: account_coda
+#: code:addons/account_coda/wizard/account_coda_import.py:167
+#, python-format
+msgid "The bank account %s is not defined for the partner %s.\n"
+msgstr ""
+
+#. module: account_coda
+#: model:ir.ui.menu,name:account_coda.menu_account_coda_import
+msgid "Import Coda Statements"
+msgstr ""
+
+#. module: account_coda
+#: view:account.coda.import:0
+#: model:ir.actions.act_window,name:account_coda.action_account_coda_import
+msgid "Import Coda Statement"
+msgstr ""
+
+#. module: account_coda
+#: model:ir.module.module,description:account_coda.module_meta_information
+msgid ""
+"\n"
+"    Module provides functionality to import\n"
+"    bank statements from coda files.\n"
+"    "
+msgstr ""
+
+#. module: account_coda
+#: view:account.coda:0
+msgid "Statements"
+msgstr "Izpiski"
+
+#. module: account_coda
+#: field:account.bank.statement,coda_id:0
+msgid "Coda"
+msgstr ""
+
+#. module: account_coda
+#: view:account.coda.import:0
+msgid "Results :"
+msgstr "Rezultat"
+
+#. module: account_coda
+#: view:account.coda.import:0
+msgid "Result of Imported Coda Statements"
+msgstr ""
+
+#. module: account_coda
+#: help:account.coda.import,def_receivable:0
+msgid ""
+"Set here the receivable account that will be used, by default, if the "
+"partner is not found"
+msgstr ""
+
+#. module: account_coda
+#: field:account.coda.import,coda:0
+#: model:ir.actions.act_window,name:account_coda.act_account_payment_account_bank_statement
+msgid "Coda File"
+msgstr ""
+
+#. module: account_coda
+#: model:ir.model,name:account_coda.model_account_bank_statement
+msgid "Bank Statement"
+msgstr "Bančni izpisek"
+
+#. module: account_coda
+#: model:ir.actions.act_window,name:account_coda.action_account_coda
+msgid "Coda Logs"
+msgstr ""
+
+#. module: account_coda
+#: code:addons/account_coda/wizard/account_coda_import.py:311
+#, python-format
+msgid "Result"
+msgstr "Rezultat"
+
+#. module: account_coda
+#: view:account.coda.import:0
+msgid "Click on 'New' to select your file :"
+msgstr "Kliknite na \"Novo\" za izbiro vaše datoteke:"
+
+#. module: account_coda
+#: field:account.coda.import,def_receivable:0
+msgid "Default Receivable Account"
+msgstr ""
+
+#. module: account_coda
+#: view:account.coda.import:0
+msgid "Close"
+msgstr "Zapri"
+
+#. module: account_coda
+#: field:account.coda,statement_ids:0
+msgid "Generated Bank Statements"
+msgstr "Generirani bačni izpiski"
+
+#. module: account_coda
+#: model:ir.module.module,shortdesc:account_coda.module_meta_information
+msgid "Account CODA - import bank statements from coda file"
+msgstr ""
+
+#. module: account_coda
+#: view:account.coda.import:0
+msgid "Configure Your Journal and Account :"
+msgstr ""
+
+#. module: account_coda
+#: view:account.coda:0
+msgid "Coda Import"
+msgstr ""
+
+#. module: account_coda
+#: view:account.coda:0
+#: field:account.coda,journal_id:0
+msgid "Journal"
+msgstr "Dnevnik"
diff --git a/addons/base_crypt/i18n/sl.po b/addons/base_crypt/i18n/sl.po
new file mode 100644
index 00000000000..d52c5723ba9
--- /dev/null
+++ b/addons/base_crypt/i18n/sl.po
@@ -0,0 +1,84 @@
+# Slovenian translation for openobject-addons
+# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2011-01-11 11:14+0000\n"
+"PO-Revision-Date: 2011-09-14 11:36+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: Slovenian \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2011-09-15 04:48+0000\n"
+"X-Generator: Launchpad (build 13921)\n"
+
+#. module: base_crypt
+#: sql_constraint:res.users:0
+msgid "You can not have two users with the same login !"
+msgstr "Ne morete imeti dva uporabnika z istim prijavnim imenom!"
+
+#. module: base_crypt
+#: model:ir.model,name:base_crypt.model_res_users
+msgid "res.users"
+msgstr "res.users"
+
+#. module: base_crypt
+#: constraint:res.users:0
+msgid "The chosen company is not in the allowed companies for this user"
+msgstr "Izbrano podjetje ni v dovoljenih podjetjih za tega uporabnika"
+
+#. module: base_crypt
+#: code:addons/base_crypt/crypt.py:132
+#, python-format
+msgid "Please specify the password !"
+msgstr "Prosim, navedite geslo !"
+
+#. module: base_crypt
+#: model:ir.module.module,shortdesc:base_crypt.module_meta_information
+msgid "Base - Password Encryption"
+msgstr "Osnovno - enkripcija gesla"
+
+#. module: base_crypt
+#: code:addons/base_crypt/crypt.py:132
+#, python-format
+msgid "Error"
+msgstr "Napaka"
+
+#. module: base_crypt
+#: model:ir.module.module,description:base_crypt.module_meta_information
+msgid ""
+"This module replaces the cleartext password in the database with a password "
+"hash,\n"
+"preventing anyone from reading the original password.\n"
+"For your existing user base, the removal of the cleartext passwords occurs "
+"the first time\n"
+"a user logs into the database, after installing base_crypt.\n"
+"After installing this module it won't be possible to recover a forgotten "
+"password for your\n"
+"users, the only solution is for an admin to set a new password.\n"
+"\n"
+"Note: installing this module does not mean you can ignore basic security "
+"measures,\n"
+"as the password is still transmitted unencrypted on the network (by the "
+"client),\n"
+"unless you are using a secure protocol such as XML-RPCS.\n"
+"                    "
+msgstr ""
+"Ta modul nadomešča obliko besedilnega geslo v bazi podatkov z hash geslom,\n"
+"ki preprečuje komurkoli branje izvirnega gesla.\n"
+"Za vašo obstoječo bazo uporabnikov, odstranitev gesla v obliki besedila se "
+"pojavi pri\n"
+"prvi prijavi uporabnika v bazo podatkov, po namestitvi base_crypt.\n"
+"Po namestitvi tega modula ne bo mogoče obnoviti pozabiljenega gesla za vaše\n"
+"uporabnike, edina rešitev je, da admin nastavi novo geslo.\n"
+"\n"
+"Opomba: namestitev tega modula ne pomeni ignoriranja osnovnih varnostnih "
+"ukrepov,\n"
+"ker se geslo še vedno prenaša nešifrirano v omrežju (preko klienta),\n"
+"razen če ne uporabljate varni protokol kot je XML-RPCS.\n"
+"                    "
diff --git a/addons/google_map/i18n/mk.po b/addons/google_map/i18n/mk.po
new file mode 100644
index 00000000000..5835b35357f
--- /dev/null
+++ b/addons/google_map/i18n/mk.po
@@ -0,0 +1,53 @@
+# Macedonian translation for openobject-addons
+# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2011-01-11 11:15+0000\n"
+"PO-Revision-Date: 2011-09-14 08:11+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: Macedonian \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2011-09-15 04:47+0000\n"
+"X-Generator: Launchpad (build 13921)\n"
+
+#. module: google_map
+#: view:res.partner:0
+#: view:res.partner.address:0
+msgid "Map"
+msgstr "Мапа"
+
+#. module: google_map
+#: view:res.partner:0
+#: view:res.partner.address:0
+msgid "Street2 : "
+msgstr ""
+
+#. module: google_map
+#: model:ir.actions.wizard,name:google_map.wizard_google_map
+msgid "Launch Google Map"
+msgstr "Стартувај Google Map"
+
+#. module: google_map
+#: model:ir.module.module,description:google_map.module_meta_information
+msgid ""
+"The module adds google map field in partner address\n"
+"so that we can directly open google map from the\n"
+"url widget."
+msgstr ""
+
+#. module: google_map
+#: model:ir.module.module,shortdesc:google_map.module_meta_information
+msgid "Google Map"
+msgstr ""
+
+#. module: google_map
+#: model:ir.model,name:google_map.model_res_partner_address
+msgid "Partner Addresses"
+msgstr "Адреса на партнерот"
diff --git a/addons/html_view/i18n/mk.po b/addons/html_view/i18n/mk.po
new file mode 100644
index 00000000000..dd98a0f9818
--- /dev/null
+++ b/addons/html_view/i18n/mk.po
@@ -0,0 +1,63 @@
+# Macedonian translation for openobject-addons
+# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2011-01-11 11:15+0000\n"
+"PO-Revision-Date: 2011-09-14 08:15+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: Macedonian \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2011-09-15 04:47+0000\n"
+"X-Generator: Launchpad (build 13921)\n"
+
+#. module: html_view
+#: field:html.view,name:0
+msgid "Name"
+msgstr "Име"
+
+#. module: html_view
+#: field:html.view,comp_id:0
+msgid "Company"
+msgstr "Компанија"
+
+#. module: html_view
+#: model:ir.actions.act_window,name:html_view.action_html_view_form
+#: model:ir.ui.menu,name:html_view.html_form
+msgid "Html Test"
+msgstr "Html тест"
+
+#. module: html_view
+#: view:html.view:0
+msgid "Html Example"
+msgstr "Html пример"
+
+#. module: html_view
+#: model:ir.module.module,shortdesc:html_view.module_meta_information
+msgid "Html View"
+msgstr "Html преглед"
+
+#. module: html_view
+#: field:html.view,bank_ids:0
+msgid "Banks"
+msgstr "Банки"
+
+#. module: html_view
+#: model:ir.module.module,description:html_view.module_meta_information
+msgid ""
+"\n"
+"    This is the test module which shows html tag supports in normal xml form "
+"view.\n"
+"    "
+msgstr ""
+
+#. module: html_view
+#: model:ir.model,name:html_view.model_html_view
+msgid "html.view"
+msgstr "html.view"

From 6af24261ba6450ea2e8ce51e5d3550821fc44fd8 Mon Sep 17 00:00:00 2001
From: Fabien Meghazi 
Date: Thu, 15 Sep 2011 10:12:41 +0200
Subject: [PATCH 8/9] [ADD] Added duplicate feature to FormView

bzr revid: fme@openerp.com-20110915081241-3q4us9bweru4iyx1
---
 addons/web/static/src/js/view_form.js | 15 +++++++++++++++
 addons/web/static/src/xml/base.xml    |  1 +
 2 files changed, 16 insertions(+)

diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index b097fc6abf0..a2188d736fd 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -89,6 +89,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
         this.$form_header.find('button.oe_form_button_save_edit').click(this.do_save_edit);
         this.$form_header.find('button.oe_form_button_cancel').click(this.do_cancel);
         this.$form_header.find('button.oe_form_button_new').click(this.on_button_new);
+        this.$form_header.find('button.oe_form_button_duplicate').click(this.on_button_duplicate);
 
         if (this.options.sidebar && this.options.sidebar_id) {
             this.sidebar = new openerp.web.Sidebar(this, this.options.sidebar_id);
@@ -307,6 +308,20 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
         });
         return def.promise();
     },
+    on_button_duplicate: function() {
+        var self = this;
+        var def = $.Deferred();
+        $.when(this.has_been_loaded).then(function() {
+            if (self.can_be_discarded()) {
+                self.dataset.call('copy', [self.datarecord.id, {}, self.dataset.context]).then(function(new_id) {
+                    return self.on_created({ result : new_id });
+                }).then(function() {
+                    def.resolve();
+                });
+            }
+        });
+        return def.promise();
+    },
     can_be_discarded: function() {
         return !this.dirty_for_user || confirm(_t("Warning, the record has been modified, your changes will be discarded."));
     },
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 422ecca5760..83ca819b4e6 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -661,6 +661,7 @@
             
             
             
+            
         
         
From 81e6707b916deb767df9cba285eb08aaeafa7365 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 15 Sep 2011 10:46:26 +0200 Subject: [PATCH 9/9] [IMP] make filtergroups [OR] their component filters instead of [AND]-ing them bzr revid: xmo@openerp.com-20110915084626-9rxv8jv65uxtq9ga --- addons/web/static/src/js/search.js | 78 ++++++++++++++++++------------ 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index f6c53b4ad17..681f2fe2f4b 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -463,30 +463,6 @@ openerp.web.search.Widget = openerp.web.Widget.extend( /** @lends openerp.web.se })); } }); -openerp.web.search.FilterGroup = openerp.web.search.Widget.extend(/** @lends openerp.web.search.FilterGroup# */{ - template: 'SearchView.filters', - /** - * Inclusive group of filters, creates a continuous "button" with clickable - * sections (the normal display for filters is to be a self-contained button) - * - * @constructs openerp.web.search.FilterGroup - * @extends openerp.web.search.Widget - * - * @param {Array} filters elements of the group - * @param {openerp.web.SearchView} view view in which the filters are contained - */ - init: function (filters, view) { - this._super(view); - this.filters = filters; - this.length = filters.length; - }, - start: function () { - this._super(); - _.each(this.filters, function (filter) { - filter.start(); - }); - } -}); openerp.web.search.add_expand_listener = function($root) { $root.find('a.searchview_group_string').click(function (e) { $root.toggleClass('folded expanded'); @@ -533,6 +509,49 @@ openerp.web.search.Input = openerp.web.search.Widget.extend( /** @lends openerp. "get_domain not implemented for widget " + this.attrs.type); } }); +openerp.web.search.FilterGroup = openerp.web.search.Input.extend(/** @lends openerp.web.search.FilterGroup# */{ + template: 'SearchView.filters', + /** + * Inclusive group of filters, creates a continuous "button" with clickable + * sections (the normal display for filters is to be a self-contained button) + * + * @constructs openerp.web.search.FilterGroup + * @extends openerp.web.search.Input + * + * @param {Array} filters elements of the group + * @param {openerp.web.SearchView} view view in which the filters are contained + */ + init: function (filters, view) { + this._super(view); + this.filters = filters; + this.length = filters.length; + }, + start: function () { + this._super(); + _.each(this.filters, function (filter) { + filter.start(); + }); + }, + get_context: function () { }, + /** + * Handles domains-fetching for all the filters within it: groups them. + */ + get_domain: function () { + var domains = _(this.filters).chain() + .filter(function (filter) { return filter.is_enabled(); }) + .map(function (filter) { return filter.attrs.domain; }) + .value(); + + if (!domains.length) { return; } + if (domains.length === 1) { return domains[0]; } + for (var i=domains.length; --i;) { + domains.unshift(['|']); + } + return _.extend(new openerp.web.CompoundDomain(), { + __domains: domains + }); + } +}); openerp.web.search.Filter = openerp.web.search.Input.extend(/** @lends openerp.web.search.Filter# */{ template: 'SearchView.filter', /** @@ -586,12 +605,11 @@ openerp.web.search.Filter = openerp.web.search.Input.extend(/** @lends openerp.w } return this.attrs.context; }, - get_domain: function () { - if (!this.is_enabled()) { - return; - } - return this.attrs.domain; - } + /** + * Does not return anything: filter domain is handled at the FilterGroup + * level + */ + get_domain: function () { } }); openerp.web.search.Field = openerp.web.search.Input.extend( /** @lends openerp.web.search.Field# */ { template: 'SearchView.field',